# 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 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版本在生命周期的模板编译阶段是不存在的,而是在挂载时直接调用渲染函数即可