# Vue学习
**Repository Path**: zq084/vue-learning
## Basic Information
- **Project Name**: Vue学习
- **Description**: vue学习内容。。。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-09-13
- **Last Updated**: 2022-09-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Vue及复习
## day01
### 1.0 Vue引入
```vue
```
### 2.0 Vue 语法
```vue
```
### 3.0 什么是MVVM模型
```vue
MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,视图数据层,V与M连接的桥梁,也可以看作为控制器)
M : 数据模型:负责业务数据
v :视图相关,展示Model层的数据;
VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点
ViewModel是Vue.js的核心,它是一个Vue实例,MVVM支持双向绑定,意思就是当M层数据进行修改时,VM层会监测到变化,并且通知V层进行相应的修改,反之修改V层则会通知M层数据进行修改
```
### 4.0 $mount
```
// $mount 可延迟挂载,效率无区别
setTimeout(()=>{
vm.$mount ("#app");
},2000)
```
### 5.0 data 为什么写成函数形式
```vue
Document
```
### 6.0 V-bind 强制绑定
```vue
```
### 7.0 水平垂直居中方式
```vue
```
### 8.0 与或 返回值
```javascript
// 逻辑运算符
/*
|| 或
(1)如果两边都为数字,或字符串数字,则返回左边的
(2)如果左边的值布尔转换后为【true】,那么返回左边的值
(3)如果左边的值布尔转换后为【false】,那么返回右边的值(不管右边的值是真还是假)。
*/
console.log("1"||"str"); // 1
console.log(NaN||undefined); // undefined
console.log(0 || 1); // 1
/*
&& 与
(1)如果两边都为数字,或字符串数字,则返回右边的
(2)如果左边的值为 【true】,不管右边的值是(真)是(假)都返回右边的
(3)如果左边的值为 【false】,则都返回左边的,那么返回左边的值,但是当逻辑与的左边为 null/NaN/undefined ,结果就会得到null/NaN/undefined
*/
console.log(null && 1); // null
console.log(undefined && 1); // undefined
console.log(NaN && 1); // NaN
console.log(NaN && undefined) // NaN
console.log(1 && 0); // 0
```
### 9.0 truthy(真值)和falsy(虚值)
```javascript
// & 左为true 返回 右边的
// truthy(真值)指的是在布尔值上下文中,转换后的值为 true 的值。被定义为假值以外的任何值都为真 值。(即所有除 false、0、-0、0n、""、null、undefined 和 NaN 以外的皆为真值)
console.log(true && "str"); // str
// falsy 值(虚值)是在 Boolean 上下文中认定为 false 的值。
// false、0、-0、0n、""、null、undefined 和 NaN
```
## day02
### 1.0 v-bind
批量传递,直接把需要展开传递给模板属性的对象 交给v-bind属性即可
```vue
{{msg}}
data(){
return {
msg:'hello',
prop: {
name:'zhangsan',
age:20,
sex:"nan"
}
}
}
```
### 2.0 v-bind强制绑定class
```css
.one {
width: 100px;
height: 100px;
background-color: yellow;
}
.two {
width: 100px;
height: 100px;
background-color: hotpink;
}
.three {
width: 100px;
height: 100px;
background-color: red;
}
.active {
color: skyblue;
}
```
- 字符串:只有一个类的时候,可以使用
```vue
.two {
width: 100px;
height: 100px;
background-color: hotpink;
}
data(){
return {
className:"two"
}
}
```
- 对象:有一个或者或者多个类,并且已经确定了类的数量,可以使用
```vue
AAAA
AAAA
data() {
return {
className: {
one:true,
two:false,
three:false,
},
isActive:true
}
}
```
- 数组:一个或者多个类,但是不确定数量,因为我们可以对数组进行增删改查
```vue
data() {
return {
className:["one", "two", "three"],
}
}
```
### 3.0 v-bind强制绑定style
- 对象:常用,把样式以键值对的形式书写在对象中
```vue
AAAA
BBBB
data() {
return {
boxStyle: {
color: "pink",
fontSize: "40px",
fontWeight: "bold",
}
}
}
```
- 数组:把多个style对象可以组合在数组中
```
AAAA
BBBB
data() {
return {
style1: { color: "red" },
style2: { fontSize: "80px" },
style3: { fontStyle: "italic" },
style4: { textShadow: "1px 1px 2px green" },
}
}
```
### 4.0 v-on注意:
- 事件函数书写位置在methods配置中,绑定事件可以简写为@
获取事件对象:
- !!!在v-on的插值语法区域就已经存在一个$event代表事件对象
- 如果绑定事件函数没有加括号,则默认传入
- 如果绑定事件函数加了括号,则需要我们显示传入
```
因为我们不需要直接操作DOM,所以事件回调函数的this不需要指向事件源
需要控制数据,数据在Vue实例vm身上,所以事件的this都是指向vm的
```
```
```
```
{{count}}
data() {
return {
count:0
};
},
methods:{
fn(){
console.log(this);
}
}
```
### 5.0 v-on的事件修饰符
```
.stop 阻止当前事件的传播
如果要阻止捕获,在最外层元素上书写
如果要阻止冒泡,在最内层元素上书写
.prevent 阻止当前事件的默认行为
.once 当前事件只能触发一次
.capture 控制当前事件在捕获阶段触发(如果不写,默认都是在冒泡阶段触发)
.self 控制只有在当前绑定事件的元素上发生事件,才能触发事件
.按键别名
```
### 6.0 获取input内容
```vue
输入框1:
输入框2:
{{msg}}
data() {
return {
msg: ""
};
},
methods: {
changeMsg(e) {
this.msg = e.target.value
}
}
```
### 7.0 v-model
- 作用:数据双向绑定
```vue
```
- 本质:给标签的value进行强制绑定,然后再绑定一个input事件,触发数据的改变
- 修饰符:.lazy .number .trim
```vue
lazy测试:
{{msg1}}
number测试:
{{msg2}}
trim测试:
{{msg3}}
```
### 8.0 v-model收集数据
- 复选框单独使用:使用布尔值收集
- 复选框多个使用:使用数组收集所有选中的value值
- 单选框的使用:使用字符串收集
- textarea:使用字符串收集
select的使用
- 单选:字符串收集
- 多选(mutiple):数组收集
### 9.0 DOM事件模型(3种)
- 基本事件模型(DOM0事件模型):使用率最高的on+事件类型绑定
- DOM事件模型(DOM2事件模型):在W3C指定的DOM2级规范中提出,使用方式的addEventListener()
- IE事件模型(只能在IE中使用):attachEvent()
- 网景事件模型(只能在网景浏览器中使用):淘汰
### 10.0 DOM事件流(事件机制)
- 事件流就是多个节点对象对同一种事件进行响应的先后顺序
- 捕获阶段:事件从最不确定的目标(document对象)开始触发,然后到最特定的目标(target)
- 目标:注册在目标节点上的事件被执行
- 冒泡阶段:事件从最特定的目标(target)向最不特定的目标(document对象)触发
### 11.0 阻止传播和阻止默认事件
- 阻止传播:e.stopPropagation() || e.cancelBubble = true
- 阻止默认事件:e.preventDefault() || e.returnValue = false
- trim方法 trimStart方法 trimEnd方法
## day03
### 1.0 条件渲染
- v-if \\ v-else-if \v-else
- 模板在编译的时候,就忽略了不符合条件的模板,所以不满足条件的模板压根都没渲染在视图中
注意:
- v-if的三个指令必须连着使用,中间不能间隔其他元素
- 如果有多个碎片节点需要条件渲染,我们可以使用template元素(在渲染后是不可见的)
- 如果在条件切换时,视图也会跟着切换,因为有diff算法默认比较,所以可能会出现复用元素的情况,如果不想复用,则给不想复用的元素添加key属性
v-show条件渲染
- 不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。
- v-show 不支持 元素,也不支持 v-else
- v-show在切换过程中也不需要考虑元素复用的情况,因为节点都已经渲染,没有diff算法比较,所有不会出现复用的情况
v-if和v-show的区别
- v-if和v-show都是用来做条件渲染的
- v-if 是“真正”的条件渲染,因为它会确保在切换过程中组件或者节点销毁和重建。
- v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
- 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
- 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
```vue
AAA
BBB
CCC
data() {
return {
isLoad: true,
type: 1
}
}
```
### 2.0 列表渲染
v-for
- 可以遍历数组\\对象\\字符串\\数字
- 需要书写一个key属性
```vue
- {{item.content}}
- {{key}}--{{value}}
- {{item}}--{{index}}
- {{item}}--{{index}} -- 页码:{{item}}
data() {
return {
obj:[
{ id:1,content:'AAA'},
{ id:2,content:'BBB'}
],
person:{
name:"zhangsan",
age:11,
sex:"nan"
},
str:"lisi",
number:10
}
}
```
### 3.0 其他指令
- v-html:更新元素的 innerHTML
- v-text:更新元素的 textContent
- v-once:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能
- v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始 插值 标签。跳过大量没有指令的节点会加快编译
- v-cloak:这个指令保持在元素上直到关联实例结束编译,我们通常可以使用选择器选择这个属性,然后再编译前对当前元素进行一些样式操作
- 修改响应式数据
* 基本类型:直接修改即可
* 数组类型:
+ 使用变更方法修改数组
+ 使用非变更方法得到一个新的值,重新赋值
* 对象类型:
+ 正常的设置可以是响应式的
+ 新增属性需要使用 Vue.set() 或者 vm.$set()
+ 删除属性需要使用 Vue.delete() 或者 vm.$delete()
### 4.0 计算属性(computed)
- 优点:计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值
- 计算属性vs方法:方法只要调用就会重新求值
- 计算属性vs插值语法中书写逻辑:臃肿,不方便识别是什么功能
- 计算属性可以设置getter和setter函数,进行可读可写操作
### 5.0 watch(侦听器)
- 作用:监听一个data数据或者一个计算属性值的改变,他只负责监听,后续操作由业务逻辑决定
- watch可以设置立即监听(immediate)
- watch可以设置深度监听(deep)
- watch的回调函数接受两个参数(newValue,oldValue),但是如果监听的是对象,则新值和旧值是一样的
### 6.0 watch和computed的对比
* watch 和 computed 它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,我们处理一些逻辑
* 区别:
+ computed能完成的功能,watch都可以完成。watch能完成的功能,computed不一定能完成,最具代表性的:watch可以进行异步操作。
+ watch擅长处理的场景:一个数据影响多个数据 ,侧重在【监视】,核心是:xxx变了,我要做???事。无需return,靠内部逻辑去完成要做的事。例如当需要在数据变化时执行异步或复杂的业务逻辑处理操作时,这个方式是最有用的
+ computed擅长处理的场景:一个数据受多个数据影响 (购物车商品结算的时候),侧重在【算】,核心是:计算出来的值。靠return来输出计算的结果以供使用。不能开启异步任务。
## day04
- $watch:
* vm.$watch('属性',callBack,{deep/immi})
* $watch返回一个取消当前监视的回调函数
- 组件的创建
* 使用Vue.extend({})创建一个组件,接受一个配置对象,然后在父组件中注册并使用组件
* Vue.extend返回一个VueComponent构造函数,在组件被使用的是时候,会实例化VueComponent构造函数得到一个组件实例
* 其实VueComponent这个构造函数在Vue内部被处理为了Vue的子类(VueCoponent继承了Vue)
* 原型关系:
+ 组件实例.__proto__--->VueComponent.Prototype
+ VueComponent.Prototype.__proto__ ---> Vue.prototype
+ Vue.prototype.__proto__--->Object.prototype
+ Object.prototype.__proto__ ---> null
* 如果我们希望把一个属性放在任何一个组件都能访问位置,放在哪里呢?
+ 肯定不能放在VueComponent.prototype上,因为每创建一个组件都会创建一个新的VueComponent构造函数,不止只有一个
+ 可以放在Vue.prototype上,因为Vue构造函数只有一个,并且原型链会找它
+ 可以放在Object.prototype上,但是我们不建议改动Object的,我们有更好的选择
* 创建组件的时候,可以直接省略Vue.extend(),直接书写一个配置对象即可,当组件被注册的时候,会把当前的配置对象交给Vue.extend方法得到一个VueComponent构造函数
* 如果某个组件复用,那么我们可以使用Vue.Component方法进行全局注册组件
- 安装Vue-cli脚手架
- 安装vue `npm install -g @vue/cli`
- 查看版本 `vue -V`
- 下载一个新的脚手架`vue create XXXX`
* Manually select features:手动配置
* 选择Babel && Linter / Formatter 两个即可
* 2.X
* ESLint with error prevention only:ESlint仅报错
* Lint on save
* In dedicated config files:把babel,eslint等配置独立出来
* 直接选N(默认),不保存刚才的配置
- 重绘重排
* 重排和重绘是DOM编程中耗能的主要原因之一
* 重排(回流):当render tree中的一部分或者是全部,因为元素的尺寸、布局、隐藏等等改变引起页面的重新渲染,这个过程称作为重排,完成重排以后,浏览器会重新绘制受影响的部分到屏幕,该过程称为重绘
* 重绘:当render tree(渲染树)中更新的属性只会影响元素的外观、风格,不会影响元素的布局的时候,浏览器需要重新绘制当前元素的样式,被称作为重绘
* 重绘不会引起重排,但重排一定会引起重绘
- 字符串的方法:startsWith\endsWith\includes\indexOf
- 数组的方法:filter\map\forEach
- eslint在非脚手架中配置
* 初始化包管理文件
`npm init`
* 下载 eslint 包
`npm i eslint -D`
* 创建 eslint 初始配置文件
`eslint --init` 下一步下一步选择
* .eslintrc.js 配置文件解析
```js
module.exports = {
/*
使用 env 关键字指定你想启用的环境,并设置它们为 true。例如,以下示例启用了 browser 和 Node.js 的环境
*/
env: {
browser: true,
es2021: true,
},
//下边这个配置:默认开启eslint规则中前边添加对勾的所有规则
extends: "eslint:recommended",
/*
ecmaVersion - 默认设置为 3,5(默认), 你可以使用 6、7、8、9 或 10 来指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本号指定为 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)或 2019 (same as 10)
sourceType - 设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
*/
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
//具体规则的配置
rules: {
"no-console": "error",
},
};
```
* 使用 eslint 检测代码(必须主动检测)
`eslint XXX.js`
- eslint在脚手架中配置(希望打包的时候进行检测)
* 始化包管理文件
`npm init`
* 下载 eslint 包
`npm i eslint -D`
* 创建 eslint 初始配置文件
`eslint --init`
* 在 webpack.config.js 中配置 eslint-loader
eslint-loader(4.X.X 版本)(`npm i eslint-loader@4 -D`)
eslint(7.X.X 版本)(`npm i eslint@7 -D`)
* 配置webpackloader,并使用webpack启动
```js
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "build"),
filename: "main.js",
},
mode: "development",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
],
},
};
```
- 忽略eslint的检测
* 在报错信息中找到对对应的eslint规则,然后去`.eslintrc.js`文件的rules配置中,直接覆盖修改这个规则
* 在代码中使用注释来忽略规则
+ `// eslint-disable-next-line eqeqeq`:下一行代码忽略eqeqeq规则
+ `// eslint-disable-next-line`:下一行代码会略所有eslint检查
+ `/* eslint-disable eqeqeq*/`当前注释后所有的代码都要忽略eslint的eqeqeq规则检查
+ `/* eslint-disable */`当前注释后所有的代码都要忽略eslint规则检查
## day05
- Vue2脚手架目录分析
* public-->公共资源,在webpack打包的时候会忽略当前文件,直接复制到打包好的目录中
* src --> 我们编写代码的地方,项目的入口文件也在src中
* .browserslistrc -->用来指定项目的目标浏览器范围,将来babel在编译的时候,会根据当前配置的浏览器针对性的编译
+ > 1% : 代表全球有超过1%的人使用的浏览器
+ last 2 versions : 表示所有的浏览器兼容到最后两个版本
+ not dead:不兼容已经淘汰的浏览器
+ not ie <=8 : 不兼容ie8及以下
+ firfox >=50 : 兼容获取大于50的版本
* babel.config.js --> 用来结合browsersList要求,进行babel编译,babel主要是把es6+的语法转为低版本的语法
* jsconfig.json --> 当项目中拥有jsconfig.json的时候,我们书写js的体验会得到提升
* vue.config.js --> 官方自带的用来补充webpack配置的文件
* .gitignore --> 配置git忽略
* package.json --> 当前项目的包管理文件
* package-lock.json --> 包的依赖描述(缓存)文件
- src中入口文件的分析
* 因为完整的Vue包中包含两块内容(1.模板编译模块 2.其他模块)
* 模板编译模块是把template模板编译成虚拟DOM,但是我们项目打包完成之后,就不再需要模板编译功能
* 模板编译模块占了vue.js的40%的空间,所以如果在项目中还携带这个完整的vue,会有下载压力
* vue还提供了一个 vue.runtime.js 版本,没有包含模板编译,还提供了一个vue-template-compiler 包,专门用来模板编译
* 在脚手架中我们把vue.runtime.js设置为生产依赖,把模板编译功能单独提炼设置为开发依赖,此时可以减少打包后的文件体积
* 因为不再使用vue包中自带的模板编译功能,所以我们在new Vue中编译App组件的写法要发生变化
```js
//vue的配置中还提供了一个配置项 render,是一个函数,接受一个createElement方法作为参数,这个方法可以接受一个组件,然后创建虚拟DOM,
render: (createElement) => {
return createElement(App);
},
//尤雨溪把createElement这个方法简写为h
render: (h) => h(App),
```
- src中其他文件
* components:用来书写组件
* App.vue : 根组件
* asstes : 公共静态资源(要被webpack打包的)
* main.js : 入口文件
- style标签的scoped属性
* scoped属性:一旦添加,当前style中样式只对当前组件的模板生效
* scoped原理:
+ 一旦在当前组件的style标签中添加了scoped属性,则代表当前的样式拥有作用域了,只在当前组件的元素内生效
+ 给当前组件的所有元素(还有子组件的最外层容器元素)全部添加一个统一的自定义属性(data-v-xxxxxx)(每个组件的自定义属性是不一样的)
+ 然后给所有的scoped中的选择器添加一个属性选择器 XXX[data-v-xxxx],那么就只能选择当前组件的元素了
- 深度选择器(样式穿透)
如果我们在父组件中想要控制后代组件的某个元素样式,我们有两种做法
* 把父组件中书写样式style不要添加scoped(但是这样可能会出现其他问题)
* 使用深度选择器: `父组件的选择器 >>> 后代组件内元素的选择器`
* 深度选择器的原理: 只在父组件选择器上添加自定义属性,后代的选择器不再添加自定义属性
- ref的基础使用(ref使用在普通元素上)
* 如果想要获取某个真实DOM,则在当前模板元素上添加一个ref属性,值为一个字符串名称
* 当模板渲染后,在当前的组件实例上的$refs对象中,就会有一个当前字符串名称为属性名,值为被设置ref的真实DOM 组成的键值对。
- ref设置在子组件上
* 如果ref设置给了子组件上,则我们通过$refs拿到的是这个组件的组件实例
* 最常用的就是通过子组件的实例拿到子组件的数据进行处理(组件通信-->子传父)
- props的基础使用
* 作用:主要是为了向子组件传递一些数据,用 给子组件添加属性 的方式传递,这样被称作为props传值
* 子组件的接收
+ 如果想要在组件实例上拿到父组件传递过来的props,必须先通过props配置项进行接收(props配置项可以是对象,数组)
+ 接受完成之后,props的数据会在 组件实例上 和 组件实例的$props对象上 各存放一份以用来使用
+ props是不能直接被修改的(vue支持单向数据流)
- props传递一个函数
- 如果props传递一个值,则代表组件通信的 父传子
- 如果props传递一个函数,则代表组件通信中的 子传父
* 假设子组件想要修改父组件的数据,子组件是不能直接修改props的
* 我们可以在父组件中定义一个修改自己数据的方法 传递给子组件
* 子组件调用父组件的方法,就可以修改父组件的数据了
- props可以直接使用 `v-bind="对象"` 直接展开对象批量传递
- props的对象写法:在子组件中接受props的写法可以写成一个对象,限制某个prop的类型和必填和默认等等
```js
props: {
count: Number,
otherTitle: {
type: String,
// required: true,
default: "暂无....",
},
},
```
- 正则表达式
* 定义一组规则,和一个字符串进行 校验
* 正则是RegExp对象 字符串是String对象,每个对象都有自己的方法正则校验
* RegExp对象提供的方法:
+ test: 正则.test(字符串):如果字符串符合正则条件则返回true,否则返回false
* String对象提供的方法:
+ replace:第一个参数是正则,第二个参数是替换匹配到的值
+ match:返回匹配到的值组成的数组
* 常见规则:
\d:数字
[0-9]:数字
[a-z]:字母
[0-9a-z]:数字字母
\s:空白字符
* 常见量词
+ : 1个或多个
? : 0个或多个
{2,4}:2个-4个
{4,}:4个及以上
* 其他:
^:以后边的规则为开头
$:以前边的规则为结尾
* 千位分隔符面试题:
`const reg = /(\d)(?=(\d{3})+$)/g;`
+ 假设这个值‘1234567890’
+ (\d{3})+:890 567890 234567890
+ ?=(\d{3})+:1234567 1234 1
+ (\d)(?=(\d{3})+):7 4 1
## day06
### 1.0 webpack
* 打包构建工具
+ 构建:把不支持的代码转为支持的代码
+ 打包:把多个文件合并成一个文件
* 最基础的5个部分
+ Entry:入口起点(entry point),打包时,第一个被访问的源码文件,指示 webpack 应该使用哪个模块来作为构建其内部依赖图的开始。
+ Output:出口,打包后,输出的文件名称
+ Loader:加载器,loader 让 webpack 能够去处理那些非 JavaScript 文件(常见loader:eslint-loader、less-loader、css-loader)
+ Plugins:插件,实现loader之外的其他功能(打包优化和压缩等)
+ Mode:模式,生产模式 production,开发模式 development
### 2.0 过滤器
- 过滤器
* vue中,过滤器是在模板的插值语法中,对数据的过滤,返回过滤器的返回值给插值语法
* 过滤器的定义可以是全局的或局部的
+ 全局过滤器定义:Vue.filter("name",(value,arg)=>{})
+ 局部过滤器定义:在配置项中使用filters配置 filters:{name(value,arg){}}
* 过滤器可以连续使用
* 过滤器可以在使用的时候传递参数
### 3.0 自定义组件及钩子函数(生命周期)
- 自定义指令的简写使用
* Vue 允许注册自定义指令,有的情况下,你需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令
* 自定义指令同样可以全局注册和组件内注册,分别使用Vue.directive()方法和directives配置项
* 简写使用的时候,自定义指令其实就是一个函数,接收两个参数,
+ 参数1是el,代表当前的DOM
+ 参数2是binding,代表当前的指令详情对象,其中value属性就是指令的值
- 自定义指令的生命周期函数
* bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置(在这个函数中无法获取到父元素)(!!!简写使用的是bind)
* inserted:被绑定元素插入父节点时调用(可以获取到父元素)
* update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前
* componentUpdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
* unbind:只调用一次,指令与元素解绑时调用
### 4.0 Vue插件
- Vue插件
* 插件通常用来为 Vue 添加全局功能
* 插件的对象写法:
+ 必须使用install方法,当插件被安装的时候,install方法会被调用
+ 接受Vue作为参数,install内部就可以拿到Vue进行全局注册一些东西
* 插件的函数写法:
+ 如果插件直接是一个函数, 则在注册时候会直接被当做install函数,并接受Vue作为参数(常用)
* 插件的安装:
+ Vue.use()可以安装一个插件
### 5.0 Vue 生命周期
#### 1.0 Vue的生命周期-初始化阶段
* new Vue({}) 或者是 new VueComponent({}):实例化一个vm或者组件实例
* init:初始化实例,比如事件系统和生命周期激活等等
* **beforeCreate**:执行的节点是:数据代理和数据劫持之前(不能获取到任何数据)
* 注入所有的配置(数据劫持、数据代理、计算属性、方法、事件/侦听器的回调函数)
* **created**:执行的节点是:数据代理和数据劫持之后(可以获取到数据)
#### 2.0 Vue的生命周期-模板编译阶段
* 判断有没有el选项,如果有则继续判断是否有template,如果没有则看一下有没有$mount挂载,然后再走判断是否有template(判断是否有容器进行挂载)
* 判断是否有template配置向
+ 如果有,则使用render函数对模板进行编译为VNode
+ 如果没有,则把容器(el)的outerHTML作为模板,编译为VNode
#### 3.0 Vue的生命周期-挂载阶段
* **beforeMount**:挂载之前(此时页面呈现的是原始el容器的DOM元素,这个节点不能操作DOM)
* 挂载的过程:把虚拟DOM转为真实DOM(vm.$el),并且把vm.$el(Vue 实例使用的根 DOM 元素)替换原始模板中的el
* **mounted**:挂载之后(此时页面呈现的是真正的DOM,此时实例的所有初始化已经结束,在这个生命周期中就可以书写我们要的初始化操作了(开启定时器,订阅,绑定自定义事件,发送初始化数据请求))
#### 4.0 Vue的生命周期-更新阶段
* 更新数据,进入更新阶段
* **beforeUpdate**:视图更新之前(此时数据和视图展示的是不一致)
* 根据新的数据生成新的虚拟DOM,然后经过diff算法比较,更新视图
* **updated**:视图更新之后
#### 5.0 Vue的生命周期-销毁阶段
* 路由的切换或者我们自己调用$destroy(),进入销毁阶段
* **beforeDestroy**:在这个函数中,我们一般进行收尾工作,比如清理定时器,取消订阅,解绑自定义事件(在这个阶段我们更新数据已经没有意义了,因为视图不会再更新,我们不可能回退到更新阶段)
* $destroy():完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器
* **destroyed**:这个阶段一般没有操作
#### 6.0 父子组件生命周期流程
* 初始化挂载:
父beforeCreate --> 父created --> 父beforeMount --> 子beforeCreate --> 子created --> 子beforeMount --> 子mounted --> 父mounted
* 更新阶段
!!!!和React不一样的地方:如果父组件更新不影响子组件的任何数据,则子组件不会重新渲染,不会走更新流程(Vue内部做的处理)
父beforeUpdate --> 子beforeUpdate --> 子updated --> 父updated
* 销毁阶段
父beforeDestroy --> 子beforeDestroy --> 子destroyed --> 父destroyed
#### 7.0 生命周期补充
* 以上说明的生命周期流程是完整版Vue的流程图(拥有模板编译的vue版本)
* runtime版本的vue是没有模板编译阶段!!!!!因为webpack中配置的vue-loader,会把vue内部的模板在构建阶段直接编译为了渲染函数,所以runtime版本在生命周期的模板编译阶段是不存在的,而是在挂载时直接调用渲染函数即可