编辑
2023-02-13
前端
00
请注意,本文编写于 646 天前,最后修改于 643 天前,其中某些信息可能已经过时。

目录

组件结构
定义组件
使用构建步骤 .vue
不使用构建步骤 .js
注册组件
全局注册
局部注册
使用组件
传递 props
声明 props
子组件调用父组件方法修改父组件
插槽 slot
动态组件 :is

组件结构

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考

image.png

定义组件

使用构建步骤 .vue

当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC)

# a.vue <script> export default { data() { return { count: 0 } } } </script> <template> <button @click="count++">You clicked me {{ count }} times.</button> </template>

不使用构建步骤 .js

这里的模板是一个内联的 JavaScript 字符串,Vue 将会在运行时编译它

js
# a.js export default { data() { return { count: 0 } }, template: ` <button @click="count++"> You clicked me {{ count }} times. </button>` }

注册组件

全局注册

全局注册的组件可以在此应用的任意组件的模板中使用

js
import { createApp } from 'vue' const app = createApp({}) app.component( // 注册的名字 'MyComponent', // 组件的实现 { /* ... */ } )
js
// 如果使用单文件组件,你可以注册被导入的 .vue 文件 import MyComponent from './App.vue' app.component('MyComponent', MyComponent) // 可以链式调用 app .component('ComponentA', ComponentA) .component('ComponentB', ComponentB) .component('ComponentC', ComponentC)

注意

全局注册虽然很方便,但有以下几个问题:

  1. 全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。 如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。

  2. 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。 和使用过多的全局变量一样,这可能会影响应用长期的可维护性。

局部注册

局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。 它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好

  • 局部注册需要使用 components 选项
html
<script> import ComponentA from './ComponentA.vue' export default { // 局部注册 components: { // key: 注册组件名,value: 组件的实现 ComponentA: ComponentA // 简写 ComponentA, } } </script> <template> <ComponentA /> </template>

使用组件

要使用一个子组件,我们需要在父组件中导入它。

  • 若要将导入的组件暴露给模板,我们需要在 components 选项上注册它。
  • 组件将会以其注册时的名字作为模板中的标签名。
  • 子组件名称建议使用大驼峰命名,用于区分 html 标签
<script> import ButtonCounter from './ButtonCounter.vue' export default { // 注册子组件 components: { ButtonCounter } } </script> <template> <h1>Here is a child component!</h1> // 插入子组件 <ButtonCounter /> </template>

传递 props

声明 props

Props 是一种特别的 attributes,你可以在组件上声明注册

当一个 prop 被注册后,可以像这样以自定义 attribute 的形式传递数据给它

html
// 使用子组件 <BlogPost title="My journey with Vue" /> <BlogPost title="Blogging with Vue" /> <BlogPost title="Why Vue is so fun" />
html
<!-- BlogPost.vue --> <script> export default { // 注册 props props: ['title'] } </script> <template> <h4>{{ title }}</h4> </template>

子组件调用父组件方法修改父组件

子组件可以通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件

html
# 父组件 data() { return { posts: [ /* ... */ ], postFontSize: 1 } } <BlogPost ... // 向子组件传递方法 @enlarge-text="postFontSize += 0.1" />
html
<!-- 子组件 BlogPost.vue --> <script> export default { props: ['title'], // 声明组件可能触发的所有事件 emits: ['enlarge-text'] } </script> <template> <div class="blog-post"> <h4>{{ title }}</h4> // 调用父组件传递的方法 <button @click="$emit('enlarge-text')">Enlarge text</button> </div> </template>

插槽 slot

slot 与 react 中的 children 类似,是一个内容占位符

html
<AlertBox> // 这里的内容会填充到子组件的 slot 中 Something bad happened. </AlertBox>
html
# 子组件 <template> <div class="alert-box"> <strong>This is an Error for Demo Purposes</strong> <slot /> </div> </template> <style scoped> .alert-box { /* ... */ } </style>

动态组件 :is

有些场景会需要在两个组件间来回切换,比如 Tab 界面

传给

的值可以是以下几种:

被注册的组件名 导入的组件对象

html
<!-- currentTab 改变时组件也改变 --> <component :is="currentTab"></component>

注意

当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载。 可以通过 <KeepAlive> 组件强制被切换掉的组件仍然保持“存活”的状态。

本文作者:Silon汐冷

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!