学习VUE的虚拟DOM(Virtual DOM)

东明兄 2021-03-12
0条评论 355 次浏览
东明兄 2021-03-120条评论 355 次浏览

虚拟dom就是用 JS 对象去描述一个 DOM 节点,因为真实的dom非常复杂,有很多用不到的属性。使用用createElement 创建一个div:

var div = document.createElement("div");
var str ="";
for(var key in div){ str += key+"," }

打印结果:

可以看到真实的dom是非常复杂的,而前端开发需要频繁的更新dom,频繁更新dom会产生性能问题。

虚拟dom用js对象描述一个节点,只用了必要的属性去描述节点,vue中使用vnode描述节点,

vnode
https://github.com/vuejs/vue/blob/dev/src/core/vdom/vnode.js

VNode对真实 DOM 进行抽象的描述,它定义了几个关键属性,标签名、数据、子节点、键值等。VNode 只是用来映射到真实 DOM 的渲染,不需要包含操作 DOM 的方法,因此很轻量。映射到真实的 DOM 实际上要经历 VNode 的 create、diff、patch 等过程。

creat

VNode 的 create 是通过 createElement 方法创建的

createElement:https://github.com/vuejs/vue/blob/dev/src/core/vdom/create-element.js

createElement 方法是对 _createElement 进行了一层封装,它对传入的数据进行了初步处理使得可传入的数据更灵活,在处理这些参数后,调用真正创建 VNode 的函数 _createElement

同dom节点一样,vnode可能会有多个子节点,这些子节点也应该是vnode类型,但是_createElement 的children参数是any类型,需要对chidren参数 进行处理,规范为 vnode类型,根据 normalizationType ,调用了 normalizeChildren(children) 和 simpleNormalizeChildren(children) 方法,

对children规范化代码位置:
https://github.com/vuejs/vue/blob/dev/src/core/vdom/helpers/normalize-children.js

接下来回到 createElement

 let vnode, ns
  if (typeof tag === 'string') {
    let Ctor
    ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
    if (config.isReservedTag(tag)) {
      // platform built-in elements
      if (process.env.NODE_ENV !== 'production' && isDef(data) && isDef(data.nativeOn) && data.tag !== 'component') {
        warn(
          `The .native modifier for v-on is only valid on components but it was used on <${tag}>.`,
          context
        )
      }
      vnode = new VNode(
        config.parsePlatformTagName(tag), data, children,
        undefined, undefined, context
      )
    } else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
      // component
      vnode = createComponent(Ctor, data, context, children, tag)
    } else {
      // unknown or unlisted namespaced elements
      // check at runtime because it may get assigned a namespace when its
      // parent normalizes children
      vnode = new VNode(
        tag, data, children,
        undefined, undefined, context
      )
    }
  } else {
    // direct component options / constructor
    vnode = createComponent(tag, data, context, children)
  }

这里对 tag 做判断,如果是 string 类型,则接着判断是内置节点的话直接创建一个普通 VNode,如果是为已注册的组件名,则通过 createComponent 创建一个组件类型的 VNode,否则创建一个未知的标签的 VNode。

createElement用于创建vnode,vnode有children,children的元素也是vnode,形成了 vnode tree,模拟了dom tree。

发表评论

您的电子邮箱地址不会被公开。