Logo
Section 1 / 6

组件

学习 Vue.js 组件的模板、脚本、样式、事件、属性和指令的基础知识。

导入

组件

学习 Vue.js 组件的模板、脚本、样式、事件、属性和指令的基础知识。

Vue 组件是 Vue 应用中可复用的代码块,封装了特定的功能和用户界面元素。每个组件都可以拥有自己的属性、方法、事件以及模板,用于定义组件的 HTML 结构,从而方便在应用的不同部分重复使用代码。

一旦定义了组件,就可以通过将其名称作为自定义 HTML 标签的方式在应用的其他地方使用。组件还可以嵌套在其他组件内部,从而实现高度模块化和可复用的复杂用户界面构建。

Vue 组件的基本架构

一个 Vue 组件通常包含三个部分:模板(template)、脚本(script)和样式(style),如下图所示:

...
Vue.js 组件的基本架构

单页应用(SPA) 小部件是一个基于浏览器的开发环境,允许我们方便地编写、编辑和运行代码。本课程将全程使用该工具来增强理解与交互性。

以下是包含基础 Vue 应用代码的 SPA 示例,展示了如何组合组件来创建页面。点击“运行”按钮即可测试,内置编译器会生成应用程序。完成后,可以在嵌入的显示区域查看页面,或通过提供的链接访问。

No configuration found for ID: cbe4421affeb99e38b3522f0e6300db47782176dea230cc9a0b9daed461f126e

Props

组件的 props 可以看作是从父组件向子组件传递数据的通道。

为了保证应用中数据的一致性和行为的稳定性,Vue 要求所有预期的组件 props 必须在组件中声明。这可以通过 defineProps 宏来完成。

1<template> 2 <div> 3 <p>{{ greetings }}</p> 4 </div> 5</template> 6 7<script setup lang="ts"> 8defineProps({ 9 greetings: String 10}) 11</script>

上述代码展示了 HelloWorldWithGreeting 组件的声明,它在 SPA 中作为 DynamicComponent 的一个选项使用。该组件接收一个 greetings 属性,并在模板的段落元素中渲染该值。

注意,代码中的 defineProps 宏不仅声明了期望的属性,还指定了属性的类型。

事件

组件事件 可以看作是 props 的反向通道,用于子组件与父组件之间的通信。这种通信可以传递数据,也可以通知某个状态变化的发生。

子组件向父组件发送消息的过程称为 触发事件(emitting)。在 Vue 中,组件可以触发的事件通过 defineEmits 宏来定义,如下所示:

1<template> 2 <div> 3 <input 4 type="text" 5 v-model="inputText" 6 @input="$emit('onChange')" 7 @mouseenter="$emit('randomEvent', mouseEnterCount++)" 8 @click="$emit('inputClickEvent', clickCount++)" 9 /> 10 </div> 11</template> 12 13<script setup lang="ts"> 14const inputText = ref(""); 15const clickCount = ref(0); 16const mouseEnterCount = ref(0); 17defineEmits(["update:inputText", "onChange", "randomEvent","inputClickEvent"]); 18</script>

上述代码中的事件包括 update:inputText、randomEvent 和 inputClickEvent。

在父组件中,除了以 update: 开头的事件外,其他事件都使用 @ 符号后接小写连字符命名的事件名进行引用。因此,randomEvent 在父组件中应写作 @random-event。

以 update: 为前缀的事件用于跟踪响应式变量(如 inputText)的值,并将其复制到父组件指定的响应式变量中,配合 v-model:input-text 使用。

以下是一个使用上述组件的父组件示例:

1<template> 2 <div> 3 <input 4 style="border: 1px solid black;" 5 type="text" 6 @input="(e) => $emit('update:inputText', e?.target?.value)" 7 @mouseenter="$emit('randomEvent', mouseEnterCount++)" 8 @click="$emit('inputClickEvent', clickCount++)" 9 /> 10 </div> 11</template> 12 13<script setup lang="ts"> 14const inputText = ref(""); 15const clickCount = ref(0); 16const mouseEnterCount = ref(0); 17defineEmits(["update:inputText", "randomEvent", "inputClickEvent"]); 18</script>

模板

组件的 模板 定义了渲染后的 HTML 布局。它包含支持 Vue 指令和绑定的 HTML 标记,用于创建动态且响应式的界面行为。

1<template> 2 <div> 3 <h1>{{ greetings }}</h1> 4 </div> 5</template> 6<script setup lang="ts"> 7 const greetings = "Hello World" 8</script> 9<style> 10 h1 { 11 font-size: 16px; 12 color: blue; 13 } 14</style>

上述代码展示了在 src/components/HelloWorld.vue 文件中声明的 HelloWorld 组件。该组件的模板简单地将变量 greetings 包裹在 h1 标签中。在 Vue 中,模板内的变量需用双大括号包裹,如 SPA 示例所示。

该组件被导入到 App.vue 组件中作为子组件,当应用在浏览器中渲染时,会在首页显示文本 “Hello World”。

脚本

在 Vue.js 中,组件的 脚本 部分负责定义组件的逻辑。它包含组件的方法、实例变量、生命周期钩子等。

函数和其他组件也可以导入到组件的脚本标签中使用。

样式

Vue.js 组件的 样式 部分用于定义 CSS 样式。这些样式的作用范围被限定在当前组件内,意味着样式仅应用于该组件模板中的 HTML 元素,不会影响应用中的其他元素。

样式部分可以包含原生 CSS、预处理器代码(如 Sass 或 Less),或 CSS-in-JS(如 styled-components)。

指令

组件的 指令 是特殊的属性,可用于修改 Vue 模板中 HTML 元素的行为。它们可用于条件渲染元素、绑定数据到元素、添加自定义事件等。

指令始终以 v- 为前缀。一些常见的内置指令包括:

  • v-if:根据布尔表达式条件性地渲染元素。
  • v-else:当 v-if 关联的表达式为假时渲染元素。
  • v-show:根据布尔表达式隐藏或显示元素。
  • v-on:为元素绑定事件处理器。
  • v-model:将元素的值绑定到 Vue 变量。
  • v-for:根据数组多次渲染一段代码或元素。
  • v-bind:动态绑定一个或多个属性,或组件的 prop 到一个表达式。例如,v-bind:src 可将图片的 src 属性映射到一个表达式。v-bind 有简写形式 :,因此 v-bind:src 也可写作 :src。

指令也可以自定义。自定义指令 是注册到 Vue 中的 JavaScript 函数,能够实现内置指令的所有功能,甚至更多。

动态组件

动态组件 在 Vue 中提供了一种强大的方式,可以根据特定条件或用户输入来渲染不同的组件。通过使用动态组件,可以创建更灵活、更具适应性的界面,使其能响应用户与应用的交互变化。

在 Vue.js 中使用动态组件,可以借助内置组件系统和 v-bind 指令,将动态组件绑定到一个属性或变量上。这使得可以根据条件(如用户输入或应用状态的变化)在不同组件之间切换。

1<template> 2 <header> 3<!-- 注意 ":" 表示该属性使用的是 v-bind 指令 --> 4<!-- 同时注意 "is" 指令使用 handleSwitch 的返回值来决定渲染哪个组件 --> 5 <component :is="handleSwitch" v-bind="{ greetings: greetings, 'message': message }" /> 6 <button @click="buttonClick">button</button> 7 </header> 8</template> 9<script setup lang="ts"> 10// 导入 Vue 的响应式函数 11import { ref, computed } from 'vue'; 12 13// 导入要动态渲染的组件 14import HelloWorldWithGreetings from '@/components/HelloWorldWithGreetings.vue'; 15import HelloWorldWithMessage from '@/components/HelloWorldWithMessage.vue' 16 17// 初始化切换状态为 false 18const toggle = ref(false); 19const greetings = "Hi, nice to meet you"; 20const message = "I'm learning Nuxt" 21 22// 定义切换状态变量的函数 23const buttonClick = () => { 24 toggle.value = !toggle.value 25} 26 27// 定义根据状态值决定渲染哪个组件的函数 28// 注意使用了 computed 响应式函数,可基于状态值缓存函数输出 29const handleSwitch = computed(() => { 30 return toggle.value ? HelloWorldWithGreetings : HelloWorldWithMessage 31}) 32</script> 33<style> 34 button { 35 background-color: #87CEEB; 36 padding: 0.4em; 37 color: white; 38 font-size: 14px; 39 } 40</style>

上述代码展示了之前课程中 SPA 显示的 DynamicComponent.vue 文件中的组件。该组件根据一个状态值选择渲染特定的组件,该状态值由按钮点击更新。

动态组件使用 <component> 标签,并通过 :is 指令决定渲染哪个组件。v-bind 指令允许将 prop 值传递给各个子组件。

需要注意的是,这是一个简单的动态组件实现。由于本例中只有两种选择,也可以使用 v-if/v-else 指令来实现相同效果。

练习

在下方的 SPA 中已创建了一个名为 ListComponent.vue 的组件。结合本课所学内容,修改该组件,使其完成以下功能:

  • 包含一个 h2 标题,文字颜色独特,内容为名为 header 的 prop 变量。header 是一个字符串类型的 prop。
  • 接收来自 App.vue 组件的字符串列表,通过 list prop 传入。list 是一个字符串数组。
  • 将接收到的列表以项目符号列表的形式渲染出来。
  • 当接收到空数组(长度为零)时,显示文本 “Empty list”。

显示提示

  • 在脚本标签中声明 props。例如:
    • header:用于定义 h2 的文本
    • list:用于定义字符串列表
  • 创建一个 h2 元素,并使用 header 变量插入文本。
  • 添加一个 ul 元素用于项目符号列表。
    • 在 ul 内部添加 li 元素用于列表项
    • 使用 v-for 指令遍历列表中的每个值,并将其添加到 li 标签中。例如:

使用 "ul" 和 "li" 标签的示例列表

1<ul> 2 <li v-for="str in list">{{str}}</li> 3</ul>

显示答案

  • components/ListComponent.vue 中的列表组件可定义如下:

ListComponent.vue 组件的答案

1<template> 2 <h2>{{ header }}</h2> 3 <ul> 4 <li v-for="str in list" :key="str">{{ str }}</li> 5 </ul> 6</template> 7<script setup lang="ts"> 8 defineProps<{ 9 header: string 10 list: string[] 11 }>() 12</script> 13<style> 14 h2 { 15 font-family: 'Montserrat', sans-serif; 16 font-size: 1.5rem; 17 color: #ff6f00; 18 text-transform: uppercase; 19 letter-spacing: 2px; 20 } 21</style>

总结

组件使开发者能够通过将复杂动态的用户界面拆分为更小、更易管理的部分来构建。它们支持代码复用,便于长期维护和更新应用。

借助动态组件,开发者可以根据状态值程序化地决定渲染哪个组件。

组件还能通过明确定义的 API 相互通信,轻松实现数据和事件的传递。总体而言,Vue.js 组件为构建可扩展、可维护且高性能的 Web 应用提供了强大工具。

简介

视图