keep-alive
keep-alive - 多看源码,方知原理,才能优化
- 作用:缓存
- 怎么缓存:用队列缓存到内存中
- 缓存什么:
VNode虚拟DOM - 注意点:缓存数量的限制,因为
VNode很大,为了防止内存溢出,所以不允许缓存过多 - 缓存机制:
LRU - 优化点:不缓存
VNode,而是缓存data数据
Vue的编译运行
vue runtime + complier
-
runtime运行时 -
complier编译时
一个单文件组件的模式:template、script、style
- 通过本地离线编译,把单文件组件编译为
render函数(JS文件),这个过程就是vue的编译时。 - 编译后的文件存放到远程服务器,浏览器访问页面时,请求这些
js文件并执行:new Vue()把数据处理成响应式数据,并触发render函数,进入vue的运行时。
render()的执行会生成VNode,并patch到真实DOM上。当数据改变时,Watcher会找到对应要更新的组件,Diff组件级别的新旧两个VNode Tree,生成补丁并应用到真实DOM树中。

vue的编译运行.png
所以,直接使用 render 函数可以在一定程度上优化编译过程。
Look实现原理
-
computed与watch
实际上它们都是通过watcher实现的,最大区别就是computed具有缓存功能。
在创建计算属性时,它会创建一个
watcher,其中有两个属性lazy:true, dirty: true。
创建过程默认是不执行的,只有当用户取值时才会判断dirty:true则让这个watcher去取值,求值结束后则改为dirty:false,不再重新求值,再次取值直接返回上次求值结果。
那什么时候会重新计算求值呢?
只有当计算属性中依赖的值发生变化时,它会调用对应的update(),更改dirty:true,从而重新执行watcher求值。
-
v-if与v-for不能一起使用,必要时应使用computed先过滤出需要的数组元素。
原因是v-for比v-if的优先级更高,即使只需要其中一个元素(只有一个元素的v-if="true"),每一次仍然需要遍历整个数组,严重影响性能。
源码编译// 1. v-if 在父元素上,v-for 在子元素上 VueTemplateCompiler.compile(`<div v-if="true"><span v-for="i in 3">hello</span></div>`); // 模板的编译结果 with(this) { return (true) ? _c('div', _l((3), function (i) { return _c('span', [_v("hello")]) }), 0) : _e() // _e()方法创建一个空的虚拟dom等等。 } // 2. v-for 与 v-if 连用的编译结果 VueTemplateCompiler.compile(`<div v-if="false" v-for="i in 3">hello</div>`); with(this) { return _l((3), function (i) { return (false) ? _c('div', [_v("hello")]) : _e() }) } -
v-show的底层实现
v-show编译出来里面没有任何东西,只有一个directives,它里面有一个指令叫做v-show
源码编译
只有在运行的时候它会去处理这个指令,它正是在操作DOM的VueTemplateCompiler.compile(`<div v-show="true"></div>`); with(this) { return _c('div', { directives: [{ name: "show", rawName: "v-show", value: (true), expression: "true" }] }) }display属性// v-show 操作的是样式 定义在platforms/web/runtime/directives/show.js bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) { vnode = locateNode(vnode) const transition = vnode.data && vnode.data.transition const originalDisplay = el.__vOriginalDisplay = el.style.display === 'none' ? '' : el.style.display if (value && transition) { vnode.data.show = true enter(vnode, () => { el.style.display = originalDisplay }) } else { el.style.display = value ? originalDisplay : 'none' } }
