Vue2的一些原理

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实现原理

  1. computedwatch
    实际上它们都是通过 watcher 实现的,最大区别就是 computed 具有缓存功能。

在创建计算属性时,它会创建一个watcher,其中有两个属性lazy:true, dirty: true
创建过程默认是不执行的,只有当用户取值时才会判断 dirty:true 则让这个watcher去取值,求值结束后则改为dirty:false,不再重新求值,再次取值直接返回上次求值结果。
那什么时候会重新计算求值呢?
只有当计算属性中依赖的值发生变化时,它会调用对应的update(),更改dirty:true,从而重新执行watcher求值。

  1. v-ifv-for 不能一起使用,必要时应使用 computed 先过滤出需要的数组元素。
    原因是 v-forv-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()
        })
    }
    
  2. v-show 的底层实现
    v-show编译出来里面没有任何东西,只有一个directives,它里面有一个指令叫做v-show
    源码编译
    VueTemplateCompiler.compile(`<div v-show="true"></div>`);
    with(this) {
        return _c('div', {
            directives: [{
                name: "show",
                rawName: "v-show",
                value: (true),
                expression: "true"
            }]
        })
    }
    
    只有在运行的时候它会去处理这个指令,它正是在操作DOM的 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'
        }
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。