IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue3组件初始化流程(四): 解决todo:applyOptions对Vue2写法的兼容 initProps Slots [Vue3源码系列_xiaolu] -> 正文阅读

[JavaScript知识库]Vue3组件初始化流程(四): 解决todo:applyOptions对Vue2写法的兼容 initProps Slots [Vue3源码系列_xiaolu]


theme: vuepress
highlight: androidstudio

解决todo

这一章我们来解决前面留下的部分todo

getExposeProxy

getExposeProxy方法 路径: core\packages\runtime-core\src\component.ts

export function getExposeProxy(instance: ComponentInternalInstance) {
  // 判断exposed是否存在
  if (instance.exposed) {
    //todo To: 返回通过proxyRefs 和markRaw处理的
    return (
      instance.exposeProxy ||
      (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {
        get(target, key: string) {
          if (key in target) {
            return target[key]
          } else if (key in publicPropertiesMap) {
            return publicPropertiesMap[key](instance)
          }
        }
      }))
    )
  }
}

才看一步,我们又看到了proxyRefs和markRaw(涉及响应式),因此留下todo

createSetupContext

createSetupContext方法 路径: core\packages\runtime-core\src\component.ts

export function createSetupContext(
  instance: ComponentInternalInstance
): SetupContext {
  // 初始化expose
  const expose: SetupContext['expose'] = exposed => {
    instance.exposed = exposed || {}
  }

  let attrs: Data
  if (__DEV__) {

  } else {
    // 返回包含attrs slots emit expose的对象
    return {
      get attrs() {
        return attrs || (attrs = createAttrsProxy(instance))
      },
      slots: instance.slots,
      emit: instance.emit,
      expose
    }
  }
}

createSetupContext方法做了什么?

功能: 返回一个包含attrs slots emit expose的对象,也就是我们使用的setup的第二个参数

对这个方法的分析我都写在了注释上,因为涉及太多的方法跳转

这一步的注释在 初始化setupContext

initProps

initProps方法 路径: core\packages\runtime-core\src\componentProps.ts

export function initProps(
  instance: ComponentInternalInstance,
  rawProps: Data | null,
  isStateful: number, // result of bitwise flag comparison
  isSSR = false
) {
  const props: Data = {}
  const attrs: Data = {}
  def(attrs, InternalObjectKey, 1)

  instance.propsDefaults = Object.create(null)

  setFullProps(instance, rawProps, props, attrs)

  // ensure all declared prop keys are present
  for (const key in instance.propsOptions[0]) {
    if (!(key in props)) {
      props[key] = undefined
    }
  }

  if (isStateful) {
    // stateful
    instance.props = isSSR ? props : shallowReactive(props)
  } else {
    if (!instance.type.props) {
      // functional w/ optional props, props === attrs
      instance.props = attrs
    } else {
      // functional w/ declared props
      instance.props = props
    }
  }
  instance.attrs = attrs
}

initProps方法做了什么?

功能: 初始化并拆分props、attrs,并对default做了处理,prop大小写进行了处理

对这个方法的分析我都写在了注释上(和initSlots在一起),因为涉及太多的方法跳转

initSlots

initSlots方法 路径: core\packages\runtime-core\src\componentSlots.ts

export const initSlots = (
  instance: ComponentInternalInstance,
  children: VNodeNormalizedChildren
) => {
  if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
    const type = (children as RawSlots)._
    if (type) {
      // users can get the shallow readonly version of the slots object through `this.$slots`,
      // we should avoid the proxy object polluting the slots of the internal instance
      instance.slots = toRaw(children as InternalSlots)
      // make compiler marker non-enumerable
      def(children as InternalSlots, '_', type)
    } else {
      normalizeObjectSlots(
        children as RawSlots,
        (instance.slots = {}),
        instance
      )
    }
  } else {
    instance.slots = {}
    if (children) {
      normalizeVNodeSlots(instance, children)
    }
  }
  def(instance.slots, InternalObjectKey, 1)
}

initSlots方法做了什么?

功能: 初始化slots

这一步注释在: initProps和initSlots

applyOptions

applyOptions方法 路径: core\packages\runtime-core\src\componentOptions.ts

export function applyOptions(instance: ComponentInternalInstance) {

  const options = resolveMergedOptions(instance)
  const publicThis = instance.proxy! as any
  const ctx = instance.ctx

  shouldCacheAccess = false

  if (options.beforeCreate) {
    callHook(options.beforeCreate, instance, LifecycleHooks.BEFORE_CREATE)
  }

  const {

    data: dataOptions,
    computed: computedOptions,
    methods,
    watch: watchOptions,
    provide: provideOptions,
    inject: injectOptions,

    created,
    beforeMount,
    mounted,
    beforeUpdate,
    updated,
    activated,
    deactivated,
    beforeDestroy,
    beforeUnmount,
    destroyed,
    unmounted,
    render,
    renderTracked,
    renderTriggered,
    errorCaptured,
    serverPrefetch,
    // public API
    expose,
    inheritAttrs,
    // assets
    components,
    directives,
    filters
  } = options


  if (injectOptions) {}

  if (methods) {}

  if (dataOptions) {}

  shouldCacheAccess = true

  if (computedOptions) {}
  
  if (watchOptions) {}

  if (provideOptions) {}

  if (created) {
    callHook(created, instance, LifecycleHooks.CREATED)
  }

  function registerLifecycleHook(
    register: Function,
    hook?: Function | Function[]
  ) {
    if (isArray(hook)) {
      hook.forEach(_hook => register(_hook.bind(publicThis)))
    } else if (hook) {
      register((hook as Function).bind(publicThis))
    }
  }

  registerLifecycleHook(onBeforeMount, beforeMount)
  registerLifecycleHook(onMounted, mounted)
  registerLifecycleHook(onBeforeUpdate, beforeUpdate)
  registerLifecycleHook(onUpdated, updated)
  registerLifecycleHook(onActivated, activated)
  registerLifecycleHook(onDeactivated, deactivated)
  registerLifecycleHook(onErrorCaptured, errorCaptured)
  registerLifecycleHook(onRenderTracked, renderTracked)
  registerLifecycleHook(onRenderTriggered, renderTriggered)
  registerLifecycleHook(onBeforeUnmount, beforeUnmount)
  registerLifecycleHook(onUnmounted, unmounted)
  registerLifecycleHook(onServerPrefetch, serverPrefetch)

  if (isArray(expose)) {}

  if (render && instance.render === NOOP) {}
  if (inheritAttrs != null) {}

  if (components) instance.components = components as any
  if (directives) instance.directives = directives
}

applyOptions方法做了什么?

功能: 这是对Vue2.0写法进行兼容处理

  1. data的处理就是将data调用之后的结果进行reactive包裹进行响应式处理
  2. methods的处理就是遍历给methods修改this指向
  3. computed的处理就是通过computed包裹,并且处理get、set的情况
  4. 以及其他更多方法都写在了注释里

只要知道对Vue2的写法兼容是在这个applyOptions方法里完成的就行了

这次的注释在applyOptions

剩下的todo

解决了这几个todo之后,现在来看剩下的todo,如图

QQ截图20220403130534.png

可以看到,现在的todo都指向了一个模块: reactivity(响应式模块)

是的,这也是我们接下来的目标,响应式

到此,Vue3组件初始化流程完结,敬请期待下一期的Vue3响应式模块

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:02:05  更:2022-04-04 12:03:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:28:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码