Skip to content

谈谈 Vue 的 VNode 是如何转换为真实 DOM 的。 #29

Open

Description

@CodeRookie262

我们在写 Vue 组件时,他们都是从 VNode 转变成真实 DOM 后再进行渲染的,再此期间 Vue 是如何将 VNode 转变为真实的 DOM 呢?

Activity

  1. CodeRookie262 commented on Jan 26, 2021

    @CodeRookie262
    OwnerAuthor

    VNode 称之为虚拟节点,React 和 Vue 都是基于 VNode 转换为 真实 DOM 节点进行视图渲染的,VNode的好处在于保证了平台性能下限,无需手动操作DOM节点和跨平台,但是它也是存在一些缺点的,因为 VNode 是一个对 DOM 节点抽象描述的 JS 对象,对象储存在堆内存中,当 VNode 的数量比较大时就会对内存会有较大的开销,同时因为他是抽象的,所以无法对其做一些各位极致细腻的处理。

    那么简单的描述下VNode的结构,例如用 VNode 描述这样一个标签 <div class="container">内容</div>,它的结构是这样的。

    const vnode = {
      type: 'div',
      props: { 
        'class': 'container',
      },
      children: '内容'
    }

    当首次渲染是会通过 render 函数会递归遍历 vnode 并且转化为 真实的 DOM 节点,最终过载到 $el 或者 .$mount 到对应的容器中。
    这里简单的封装一下render函数。

    // 定义 VNode 类
    function VNode(type,props,children){
        this.type = type;
        this.props = props;
        this.children = children;
    }
    
    // 将虚拟DOM转化为真实DOM节点
    function render(vnode) {
        const { type, props, children } = vnode
    
        const el = document.createElement(type);
    
        for (let key in props) {
            setAttrs(el, key, props[key]);
        }
    
        children.map((c)=>{
            if(c instanceof VNode){
                c = render(c);
            }else{
                c = document.createTextNode(c);
            }
    
            el.appendChild(c)
        })
    
        return el;
    }

    最终render会返回成真实的 DOM 节点。

    如果是 update 操作的话,在形成真实节点前会先进行 patchValue,计算和判断新旧vnode之间的差异,如果新旧vnode不一致的话就进行增加或者删除操作,如果新旧 vnode 一直的话,且 key 值一样和是静态或者v-once则将旧vnode的children直接转给新的 vnode中,负责就进行 patch 处理,对内部子节点进行比对(就是我们所说的 diff 算法)最终会生成新的 vnode并将其转化为真实DOM动态更新到终点的父级节点中(这里的父集节点有可能不是挂载时绑定的节点,而是变化节点的父级节点)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions