Vue3.0 渲染流程(二)

上一篇文章(https://blog.csdn.net/liubangbo/article/details/112792345)分析了渲染流程大体过程,这一篇文章分析一下创建VNode过程,以及渲染VNode过程。

分析之前还是先贴一下我们那个最简单的例子:

​
<html>
  <head>
    <style type="text/css">
    </style>
  </head>

  <body>
    <div id="app">
      <div>hello {{state.msg}}</div>
    </div>
    <script src="../dist/vue.global.js"></script>
    <script>
      const {createApp, ref, reactive} = Vue
      
      const app = createApp({
        setup(){                 
          const state = reactive({
            msg: 'Vue3.0'
          })          
          const num = ref(10)
          return {state}
        },                
      }, {style: {
        color: 'red'
      }}).mount('#app')   
          
    </script>
  </body>
</html>

细心的读者会发现,例子有点变动。我们给createApp方法传入了第二个参数,通过运行可以看到渲染出了红色字体。我们从createApp返回的app对象的mount方法开始分析。mount方法代码如下:

      mount(rootContainer: HostElement, isHydrate?: boolean): any {
        //rootContainer参数就是要挂载的Dom节点(app节点)
        if (!isMounted) {
          //传给createVNode的参数rootComponent就是createApp第一个参数,rootProps参数就是createApp的第二个参数
          const vnode = createVNode(
            rootComponent as ConcreteComponent,
            rootProps
          )
          // store app context on the root VNode.
          // this will be set on the root instance on initial mount.
          vnode.appContext = context

          // HMR root reload
          if (__DEV__) {
            context.reload = () => {
              render(cloneVNode(vnode), rootContainer)
            }
          }

          if (isHydrate && hydrate) {
            hydrate(vnode as VNode<Node, Element>, rootContainer as any)
          } else {
            render(vnode, rootContainer)
          }
          isMounted = true
          app._container = rootContainer
          // for devtools and telemetry
          ;(rootContainer as any).__vue_app__ = app

          if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
            devtoolsInitApp(app, version)
          }

          return vnode.component!.proxy
        } else if (__DEV__) {
          warn(
            `App has already been mounted.\n` +
              `If you want to remount the same app, move your app creation logic ` +
              `into a factory function and create fresh app instances for each ` +
              `mount - e.g. \`const createMyApp = () => createApp(App)\``
          )
        }
      },

rootComponent 通过调试可以看到:

rootProps通过调试可以看到:

 

先看看createVNode 这个方法:

export const createVNode = (__DEV__
  ? createVNodeWithArgsTransform
  : _createVNode) as typeof _createVNode

function _createVNode(
  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
  props: (Data & VNodeProps) | null = null,
  children: unknown = null,
  patchFlag: number = 0,
  dynamicProps: string[] | null = null,
  isBlockNode = false
): VNode {
  if (!type || type === NULL_DYNAMIC_COMPONENT) {
    if (__DEV__ && !type) {
      warn(`Invalid vnode type when creating vnode: ${type}.`)
    }
    type = Comment
  }
   
  //....
  // class & style normalization.
  // 对props进行了处理
  if (props) {
    // for reactive or proxy objects, we need to clone it to enable mutation.
    if (isProxy(props) || InternalObjectKey in props) {
      props = extend({}, props)
    }
    //从props对象中解构出class,style属性进行处理
    let { class: klass, style } = props
    if (klass && !isString(klass)) {
      props.class = normalizeClass(klass)
    }
    if (isObject(style)) {
      // reactive state objects need to be cloned since they are likely to be
      // mutated
      if (isProxy(style) && !isArray(style)) {
        style = extend({}, style)
      }
      props.style = normalizeStyle(style)
    }
  }

  // encode the vnode type information into a bitmap
  // 这里根据type类型 设置shapeFlag,就这个简单例子而言,shapeFlag是 
  // ShapeFlags.STATEFUL_COMPONENT
  const shapeFlag = isString(type)
    ? ShapeFlags.ELEMENT
    : __FEATURE_SUSPENSE__ && isSuspense(type)
      ? ShapeFlags.SUSPENSE
      : isTeleport(type)
        ? ShapeFlags.TELEPORT
        : isObject(type)
          ? ShapeFlags.STATEFUL_COMPONENT
          : isFunction(type)
            ? ShapeFlags.FUNCTIONAL_COMPONENT
            : 0
    const vnode: VNode = {
    __v_isVNode: true, //给vnode打上一个标记
    [ReactiveFlags.SKIP]: true, //这里设置这个对象应该不是reactive的
    type,
    props,
    key: props && normalizeKey(props), //props没有key属性返回null
    ref: props && normalizeRef(props), //props没有ref属性返回null
    scopeId: currentScopeId,
    children: null,
    component: null,
    suspense: null,
    ssContent: null,
    ssFallback: null,
    dirs: null,
    transition: null,
    el: null,
    anchor: null,
    target: null,
    targetAnchor: null,
    staticCount: 0,
    shapeFlag,
    patchFlag,
    dynamicProps,
    dynamicChildren: null,
    appContext: null
  }
  //最后把创建的vnode对象返回 
  return vnode

  创建vnode对象过程还是比较简单的,主要是处理了props,并且设置了shapeFlag,最后返回创建的vnode。接着往下走,

      mount(rootContainer: HostElement, isHydrate?: boolean): any {
        //rootContainer参数就是要挂载的Dom节点(app节点)
        if (!isMounted) {
          //传给createVNode的参数rootComponent就是createApp第一个参数,rootProps参数就是createApp的第二个参数
          const vnode = createVNode(
            rootComponent as ConcreteComponent,
            rootProps
          )
          // store app context on the root VNode.
          // this will be set on the root instance on initial mount.
          //给vnode的appContext属性赋值为之前创建的context,而context.app就是最开始的时候
          //创建的app对象,
          vnode.appContext = context

          // HMR root reload
          if (__DEV__) {
            context.reload = () => {
              render(cloneVNode(vnode), rootContainer)
            }
          }

          if (isHydrate && hydrate) {
            hydrate(vnode as VNode<Node, Element>, rootContainer as any)
          } else {
            //在这里开始进行渲染vnode
            render(vnode, rootContainer)
          }
          isMounted = true
          app._container = rootContainer

vnode.appContext = context  这行代码让vnode 拥有了 app对象,最后调用render函数进行vnode的渲染。我们下一篇文章继续分析vnode的patch过程。

如有需要可以关注作者公众号:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flowable是一个开源的低代码流程引擎,它可以帮助企业快速构建和管理各种业务流程。Vue 3.0是一种先进的JavaScript框架,用于构建现代化的用户界面。 Flowable Vue 3.0是将Flowable流程引擎与Vue 3.0框架集成在一起的解决方案。它提供了一个基于Web的用户界面,用于创建、管理和监控业务流程。通过Flowable Vue 3.0,用户可以通过直观的界面设计和配置各种业务流程,包括工作流、审批流程、订单处理流程等等。 Flowable Vue 3.0具有以下特点和优势: 1. 低代码开发:Flowable Vue 3.0提供了丰富的可视化工具和组件,使用户能够快速构建复杂的业务流程,减少开发时间和成本。 2. 灵活性和可扩展性:Flowable Vue 3.0借助Vue 3.0框架的优势,具备高度灵活性和可扩展性。用户可以根据自己的需求对界面进行定制和扩展,满足各种不同的业务需求。 3. 实时监控和报告:Flowable Vue 3.0提供了实时的流程监控和报告功能,用户可以及时了解流程的执行情况和指标,提高业务效率和管理能力。 4. 高度集成化:Flowable Vue 3.0可以与其他系统和工具集成,如数据库、企业资源规划系统(ERP)等,实现数据的共享和交换,提高整体业务的一致性和效率。 通过Flowable Vue 3.0,企业可以快速搭建和管理各类业务流程,提高工作效率和响应速度,降低人为错误的风险。同时也能够实现业务流程的可视化和集中控制,帮助企业进行业务优化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值