vue的create(create vue app)

今天来看下 Vue3 在 createApp 这个方法执行的时候,都执行了哪些步骤?

我们先来初始化一个应用:
import { createApp, ref } from \\\'vue\\\'createApp({  setup(){    const hello = ref(\\\'this is vue3\\\');    return { hello }    }}).mount(\\\'#app\\\')
从 vue 中我们导出了 createApp 方法,用来包装项目「方法」和「初始化参数」。我们去源码文件看下:
//...args就是 setup 里面编写的代码const createApp = ((...args) => {  const app = ensureRenderer().createApp(...args)})
我们在 createApp 里写的方法都当做参数传了进去。ensureRenderer() 方法执行「baseCreateRenderer」方法,里面封装了渲染的核心逻辑。
    function baseCreateRenderer(  options: RendererOptions,  createHydrationFns?: typeof createHydrationFunctions): any {  //move方法     //patch方法   //render方法   //...      return {    render,    hydrate,    createApp: createAppAPI(render, hydrate)  }}
    我们看到 createApp 其实执行的是 createAppAPI 方法,并且把 render 方法和 hydrate 传递了过去。
    在 createAppAPI 内部又返回了 createApp 方法,此方法接收两个参数「根组件、根 props」,声明 app 并注册方法和属性返回它。
    export function createAppAPI<HostElement>(  render: RootRenderFunction,  hydrate?: RootHydrateFunction){  //接收两个参数:根组件和根props  return function createApp(rootComponent, rootProps = null) {    const app: App = (context.app = {      _uid: uid++,      _component: rootComponent as ConcreteComponent,      _props: rootProps,      _container: null,      _context: context,      version,      //... use、mixin、directive、mount、unmount、provide      return app    })      }  }
    我们传递的根组件和根props,来源于我们页面中 createApp 里声明的方法,如最上面代码里的 setup 函数当做参数传进了 createApp 函数里。最后返回的 app 是被包装过的。

    给 app 赋了值,随即执行了 app.mount 方法。方法内部逻辑:
    app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {  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.innerHTML = \\\'\\\'  const proxy = mount(container)  if (container instanceof Element) {    container.removeAttribute(\\\'v-cloak\\\')    container.setAttribute(\\\'data-v-app\\\', \\\'\\\')  }  return proxy}
    传入一个参数:containerOrSelector,这个参数可以是 Element、ShadowRoot 或者 string,去判断是否可以拿到传入的节点。如果不能拿到节点,返回错误信息,并且中断执行。
    如果 app._component 不是函数,并且也没有定义 render 方法和 template 模板标签,就直接把 innerHTML 赋值给 template。
    当拿到里面的内容后,就可以把根组件的内容清空了。
    还记得我们在页面中显示的 {{}} 括号么?在 app.mount 方法内部就处理了。我们在css 里面写:
    [v-cloak] {    display: none !important;}<div id=\\\"app\\\" v-cloak></div>
    先在挂载目标上隐藏它的显示,然后等 mount 挂载完成,再把 v-cloak 这个属性清除掉,这样就去掉了 {{}} 括号在页面的显示。
    它其实本质上没有去掉括号,只是不再显示挂载标签内容了而已。先隐藏我们的挂载目标,等挂载完成再显示出来。
    container.removeAttribute(\\\'v-cloak\\\')
    简单的梳理了一下 createApp 的执行逻辑。里面涉及到的细节知识实在太多了,我们需要一点一点的分析,一点点的拆开深入内部去了解。

    我会按执行逻辑,一步步分析 Vue3 源码,并持续输出为文字或视频。

    点击关注公众号,查看更多 Vue 的内容

    图片授权基于 www.pixabay.com 相关协议

    原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34474.html

    (0)
    小道研究's avatar小道研究
    上一篇 2024年4月11日 上午6:02
    下一篇 2024年4月11日 上午6:04

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注