VUE3-createApp的源码原理

creatApp的源码原理

// 1.创建app对象
  // ensureRenderer() ,和渲染相关的代码都在这里,待会儿我们会读到
  const app = ensureRenderer().createApp(...args)

  if (__DEV__) {
    injectNativeTagCheck(app)
    injectCustomElementCheck(app)
  }

  // 2.这里取出了app中的mount方法,因为待会儿要进行重写
  const { mount } = app

  // 3.重写mount方法
  // 这里重写的目的是考虑到跨平台(app.mount里面只包含和平台无关的代码)
  // 这些重写的代码都是一些和web关系比较大的代码(比如其他平台也可以进行类似的重写)
  app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
    // normalizeContainer方法就是在web端获取我们的元素,比如div#app
    const container = normalizeContainer(containerOrSelector)
    if (!container) return
    const component = app._component
    if (!isFunction(component) && !component.render && !component.template) {
      component.template = container.innerHTML
    }
    // clear content before mounting
    // 先清空container中的原本内容
    container.innerHTML = ''
    // 调用真正的mount函数, 进行挂载
    const proxy = mount(container, false, container instanceof SVGElement)
    if (container instanceof Element) {
      container.removeAttribute('v-cloak')
      container.setAttribute('data-v-app', '')
    }
    return proxy
  }

  // 3.返回app
  return app
}) as CreateAppFunction<Element>

组件的vNode和组件的instance有什么区别
Vnode是虚拟DOM,形成树构造的一个个节点
instance是保存组件的各种状态

template有多个根节点处理情况
runtime-core→renderer.ts→baseCreateRenderer→patch
会被当成Fragment组件节点包裹处理

1、createApp
2、app.mount
3、rerender的render
4、再调用patch函数 判断类型
5、是组件类型就调用processComponent,看组件有没有挂载
6、没有挂载就调用mountComponent
7、创建组件实例Instance
8、初始化setupComponent(instance)
9、setuprerenderEffet()判断有没有挂载
10、没有挂载就取出subtree
11、再次来到patch判断el
12、通过processElement来处理
13、通过创建document.createElement()
14、有子节点的情况下就调用mountChildren,for循环拿到一个个小children再次调用patch(null,children),判断是组件还是元素

通过render函数生成vNode的时候会有以下情况:
1、对于不会改变的静态节点,进行作用域的提升,不会生成vnode
2、diff算法,patch操作不会对静态节点进行操作,diff那些有可能修改的vnode,

let normalizedProps
    if (key[0] !== '$') {
      const n = accessCache![key]
      if (n !== undefined) {
        switch (n) {
          case AccessTypes.SETUP:
            return setupState[key]
          case AccessTypes.DATA:
            return data[key]
          case AccessTypes.CONTEXT:
            return ctx[key]
          case AccessTypes.PROPS:
            return props![key]
          // default: just fallthrough
        }
      } else if (setupState !== EMPTY_OBJ && hasOwn(setupState, key)) {
        accessCache![key] = AccessTypes.SETUP
        return setupState[key]
      } else if (data !== EMPTY_OBJ && hasOwn(data, key)) {
        accessCache![key] = AccessTypes.DATA
        return data[key]
      } else if (
        // only cache other properties when instance has declared (thus stable)
        // props
        (normalizedProps = instance.propsOptions[0]) &&
        hasOwn(normalizedProps, key)
      ) {
        accessCache![key] = AccessTypes.PROPS
        return props![key]
      } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {
        accessCache![key] = AccessTypes.CONTEXT
        return ctx[key]
      } else if (!__FEATURE_OPTIONS_API__ || shouldCacheAccess) {
        accessCache![key] = AccessTypes.OTHER
      }
    }

根据源码展示:查找值的优先顺序是:$全局>setUp>data>prop>context(methods、computed)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值