最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue源码,你真的看懂了吗(三)

    正文概述 掘金(蒲月阿七)   2021-02-27   618

    虚拟DOM与diff算法

    虚拟dom

    是将状态映射成视图的总舵解决方案的一种,运作原理是使用状态生成虚拟节点,然后使用虚拟节点渲染视图。

    虚拟DOM和真实DOM的区别

    virtual DOM是将真实的 DOM 的数据抽取出来,以对象的形式模拟树形结构,diff算法比较的也是virtual DOM

    为什么引入虚拟DOM

    Vue.js1.0变化侦测粒度太细,会有很多watcher同时观察某些状态,多了一些内存开销和依赖追踪的开销。Vue.js2.0的状态侦测不细化到某个具体节点,而是某个组件,组件内部通过虚拟DOM来渲染视图,就可以大大缩减watcher和依赖的数量。

    虚拟dom在vue中所做的事

    • 提供与真实DOM节点所对应的虚拟节点vnode
    • 将新vnode与旧vnode比对,更新视图

    vnode是什么?

    Vnode是一个类,可以生成不同的vnode实例,而不同类型的vnode表示不同类型的真实DOM元素。

    可以理解为节点描述对象,渲染视图的过程就是创建vnode,然后使用vnode去创建真实的DOM节点,生成的DOM节点可以插入到页面渲染视图。

    export default class VNode {
      tag: string | void;
      data: VNodeData | void;
      children: ?Array<VNode>;
      text: string | void;
      elm: Node | void;
      ns: string | void;
      context: Component | void; // rendered in this component's scope
      key: string | number | void;
      componentOptions: VNodeComponentOptions | void;
      componentInstance: Component | void; // component instance
      parent: VNode | void; // component placeholder node
    
      // strictly internal
      raw: boolean; // contains raw HTML? (server only)
      isStatic: boolean; // hoisted static node
      isRootInsert: boolean; // necessary for enter transition check
      isComment: boolean; // empty comment placeholder?
      isCloned: boolean; // is a cloned node?
      isOnce: boolean; // is a v-once node?
      asyncFactory: Function | void; // async component factory function
      asyncMeta: Object | void;
      isAsyncPlaceholder: boolean;
      ssrContext: Object | void;
      fnContext: Component | void; // real context vm for functional nodes
      fnOptions: ?ComponentOptions; // for SSR caching
      devtoolsMeta: ?Object; // used to store functional render context for devtools
      fnScopeId: ?string; // functional scope id support
    
      constructor (
        tag?: string,
        data?: VNodeData,
        children?: ?Array<VNode>,
        text?: string,
        elm?: Node,
        context?: Component,
        componentOptions?: VNodeComponentOptions,
        asyncFactory?: Function
      ) {
        this.tag = tag
        this.data = data
        this.children = children
        this.text = text
        this.elm = elm
        this.ns = undefined
        this.context = context
        this.fnContext = undefined
        this.fnOptions = undefined
        this.fnScopeId = undefined
        this.key = data && data.key
        this.componentOptions = componentOptions
        this.componentInstance = undefined
        this.parent = undefined
        this.raw = false
        this.isStatic = false
        this.isRootInsert = true
        this.isComment = false
        this.isCloned = false
        this.isOnce = false
        this.asyncFactory = asyncFactory
        this.asyncMeta = undefined
        this.isAsyncPlaceholder = false
      }
    
      get child (): Component | void {
        return this.componentInstance
      }
    }
    

    vnode作用

    vnode对组件采用了虚拟DOM来更新视图,属性发生变化的时候,整个组件都要进行重新渲染,但是组件内并不是所有的DOM节点都需要更新。Vue中将vnode进行缓存并将新生成的vnode与上一次缓存的oldvnode进行对比,对需要更新的部分进行DOM操作,这样提高了渲染速度,降低了内存消耗。

    vnode类型

    vnode有多种类型,本质上是从Vnode类实例化出来的对象,唯一区别是属性不同。

    • 注释节点

    • 文本节点

    • 克隆节点

      作用是优化静态节点和插槽节点。

      因为静态节点的内容一直不会变,可以使用创建克隆节点的方法将静态节点的vnode克隆一份,使用克隆节点进行渲染,这样就不需要重新执行渲染函数生成新的静态节点的vnode,可以提升一定程度的性能。

    • 元素节点

    • 组件节点

    • 函数式节点

    patch函数

    diff算法是一种优化手段,将前后两个模块进行差异化对比,修补(更新)差异的过程叫做patch(打补丁)。

    也就是,Vue中diff算法过程就是调用名为patch函数。

    diff算法原理

    1、先同级比较,再比较儿子节点

    2、先判断一方有儿子一方没儿子的情况

    3、比较都有儿子的情况

    4、递归比较子节点

    vue3中做了优化,只比较动态节点,略过静态节点,极大的提高了效率。

    思考

    diff算法时间复杂度?

    两棵树进行完全比对diff算法的事件复杂度为O(n),Vue对此进行优化,只考虑同级不考虑跨级,将时间复杂度降低到O(n)。

    因为我们在操作页面的时候很少会去跨层级的移动DOM元素,所以Virtual DOM只会对同一个层级的元素进行对比。 Vue源码,你真的看懂了吗(三)

    Vue 中的 key 到底有什么用?

    同一层级的一组节点,他们可以通过唯一的id进行区分。key是每一个vnode的唯一id,依靠key,diff操作可以更加准确,更加快速。

    如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。

    如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。

    Vue源码,你真的看懂了吗(三)

    在B和C之间加一个F,Diff算法默认执行起来是这样的:

    Vue源码,你真的看懂了吗(三)

    即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

    所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

    v-for(:key)绑定index、id、key的区别

    使用v-for渲染元素时,使用元素自身的id属性去指定渲染元素的key值有利于单个元素的重新渲染,若采用其他如v-for提供的index, key等值,在改变渲染出来的DOM结构时,会触发所有元素的重新渲染,当数据过大时,可能会造成性能负担。

    当我们在使用v-for进行渲染时,尽可能使用渲染元素自身属性的id给渲染的元素绑定一个key值,这样在当前渲染元素的DOM结构发生变化时,能够单独响应该元素而不触发所有元素的渲染。


    起源地下载网 » Vue源码,你真的看懂了吗(三)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元