文章目录
组件名
使用 kebab-case:
- 定义:
app.component('my-component-name', {/* ... */})
- 引用:
<my-component-name></my-component-name>
使用 PascalCase:
- 定义:
app.component('MyComponentName', {/* ... */})
- 引用:
<my-component-name>
活<MyComponentName>
注意:直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的
全局注册:Vue.component(name, options)
全局注册的组件可以在应用中的任何组件的模板中使用。
注意:
- 全局组件实际未使用到的也会打包进 js 包中,无法被摇树 tree-shaking
- 全局组件依赖关系不明显,不容易定位组件的实现,长期使用影响维护性
main 注册组件
MyComponent.vue
<template>
<div>my-component</div>
</template>
main.ts
import { createApp } from 'vue'
import App from './App.vue'
import MyComponent from './MyComponent.vue'
const app = createApp(App)
// 注意:在 main.ts 引入全局组件时,组件需要在 createApp(App) 后面 mount 前面
app.component('MyComponent', MyComponent).mount('#app')
批量注册组件
可以参考element ui 其实就是遍历一下然后通过 app.component 注册
局部注册:components
选项
方式一:
<div id="app">
<component-a></component-a>
</div>
<script>
const ComponentA = {
/* ... */
};
const app = Vue.createApp({
components: {
"component-a": ComponentA,
"component-b": ComponentB,
},
});
app.mount("#app");
</script>
方式二:引入外部组件
使用 <script setup>
语法糖中引入局部组件,无需注册
<div id="app">
<component-a></component-a>
</div>
<script setup lang="ts">
import ComponentA from "./ComponentA.vue";
</script>
选项式写法与 Vue2 一致
<div id="app">
<component-a></component-a>
</div>
<script>
import ComponentA from "./ComponentA.vue";
export default {
components: { ComponentA },
};
</script>
注意项:
特殊元素限制
有些 HTML 元素,诸如 <ul>
、<ol>
、<table>
和 <select>
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>
、<tr>
和 <option>
,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
<table>
<blog-post-row></blog-post-row>
</table>
<ul>
<blog-post-row></blog-post-row>
</ul>
这个自定义组件 <blog-post-row>
会被作为无效的内容提升到外部,并导致最终渲染结果出错。我们可以使用特殊的 v-is
指令作为一个变通的办法:
<table>
<tr v-is="'blog-post-row'"></tr>
</table>
<ul>
<li v-id="'blog-post-row'"></li>
</ul>
v-is
值应为 JavaScript 字符串文本:<tr v-is="'blog-post-row'"></tr>
注意单引号。
错误写法<tr v-is="blog-post-row"></tr>
不会渲染任何东西。
元素属性名限制
HTML attribute 名不区分大小写,因此浏览器将所有大写字符解释为小写。这意味着当你在 DOM 模板中使用时,驼峰 prop 名称和 event 处理器参数需要使用它们的 kebab-cased (横线字符分隔) 等效值:
// 在JavaScript中的驼峰
app.component("blog-post", {
props: ["postTitle"],
template: `<h3>{{ postTitle }}</h3>`,
});
<!-- 在HTML则是横线字符分割 -->
<blog-post post-title="hello!"></blog-post>
需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
- 字符串模板 (例如:
template: '...'
) - 单文件组件
<script type="text/x-template">