YoseZang 2022-09-28 21:44 采纳率: 87.5%
浏览 34
已结题

Vue CLI创建的项目的组件的问题

使用Vue CLI生成的项目,有个地方不理解,
在项目默认生成的App.vue中定义的组件,在main.js中加载,为什么在index中没有进行引用(没有相应的标签对),但是还是加载了呢?

App.vue中默认定义的组件如下:

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

通过main.js进行挂载:

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

首页(index.html)的代码如下(body部分):

  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    
  </body>

1)按理说根元素App不应该包含template
2)id为app的元素里面没有引用某个组件啊(里面没有元素内容),但是渲染之后装载了App.vue定义的组件模板
这两个问题求解释,谢谢

  • 写回答

2条回答 默认 最新

  • MAXLZ 2022-09-29 01:58
    关注

    第一个问题:首先template只是一种声明式的模板语法,关于组件的写法,可以不使用template,你可以使用h渲染函数或jsx都ok。template的写法会更接近html,而且在编译时,会进行一些编译优化。那么App可以不包含template吗?可以,如果App根组件不是函数式组件或不存在template和渲染函数,那么会将#app的innerHTML属性作为template。下面是mount过程的部分源码

    
    const component = app._component
    if (!isFunction(component) && !component.render && !component.template) {
      // 将container.innerHTML作为根组件的template属性
      component.template = container.innerHTML
      //...
    }
    

    第二个问题:#app为什么没有显示引用组件。在main.js中会执行一个mount方法,这个mount方法会将App渲染出来的dom整个挂在到#app上。下面是mount方法的源码,其中的render就是渲染dom并挂载到#app的核心

    
    mount(
      rootContainer: HostElement,
      isHydrate?: boolean,
      isSVG?: boolean
    ): any {
      if (!isMounted) {
        if (__DEV__ && (rootContainer as any).__vue_app__) {
          warn(
            `There is already an app instance mounted on the host container.\n` +
            ` If you want to mount another app on the same host container,` +
            ` you need to unmount the previous app by calling \`app.unmount()\` first.`
          )
        }
        const vnode = createVNode(
          rootComponent as ConcreteComponent,
          rootProps
        )
        vnode.appContext = context
    
        if (__DEV__) {
          context.reload = () => {
            render(cloneVNode(vnode), rootContainer, isSVG)
          }
        }
    
        if (isHydrate && hydrate) {
          hydrate(vnode as VNode<Node, Element>, rootContainer as any)
        } else {
          render(vnode, rootContainer, isSVG)
        }
        isMounted = true
        app._container = rootContainer
        ;(rootContainer as any).__vue_app__ = app
    
        if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
          app._instance = vnode.component
          devtoolsInitApp(app, version)
        }
    
        return getExposeProxy(vnode.component!) || 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)\``
        )
      }
    }
    
    

    如果你对vue3源码感兴趣,可以关注我,目前我正在更新vue3源码系列文章

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月3日
  • 已采纳回答 10月3日
  • 创建了问题 9月28日

悬赏问题

  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端