前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue中vdom的创建

Vue中vdom的创建

作者头像
terrence386
发布2022-07-14 21:20:18
3420
发布2022-07-14 21:20:18
举报

本来准备开始之前打算好的新项目,打算基于taro进行多端开发。但是本地安装的版本太低,用taro update 更新版本,然后taro init 命令创建初始化项目后,项目根本跑步起来。缺少各种依赖...无语了...😶

前情回顾

昨天发的牢骚里感觉Vue的三个功能是解析并渲染html模板解析并执行js解析并渲染css样式。然后有个核心概念vdom,那么这个虚拟dom(vdom)在代码里是怎么体现的呢。一起来看下。

vdom文件夹

如图:

从上至下,helpers文件夹定义了一些类似工具方法的函数,比如:提取props,合并hooks,解析异步组件,更新侦听器modules文件夹定义了指令ref相关的内容。三个create-**.js定义了组件、元素、函数组件的创建方法。patch.js则是虚拟dom的diff算法。vnode.js则是对虚拟dom的定义。

vnode的定义

从代码里看,vnode是一个类似如下的对象:

代码语言:javascript
复制
let myNode = {
  tag:'div',
  data:{
    key:'1',
    tag:'div',
    class:"box-wrapper",
    style:{width:'100%'},
    props:{
      name:'terrene',
    },
    attrs:{
      alt:'pic'
    },
    on:{
      click:()=>{console.log('click')}
    },
    
  },
  children:[]
}

这个对象写出来以后,很容易联想到我们有时候在遇到vue表格自定义内容的时候,有时候会写一个render函数,通常用h('div',{...})来表示,这个h函数里面其实就是这个vnode对象

创建vnode

创建vnode实际上就是对vnode构造函数进行实例化。比如创建一个emptyNode(空节点)

代码语言:javascript
复制
export const createEmptyVNode = (text: string = '') => {
// 这里进行实例化操作
  const node = new VNode()
  node.text = text
  node.isComment = true
  return node
}

再比如创建一个文本节点textNode

代码语言:javascript
复制
export function createTextVNode (val: string | number) {
// 又是一个实例化操作
  return new VNode(undefined, undefined, undefined, String(val))
}

同理,创建组件也是对vnode进行实例化的过程。但是由于组件包含了生命周期,实例化的过程中会将生命周期的钩子函数merge进去。

创建函数式组件

函数式组件先是定义了一个类vnode的构造函数,然后构造函数返回了一个由createElement方法生成的一个vnode实例。

代码语言:javascript
复制
function FunctionalRenderContext (
  data,
  props,
  children,
  parent,
  Ctor
) {
  const options = Ctor.options
  this.data = data
  this.props = props
  this.children = children
  this.parent = parent
  this.listeners = data.on || emptyObject
  this.injections = resolveInject(options.inject, parent)
  this.slots = () => resolveSlots(children, parent)

  // ensure the createElement function in functional components
  // gets a unique context - this is necessary for correct named slot check
  const contextVm = Object.create(parent)
  const isCompiled = isTrue(options._compiled)
  const needNormalization = !isCompiled

  // support for compiled functional template
  if (isCompiled) {
    // exposing $options for renderStatic()
    this.$options = options
    // pre-resolve slots for renderSlot()
    this.$slots = this.slots()
    this.$scopedSlots = data.scopedSlots || emptyObject
  }

  if (options._scopeId) {
    this._c = (a, b, c, d) => {
      const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
      if (vnode) {
        vnode.functionalScopeId = options._scopeId
        vnode.functionalContext = parent
      }
      return vnode
    }
  } else {
    this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization)
  }
}

createFunctionalComponent函数返回了这个构造函数的实例。

代码语言:javascript
复制
export function createFunctionalComponent (
  Ctor: Class<Component>,
  propsData: ?Object,
  data: VNodeData,
  contextVm: Component,
  children: ?Array<VNode>
): VNode | void {
  const options = Ctor.options
  const props = {}
  const propOptions = options.props
  if (isDef(propOptions)) {
    for (const key in propOptions) {
      props[key] = validateProp(key, propOptions, propsData || emptyObject)
    }
  } else {
    if (isDef(data.attrs)) mergeProps(props, data.attrs)
    if (isDef(data.props)) mergeProps(props, data.props)
  }
// 实例化FunctionalRenderContext
  const renderContext = new FunctionalRenderContext(
    data,
    props,
    children,
    contextVm,
    Ctor
  )
// 这里进行返回
  const vnode = options.render.call(null, renderContext._c, renderContext)

  if (vnode instanceof VNode) {
    vnode.functionalContext = contextVm
    vnode.functionalOptions = options
    if (data.slot) {
      (vnode.data || (vnode.data = {})).slot = data.slot
    }
  }

  return vnode
}

思考

源码是个工程化的东西,里面的逻辑非常复杂,而且方法的调用都是彼此相互引用。比如vdom中有很多地方也用到了lifecycle的方法。而lifecycle本身也是个非常复杂的东西。

这篇内容大致介绍了vdom中涉及的内容以及vdom的创建。细节部分接下来会慢慢的拆解。

javascript基础知识总结

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JavaScript高级程序设计 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前情回顾
  • vdom文件夹
  • vnode的定义
  • 创建vnode
  • 创建函数式组件
  • 思考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档