1.Object.definePropoty
2.vue初始化数据时,会对data中的属性进行观测,通过Object.property来劫持各个属性的getter、setter,会进行依赖收集, 在数据变动时会通知相应的依赖进行通知更新操作。
1.重写了数组方法,对数组进行了原型链重写
2.对数组的每一项进项观测(是对象也会进行更新)
vue源码 src/compiler/core/observer/index
if (Array.isArray(value)) { //数组
if (hasProto) {
protoAugment(value, arrayMethods) //数组重写
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
}
vue是组件级更新,每次数据更新都会对当前页面进行更新,为了提高新能,会在本轮数据更新后,再异步更新视图
源码:
update () {
/* istanbul ignore else */
if (this.lazy) { //计算属性
this.dirty = true
} else if (this.sync) { //同步watcher
this.run()
} else {
queueWatcher(this) //将watcher放入队列
}
}
事件循环机制。
使用宏任务和微任务定义异步方法。
默认computed也是一个watcher,是具备缓存,只要当依赖的属性发生变化时才会更新视图
function createComputedGetter (key) {
return function computedGetter () {
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
if (watcher.dirty) { //做了一个dirty,实现缓存
watcher.evaluate()
}
if (Dep.target) {
watcher.depend()
}
return watcher.value
}
}
}
当用户指定了watch中的deep属性为true时,如果当前监控的值是数组类型,会对对象中的每一项进行求职,此时会将当前watcher存入到对应属性的依赖中,这样数组中对象发生变化时也会通知数据更新。
耗内存。所有数据遍历,递归
created 实例已经创建完成
mounted 实例已经挂在完成,可以进行dom
beforeUpdate 可以再狗子中进一步更改状态,不会触发附加的重渲染过程
updated可以执行依赖于dom的操作,更改状态可以导致无线循环
destoryed 清空定时器,接触绑定操作
created中dom没有渲染,一般都放在mounted,服务端渲染不支持mounted,统一放到created
1.将模板转化成ast树
2.优化树
3.将ast树生成代码
v-for优先级更高,数据量多影响性能。
将template ast树=》codegen => 转换车工render函数 => 内部调用 =>虚拟dom
template => 虚拟dom
1.只对同级比较,再比较子节点
2.先判断一方有儿子,一方没儿子的情况
3比较都有儿子的情况
4.递归比较子节点
.
方便diff算法
不使用key或用索引,使用复用策略,标签一样仅替换内容
渲染组件时,会通过Vue.extend方法构建子组件的构造函数,并进行实例化。最终手动调动$mount进行挂载,更新组件时会进行patchVnode流程,核心是diff算法
保证数据独立性
同一个组件被复用多次,会创建多个实例,用的都是同一个构造实例。防止实例互相干扰
1.原生dom使用addEventListener
2.组件绑定 使用$on
1.可能会导致xss攻击
2.会替换掉标签内部的子元素
父 beforeCreate ->created->beforeMount ->子 beforeCreate - > created ->beforeMount->mounted-> 父mounted
1.父子通信 props, o n , on, on,emit
2.获取父子组件实例的方式 p a r e n t 、 parent、 parent、children
3.provide、inject
4.ref获取实例的方式
5.Event Bus跨组件通信 vue.prototype. b u s = n e w V u e 6. V u e x 状 态 管 理 7. bus= new Vue 6.Vuex状态管理 7. bus=newVue6.Vuex状态管理7.attrs $listeners
//异步组件一定是一个函数,新版本支持对象
如果组件功能多打包出的结果会变大,会使用异步加载组件,使用Import引入
创建组件虚拟节点时,会将组件的儿子的虚拟节点保存起来
渲染组件时会拿对应的slot进行渲染
普通插槽与作用域插槽渲染作用域不同,普通插槽作用域是父组件,作用域插槽是子组件
编码优化
1.SPA页面采用keep-alive
2.拆分组件(提高复用性、减少不必要的渲染)
3.key保持唯一
4.v-if代替v-show
5.Object.freeze冻结数据,不会增加getter,setter
6.v-for时给每项元素绑定事件用事件代理
7.不要将所有数据放在data中,data中的数据都会增加getter和setter,会收集对应的wacther
8.合理使用路由懒加载、异步组件
9.尽量采用runtime运行时版本
10.数据持久化的问题(防抖、节流)
vue加载性能优化
·1.第三方按需导入
2.图片懒加载 (vue-lazyload)
3.滚到可视区域动态加载(vue-virtual-scroll-list)
用户体验
app-skeleton 骨架屏
app-shell app壳
pwa
seo优化
预渲染插件 (prerender-spa-plugin)
服务端渲染 (ssr)
打包优化
使用cdn的方式加载第三方模块
sourcemap
composition API 解决mixin的缺陷
响应式数据原理改成proxy
TS编写
vdom的对比算法更新,只更新动态数据的部分
runtime-core 体积压缩成了 约10kb