Vue3全局组件注册的实现代码
1. 全局组件注册
组件注册在Vue
的官方文档中有详细的介绍,我们可以通过app.component
方法来注册一个全局组件,如下所示:
import { createApp } from 'vue' const app = createApp({}) app.component('component-a', { /* ... */ })
注册组件在Vue
中是非常简单的一个操作,但是在Vue3
中,我们需要知道的是,Vue3
是如何将我们注册的组件挂载到app
实例上的呢?
参考链接
2. 全局组件注册实现
我们可以在组件注册的代码上面打上断点,在浏览器中执行一下,然后我们就可以看到Vue3
是如何将我们注册的组件挂载到app
实例上的了。
当我们跟踪进入component
方法中,可以看到源码实现很少,如下所示:
function component(name, component) { { // 1. 校验组件名称是否合法 validateComponentName(name, context.config); } // 2. 如果没有传递组件,则返回已经注册的组件 if (!component) { return context.components[name]; } // 3. 如果传递了组件,并且组件已经注册,则打印警告信息提示组件已经注册 if (context.components[name]) { warn(`Component "${name}" has already been registered in target app.`); } // 4. 将组件直接赋值给 app 实例的 components 属性中 context.components[name] = component; // 5. 返回 app 实例 return app; }
组件注册整体来说是非常简单的一个操作,我们可以看到,Vue3
在注册组件的时候,主要做了以下几件事情:
- 校验组件名称是否合法
- 如果没有传递组件,则返回已经注册的组件,这一步对应着已注册组件的获取
- 如果传递了组件,并且组件已经注册,则打印警告信息提示组件已经注册,这里少提示了一个警告信息,就是会将已注册的组件覆盖
- 将组件直接赋值给 app 实例的 components 属性中,这里只是缓存下来,并不会使用
- 返回 app 实例,这里返回 app 实例主要是用于链式调用
3. 组件名称规则
在Vue
的风格指南中有明确的组件名称规则,而在组件注册的第一步也是校验组件名称是否合法,那么我们就来看一下Vue
的组件名称规则。
我们可以继续跟随源码来查看validateComponentName
方法的实现,如下所示:
function validateComponentName(name, config) { // 1. 获取内部配置的 isNativeTag 方法来判断是否是 HTML 原生标签 const appIsNativeTag = config.isNativeTag || NO; // 2. 判断组件名是否是内置的标签名或者是原生标签名 if (isBuiltInTag(name) || appIsNativeTag(name)) { // 3. 如果是内置的标签名或者是原生标签名,则打印警告信息 warn( "Do not use built-in or reserved HTML elements as component id: " + name ); } }
我们可以看到,Vue
的组件名称规则主要是校验组件名称是否是内置的标签名或者是原生标签名,如果是,则会打印警告信息。
isNativeTag
的配置在官网中并没有明确的说明,我们可以继续跟踪源码来查看isNativeTag
的实现,如下所示:
function injectNativeTagCheck(app) { Object.defineProperty(app.config, "isNativeTag", { value: (tag) => isHTMLTag(tag) || isSVGTag(tag), writable: false }); }
它是通过Object.defineProperty
方法来定义的,并且writable
为false
表示不可修改,我们可以看到,isNativeTag
的实现是通过isHTMLTag
和isSVGTag
来判断的;
这里就没有必要在继续看了,反正我们熟知的div/span/button
等等html
标签肯定是不行的,然后就是svg/path/group
等等svg
标签也是不行的,这里就不一一列举了。
再就是isBuiltInTag
他是通过makeMap
方法来实现的。
const isBuiltInTag = /* @__PURE__ */ makeMap("slot,component");
这里只有两个组件,一个是slot
,一个是component
,不知道为什么不包含transition
,这里就不深究了。
风格指南参考链接:
Vue3 的风格指南对比 Vue2 的风格指南少了很多,但是核心理念还是一致的,所以我们可以参考 Vue2 的风格指南来学习 Vue3 的风格指南。
4. 组件挂载
在我们之前的章节中也讲过组件的挂载,但是那个讲的是一个组件是如何挂载到页面上的,并没有涉及到组件是如何从实例中获取的,这次我们就来看一下组件是如何从实例中获取的。
根据我们之前学习的章节,我们知道一个组件最后会通过createVNode
方法来创建一个虚拟节点,然后通过render
方法来渲染到页面上;
而虚拟节点上会有一个type
属性和一个shapeFlag
属性,type
属性就是我们的组件,shapeFlag
属性就是一个标识,用于标识当前节点的类型。
而我们的组件最后在Vue
的内部都是以对象的型式存在,所以shapeFlag
的值通常是4
,表示是一个对象,所以最后会执行到mountComponent
方法中;
这里的组件是直接通过生成子树,然后将子树进行patch
的方式来挂载的,本质上是和普通的元素挂载是一样的;
由于这一块我们是用模板语法来进行组件的使用的,这里的逻辑会比较复杂,在上面的组件挂载的文章中不能完全体现, 模板本质是一个字符串,最后会转换成一个
ast
之后进行组件的匹配和挂载,内容量会比较大,所以会在下一章进行详细分析;
5. 总结
在这篇文章中,我们学习了Vue3
的全局组件注册是如何实现的,主要是通过app.component
方法来实现的,component
方法内部实现很简单,主要有两个功能:
- 注册组件,但是组件只是以对象的方式缓存在
app
实例的components
属性中,并没有使用; - 获取已经注册的组件,如果没有传递组件,则通过组件名称获取已经注册的组件,这一步就是一个函数重载;
而组件挂载的过程和普通元素的挂载是一样的,都是通过patch
的方式来进行的,这里就不再赘述了。
以上就是Vue3全局组件注册的实现代码的详细内容,更多关于Vue3全局组件注册的资料请关注脚本之家其它相关文章!
相关文章
Vue3 elementUI 中 date-picker 使用过程遇到坑
这篇文章主要介绍了Vue3 elementUI 中 date-picker 使用过程遇到坑,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧2023-10-10vue3+ts重复参数提取成方法多处调用以及字段无值时不传字段给后端问题
在进行API开发时,优化参数传递是一个重要的考量,传统方法中,即使参数值为空,也会被包含在请求中发送给后端,这可能会导致不必要的数据处理,而优化后的方法则只会传递那些实际有值的字段,从而提高数据传输的有效性和后端处理的效率2024-10-10VUE中对object.object和object[object]的使用解读
这篇文章主要介绍了VUE中对object.object和object[object]的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-06-06
最新评论