Vue2入门学习笔记

Vue2入门必备!

⭐关注我查看更多配套笔记

学习视频:https://www.bilibili.com/video/BV1Zy4y1K7SH/

【尚硅谷Vue全家桶】

本博客是对该视频内容的整理以及加入自己的理解 想全面学习的推荐大家去看原视频

1.Vue脚手架基础

官方提供的 Vue 官方 标准开发工具

官方文档:https://cli.vuejs.org/zh/

Vue CLI(command line interface)脚手架

0.配置淘宝镜像 不然会很慢 甚至安装失败

npm config set registry https://registry.npm.taobao.org

1.全局安装@vue/cli

npm install -g @vue/cli

2.切换到对应目录 创建脚手架

vue create vue_projectone

输入后会选择 使用Vue的版本 2/3/自定义

bable : ES6 语法转换为 ES5

eslint : 语法检查工具 检查代码是否合理

选择好之后输入回车

进行如下操作

  • cd 项目名
  • npm run serve

之后后开始编译代码

停止终端运行 ctrl + c 连续按两次 y/n 输入什么都会关闭

脚手架结构讲解

src

  • main.js 整个项目的入口文件
  • App.vue
  • .gitignore git 忽略上传git文件的 配置
  • babel.config.js babel的配置文件
  • package.json npm包配置文件
    • serve 代码执行后直接运行 man.js
    • build 构建 css js html
    • lint 进行语法检查
  • package-lock.json 包版本控制文件
  • README.md 教程

app.vue

image-20220409160558455

app.vue内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>

<script>
// 导入vue
import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'App',
components: {
HelloWorld
}
}
</script>

<style>
/*写样式*/
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

public => index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<!-- 针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 开启移动端的理想视口 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- 引入 favicon.ico <%= BASE_URL %> 代表“./”底层有处理-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!--会将 package.json 中的内容当作标题 webpack相关内容 -->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!--当浏览器不支持js时 noscript会渲染noscript的标签-->
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<!--容器-->
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

分析render函数

引入的是残缺的Vue 不含模板解析器

需要自己使用render #省体积 省空间

或者自己引入完整版vue

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
// h 官方说法是 createElement 是一个函数
// createElement("h1","你好啊") 生成<h1>你好啊</h1>
// 传入 组件 为渲染组件
render: h => h(App),
}).$mount('#app')
1
2
3
4
5
6
7
/*
关于不同版本的Vue:
1.vue.js 与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement的数去指定具体内容。
*/

2.脚手架配置

Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpakc配置,请执

vue inspect > output.js

// 仅仅是输出让你看的文件 在这里更改是无效的

如何自行配置?

配置参考 | Vue CLI (vuejs.org)

在 package.json 同级目录下创建 vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Commonjs 的暴露
// node.js 使用的 commonjs的暴露 不能用ES6
module.exports = {
pages: {
index: {
// page 的入口
entry: 'src/index/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Index Page',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
// 当使用只有入口的字符串格式时,
// 模板会被推导为 `public/subpage.html`
// 并且如果找不到的话,就回退到 `public/index.html`。
// 输出文件名会被推导为 `subpage.html`。
subpage: 'src/subpage/main.js'
}
}

关闭语法检查

1
lintOnSave:false //与page平级

3.ref属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<h1 ref="title">H1标签</h1>
<School ref="sc">H1标签</School> 组件标签使用
<script>
// vuecomponent 对象属性
console.log(this.$refs.title) // 获取真实dom
// 可在此处操作DOM
console.log(this.$refs.sc) // 获得vc对象
</script>
<!--

1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在htm1标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3.使用方式:
打标识:<h1 ref="xxx ">.....</h1>或<School ref="xxx"></School>
获取: this.$refs.xxx
-->

4.props配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
<!-- 传入data参数 -->
<Student name="李四" sex="女" age="18"/>
</div>
</template>

<template>
<div>
<!-- age不绑定为字符串 无法使用数字计算
可以使用绑定 -->
<Student name="李四" sex="女" :age="18"/>
</div>
</template>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
export default {
// 加入此项配置项 接收数据
props:['name','age','sex'],
// 第二种写法 限制类型
props:{
name:String,
age:Number,
sex:String,
}
// 第三种写法
props:{
name:{
type:String, // 指定类型
required:true, // 是否为必须的参数
default:"王二", // 不传参默认为该值
}
}
}

// props 中接收的数据无法更改 会报错
// 强行更改方法

new Vue({
props:['name','age','sex'],
data(){
return {
myAge = this.age;
}
}
// 修改 myAge 代替 age
// props 优先级更高 会优先展示
})
// props 不能传入 vue 已经使用的属性
// ref key ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## 配置项props
功能:让组件接收外部传过来的数据
(1).传递数据:
<Demo name="xxx"/>
(2).接收数据:
第一种方式(只接收)∶
props:["name"]
第二种方式(限制类型):
props:{
name: Number
}
第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String, // 指定类型
required:true, // 是否为必须的参数
default:"王二", // 不传参默认为该值
}
}

备注: props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,
若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。

5.mixin(混入)

mixin.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//两个组件共同使用相同的配置
export const mixin = {
methods:{
alert(this.name);
}
}

export const mixin = {
data(){
return {
x:200,
y:200,
}
}
}

vue中的script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 引入一个混合组件
import {mixin} from "../mixin";
export default {
name:"School",
// 复用配置
mixins:[minxin,mixin2],
// 数据重复
// 不破坏原有数据 将现有数据与原有数据整合 如果重复现有数据优先级更高
data(){
return{
x:300,
y:200,
}
},
// 生命周期 mounted 等挂载函数 混入会执行相同两段代码
// 来者不拒 均会执行
mounted(){
console.log("多次重复执行");
}
}


// 全局混合
// main.js 中
import {mixin} from "../mixin";
// vm 与 vc 均会执行该函数
Vue.mixin(mixin);

6.插件

聚合代码 书写全局配置

在 src 添加 plugs.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default {
// 该参数 为 Vue的构造函数
install(Vue,x,y,z){
// 全局过滤器
Vue.filter("mySlice",fuction(value){});
// 全局指令
Vue.directive("fbind",{});
// 定义混入
Vue.mixin({});

// 给Vue原型添加方法 vm 与 vc 均能使用
Vue.prototype.hello = ()=>{alert("你好啊")};
}
}

main.js

1
2
3
4
5
6
7
8
// 引入插件 
import plugs from "../plugs.js"
// 在声明 vm 之前开启插件
// 能接收多个 参数 但是第一个必须是插件名 install的第一个参数必须为 Vue
Vue.use(plugs,1,2,3)

// 全局声明之后 可在 全部 vm vc 中使用

7.scoped样式 / less 编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style scoped>
/* 加入scoped之后 各个css之间相互独立 不互相影响 */
/* 一般app组件中 不会使用scoped */
/* 使css样式局部生效 */
</style>

<style lang="less">
/* 支持使用less */
/* 需要安装包 less-loader */
/* 需要考虑兼容性问题 */
/* 安装对应版本的 less-loader 不然会报错 */
</style>


<style lang="css">
</style>

8.给兄弟组件传参

1.传给父元素 (props传给父元素一个方法)

2.由父元素传给子元素的兄弟元素

(9. 中含其他方法 使用ref与自定义事件 与mounted)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<School :receive="receive"></School>
</template>


<script>
export default{
name:"Compents",
methods:{
receive(x){
console.log('我是app组件我收到了数据',x)
}
}
}
</script>

School.vue

1
2
3
4
5
6
7
8
9
10
11
<script>
export default{
name:"School",
props:["receive"],
method:{
add(x){
receive(x);
// 可在子元素调用父元素的方法
}
}
</script>

9.组件的自定义事件

1.js内置事件 click keyup 等

2.自定义事件

app.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<Student v-on:atguigu="getStudentName"></Student>
<Student ref="studnet"></Student>
</template>
<script>
{
// 挂载mounted 子传父
mounted(){
// $on 当atguigu事件触发的时候
this.$refs.student.$on('atguigu',this.getStudentName)
},
methods:{
getStudentName(name){
console.log("获得name数据")
}
}
}
</script>

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<h1 @click="ad"></h1>
</template>

<script>
{
// props:['getStudentName'],
// 触发事件 子传父
methods:{
ad(){
// 触发事件 使用方法 $emit
this.$emit('atguigu',this.name)
},
}
}
</script>

10.解除绑定自定义事件

Student.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<h1 @click="unBind"></h1>
</template>

<script>
{
methods:{
unBind(){
// 触发事件 使用方法 $emit
this.$emit('atguigu',this.name)
// 解绑单个自定义事件
this.$off('atguigu')
// 解绑多个自定义事件
// 传入数组
this.$off(['atguigu','...','...'])
// 解绑全部自定义事件
this.$off()
// 摧毁 vc实例 自定义事件解绑(全部失效)
this.$destroy()
},
}
}
</script>

11.全局事件总线

设计一个不在任何组件内的组件 作为全部事件的中转站

A中触发自定义事件 中转X 触发C的操作

1
2
3
4
5
// 条件

//在所有组件都能访问的地方添加 数据对象

// 可以使用 $on $off $emit

1.windows 2.VueCompents(需要改原型)

使用 Vue 在main.js中操作

VueCompent对象的____proto____指向Vue的原型对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 在main.js 中添加 'X' 傀儡 作为 vm / vc 可以使用 $on $emit $off
// 则傀儡必须为 Vue 实例 vm

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
el:"app",
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this; //全局事件总线
}
}).$mount('#app')


// 在其他 vc 中使用全局事件总线
{
methods:{
unBind(){
// 触发事件 使用方法 $emit
this.$bus.$emit('atguigu',this.name)

// 解绑全部自定义事件
this.$bus.$off()
// 摧毁 全局事件总线 vm 实例 自定义事件解绑(全部失效)
this.$bus.$destroy()
},
},
beforDestroy(){
// 在在被摧毁之前解绑该组件 在总线中的事件
// 解绑单个自定义事件
this.$bus.$off('atguigu')
// 解绑多个自定义事件
// 传入数组
this.$bus.$off(['atguigu','...','...'])
}
}

image-20220418175658554

12.消息订阅与发布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
消息订阅与发布
1.订阅消息︰消息名
2.发布消息︰消息内容
*/

// 需要使用 消息订阅与发布的库
// 在各种框架里都能使用 不局限于 vue
// 有多种库存在 消息订阅与发布是一种理念
// 这里推荐 : pubsub-js

// 类似于 $bus

// 订阅消息
import pubsub from 'pubsub-js'
// 在mounted中订阅
// 需要设置id // 非vue管理必须使用箭头函数!!
const this.pubid = pubsub.subscribe("消息名",fuction(msgName,data){
// msgName 为消息名
// data 为之后的传递的参数
})
// 或者传入 在 methods 中配置的方法 this 不会出问题
const this.pubid = pubsub.subscribe("消息名",this.method);

// 在销毁前取消丁订阅 beforDistory
pubsub.unsubscribe(this.pubid);

// 发布消息
pubsub.publish('hello',666);

13.$nextTick

在DOM节点 下一次更新之后 执行回调函数

1
2
3
4
5
this.$nextTick(()=>{
this.$refs.editInput.forEach((element)=>{
element.focus();
})
)}