组件基础
一、定义一个组件
- 1、使用构建步骤,定义在一个单独的 .vue 文件中,这被叫做单文件
组件 (简称 SFC):
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">You clicked me {{ count }} times.</button>
</template>
- 2、不使用构建步骤时,一个 Vue 组件以一个包含 Vue 特定选项的 JavaScript 对象来定义:
- 这里的模板是一个内联的 JavaScript 字符串,Vue 将会在运行时编译它。你也可以使用 ID 选择器来指向一个元素 (通常是原生的 <template> 元素),Vue 将会使用其内容作为模板来源。
- 上面的例子中定义了一个组件,并在一个 .js 文件里默认导出了它自己,但你也可以通过具名导出在一个文件中导出多个组件。
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return { count }
},
template: `
<button @click="count++">
You clicked me {{ count }} times.
</button>`
}
二、全局注册
- 使用 Vue 应用实例的 .component() 方法,让组件在当前 Vue 应用中全局可用。
- 全局注册,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。
import MyComponent from './MyComponent.vue';
app.component('MyComponent', MyComponent);
app
.component('ComponentA', ComponentA)
.component('ComponentB', ComponentB)
.component('ComponentC', ComponentC)
三、使用组件
- 通过 <script setup>,导入的组件都在模板中直接可用。
- 全局注册的组件无需引入。
<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>
<template>
<h1>Here is a child component!</h1>
<ButtonCounter />
</template>
- 如果没有使用 <script setup>,则需要使用 components 选项来显式注册:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
setup() { }
}
- 如果你是直接在 DOM 中书写模板 (例如原生 <template> 元素的内容),模板的编译需要遵从浏览器中 HTML 的解析行为。
- 在这种情况下,你应该需要使用 kebab-case 形式并显式地关闭这些组件的标签。
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
四、组件名格式
- 在整个指引中,我们都使用 PascalCase 作为组件名的注册格式,这是因为:
- 1.PascalCase 是合法的 JavaScript 标识符。这使得在 JavaScript 中导入和注册组件都很容易,同时 IDE 也能提供较好的自动补全。
- 2. 在模板中更明显地表明了这是一个 Vue 组件,而不是原生 HTML 元素。同时也能够将 Vue 组件和自定义元素 (web components) 区分开来。
- 在单文件组件和内联字符串模板中,我们都推荐这样做。但是,PascalCase 的标签名在 DOM 内模板中是不可用的。
- Vue 支持将模板中使用 kebab-case 的标签解析为使用 PascalCase 注册的组件。这意味着一个以 MyComponent 为名注册的组件,在模板中可以通过 <MyComponent> 或 <my-component> 引用
五、插槽来分配内容
<AlertBox>
Something bad happened.
</AlertBox>
<template>
<div class="alert-box">
<strong>This is an Error for Demo Purposes</strong>
<slot />
</div>
</template>
六、动态组件
- 通过 Vue 的 <component :is="..."> 元素和特殊的 is attribute 实现的:
- :is 的值可以是:被注册的组件名、导入的组件对象
<component :is="componentName"></component>
- 当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载。我们可以通过 组件强制被切换掉的组件仍然保持“存活”的状态。
<KeepAlive>
<component :is="activeComponent" />
</KeepAlive>
1、DOM 内模板解析注意事项
- 如果你想在 DOM 中直接书写 Vue 模板,Vue 则必须从 DOM 中获取模板字符串。由于浏览器的原生 HTML 解析行为限制,有一些需要注意的事项。
- 请注意下面讨论只适用于直接在 DOM 中编写模板的情况。如果你使用来自以下来源的字符串模板,就不需要顾虑这些限制了:
- 单文件组件
- 内联模板字符串 (例如 template: '...')
- <script type="text/x-template">
2、大小写区分
- HTML 标签和属性名称是不分大小写的,所以浏览器会把任何大写的字符解释为小写。这意味着当你使用 DOM 内的模板时,无论是 PascalCase 形式的组件名称、camelCase 形式的 prop 名称还是 v-on 的事件名称,都需要转换为相应等价的 kebab-case (短横线连字符) 形式:
// JavaScript 中的 camelCase
const BlogPost = {
props: ['postTitle'],
emits: ['updatePost'],
template: `
<h3>{{ postTitle }}</h3>
`
}
<blog-post post-title="hello!" @update-post="onUpdatePost"></blog-post>
3、闭合标签
- Vue 的模板解析器支持任意标签使用 /> 作为标签关闭的标志
<MyComponent />
- 然而在 DOM 内模板中,我们必须显式地写出关闭标签:
<my-component></my-component>
4、元素位置限制
- 某些 HTML 元素对于放在其中的元素类型有限制,例如 <ul>,<ol>,<table> 和 <select>,相应的,某些元素仅在放置于特定元素中时才会显示,例如 <li>,<tr> 和 <option>。
- 这将导致在使用带有此类限制元素的组件时出现问题。例如:
<table>
<blog-post-row></blog-post-row>
</table>
- 自定义的组件 <blog-post-row> 将作为无效的内容被忽略,因而在最终呈现的输出中造成错误。我们可以使用特殊的 is attribute 作为一种解决方案:
<table>
<tr is="vue:blog-post-row"></tr>
</table>