一、生命周期
1、new vue实例过程中,实例初始化之后,数据观测、事件配置之前,beforeCreate被
调用
2、实例创建后,created被立即调用,完成数据观测、method、computed、watch
挂载阶段还没开始,$el 属性目前尚不可用。
3、实例挂载(实例绑定到tenplete模版)前,相关的 render 函数首次被调用,beforeMounted被调用
4、实例挂载之后(tenplete模版有数据了),mounted,注意:mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick:
5、观察者监测到数据发生变化,订阅者通知对应组件重新渲染,beforeupdate--updated
6、实例销毁前,beforeDestroy,此时实例仍然可用,当Destroyed,所有子实例被销毁,事件绑定解除
另外还有 keep-alive 独有的生命周期,分别为 activated 和 deactivated 。用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子,命中缓存渲染后会执行 actived 钩子函数。
二、双向绑定原理 3:05-

1、首先:Vue单向数据流,双向:单向绑定和 oninput/onchange 事件侦听的语法糖
原理:
监听状态的变化:defineProperty 重写对象属性的 getter/setter 方法
通过getter进行依赖收集,而每个setter方法就是一个观察者,在数据变更的时候通知订阅者更新视图。
Object.defineProperty 不能监听数组的变化,需要进行数组方法的重写
首先:跟据数组的prototype创建一个新对象,然后对数组方法进行逐个重写,
继续监听(push、splice等)带入的新数据
数组方法在调用时触发notify()进行通知订阅者
数组进行重写,覆盖掉原生的数组方法
重写之后的数组方法需要能够被拦截。
但有些数组操作Vue时拦截不到的,当然也就没办法响应,比如:
obj.length-- // 不支持数组的长度变化
obj[0]=1 // 修改数组中第一个元素,也无法侦测数组的变化
const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);
['push','pop','shift','unshift','splice','sort','reverse']
.forEach(method => {
// 拿到对应的原生方法
var original = arrayProto[method];
def(arrayMethods, method, () => {
// 参数处理
var i = arguments.length;
var args = new Array(i);
while (i--) {
args[i] = arguments[i];
}
// 运行原生方法
var result = original.apply(this, args);
var ob = this.__ob__;
// 特殊处理数组插入方法
var inserted;
switch (method) {
case 'push':
inserted = args;
break;
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
// 对插入的参数进行数据劫持
if (inserted) ob.observeArray(inserted);
// 发布改变通知
ob.dep.notify();
return result;
})
})
源码分析:segmentfault.com/a/119000001…
数据发生变化后,会重新对页面渲染,这就是Vue响应式
方法2. Proxy实现
Proxy 的代理是针对整个对象的,因此不同于 Object.defineProperty 的必须遍历对象每个属性
Proxy支持代理数组的变化。
三、mvvm
1、mvc,数据源-视图-控制器修改数据
2、微创新:
viewmodel :vue 桥:数据视图分离:通过data绑定操作视图,通过事件绑定操作model
v:
m:js对象,
准确: 如果不加key,那么vue会选择复用节点(Vue的就地更新策略),导致之前节点的状态被保留下来,会产生一系列的bug.
快速: key的唯一性可以被Map数据结构充分利用,相比于遍历查找的时间复杂度O(n),Map的时间复杂度仅仅为O(1).
四、Vue 组件间通信
1、props/$emit
2、vuex
3、$emit/$on
通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,实现了任何组件间的通信,包括父子、兄弟、跨级
var Event=new Vue();
Event.$emit(事件名,数据);
Event.$on(事件名,data => {});
4、ref $父组件 $子组件
五:watch、methods 和 computed 的区别
watch 为了监听某个响应数据的变化。
computed 是自动监听依赖值的变化,从而动态返回内容,主要目的是简化模板内的复杂运算。所以区别来源于用法,只是需要动态值,那就用 computed ;需要知道值的改变后执行业务逻辑,才用 watch。
methods是一个方法,它可以接受参数,而computed 不能,computed 是可以缓存的,methods 不会。computed 可以依赖其他 computed,甚至是其他组件的 data。
六、路由钩子
组件内的守卫 beforeRouteEnter(不保证所有组件挂载完毕,echart有时获取不到)、beforeRouteUpdate、beforeRouteLeave
全局前置守卫 router.beforeEach
路由独享的守卫 beforeEnter
全局解析守卫 router.beforeResolve(在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。)
全局后置钩子 router.afterEach(不会接受 next 函数也不会改变导航本身:)
route 和 router 的区别:
route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
router是“路由实例对象”,包括了路由的跳转方法(push、replace),钩子函数等。
七、vue 首屏加载优化
1、 将不常更新的第三方库脱离webpack打包:放到 index.html 中,通过 cdn 引入
使用 CDN 的好处有以下几个方面
(1)加快打包速度。分离公共库以后,每次重新打包就不会再把这些打包进 vendors 文件中。
(2)CDN减轻自己服务器的访问压力,并且能实现资源的并行下载。浏览器对 src 资源的加载是并行的(执行是按照顺序的)。
然后找到 build/webpack.base.conf.js 文件,在 module.exports = { } 中添加以下代码
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'element-ui': 'ELEMENT',
},
2、图片懒加载:
原理:
先将img标签的src链接设为同一张图片(比如空白图片),然后给img标签设置自定义属性(比如 data-src),然后将真正的图片地址存储在data-src中,当JS监听到该图片元素进入可视窗口时,将自定义属性中的地址存储到src属性中。达到懒加载的效果

<ul>
<li><img src="./imgs/default.png" data="./imgs/1.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/2.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/3.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/4.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/5.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/6.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/7.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/8.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/9.png" alt=""></li>
<li><img src="./imgs/default.png" data="./imgs/10.png" alt=""></li>
</ul>
let imgs = document.querySelectorAll('img')
// 可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
function lazyLoad () {
// 滚动卷去的高度
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
for (let i = 0; i < imgs.length; i ++) {
// 图片在可视区冒出的高度
let x = clientHeight + scrollTop - imgs[i].offsetTop
if (x > 0) {
imgs[i].src = imgs[i].getAttribute('data')
}
}
}
// addEventListener('scroll', lazyLoad) or setInterval(lazyLoad, 1000)
3、预加载:简单来说就是将所有所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。虽然增加了服务器前端压力,但首屏优化可用 懒加载对服务器前端有一定的缓解压力作用,
4、仔细考虑组件是否需要全局引入,需要全局引入的:main.js里:axios vue router,其他适当的按需引入 例如:手动引入 ECharts 各模块
八、Vue 3.0
过尤大的关于3.0版本的RFC Vue Function-based API RFC。
大致说了三个点,第一个是关于提出的新API setup()函数,第二个说了对于Typescript的支持,
最后说了关于替换Object.defineProperty为 Proxy 的支持。
详细说了下关于Proxy代替带来的性能上的提升,
因为传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,
但使用Proxy又带来了浏览器兼容问题。
九、vue-cli 替我们做了哪些工作?
.vue 文件 --> .js 文件
ES6 语法 --> ES5 语法
Sass,Less,Stylus --> CSS
对 jpg,png,font 等静态资源的处理
热更新
...