Vue 组件是 Vue 应用的构建块,允许我们在其中耦合标签 (HTML)、逻辑 (JS) 和样式 (CSS)。
在 Vue 应用中,有一个观念很重要: 界面中的每个元素几乎都是由 Vue 组件所构成。因为 Vue 应用中的组件会层层嵌套,从而形成有层次的结构。
可重用性和可维护性是构建应用程序时特别重要的原因之一。在构建应用程序时,使用良好结构化的组件可以帮助你更好地实现这些目标。
为了更好地理解组件,我们将创建一个组件。在不包含构建过程的应用(例如 Webpack)中创建 Vue 组件的最简单方法是创建一个包含 Vue 特定选项的纯 JavaScript 对象。
js
export default {
props: ["name"],
template: `<h1>Hello, my name is {{ name }}</h1>`,
};
该组件定义了一个 props
属性,它接受名为 name
的单个 prop。 Props 是一种将数据从父组件传递到组件的方法。
template
属性定义组件的 HTML 模板。在本例中,它包含一个 <h1>
标题标签,显示文本 "Hello, my name is"
后跟 name
属性的值,该值使用 Vue 的双花括号语法 {{ }}
进行渲染。
除了将组件定义为纯 JavaScript 对象之外,在 Vue 中创建组件的最常见方法是使用单文件组件 (SFC)。单文件组件允许我们在一个特殊的 .vue
文件中定义组件的 HTML、CSS 和 JS ,如下所示:
html
<template>
<h1>Hello, my name is {{ name }}</h1>
</template>
<script setup>
const { name } = defineProps(["name"]);
</script>
注意:由于 Vite 等构建工具的存在,使得 Vue 中的单文件组件成为可能。这些工具将
.vue
组件编译为浏览器可以理解的纯 JavaScript 模块。
组件=构建块
我们将通过一个简单的练习来说明如何将组件拆分为更小的组件。考虑以下虚构的 Tweet
组件:
上述组件可以通过以下方式实现:
html
<template>
<div class="Tweet">
<image class="Tweet-image" :src="image.imageUrl" :alt="image.description" />
<div class="User">
<image class="Avatar" :src="author.avatarUrl" :alt="author.name" />
<div class="User-name">{{ author.name }}</div>
</div>
<div class="Details">
<div class="Tweet-text">{{ text }}</div>
<div class="Tweet-date">{{ formatDate(date) }}</div>
<!-- ... -->
</div>
</div>
</template>
<script setup>
// ...
</script>
我们可以看到上面的组件因为过于拥挤而难以操作,而且重用其中的各个部分也可能会很困难。为了使其更具组合性,我们可以从这个组件中提取出一些子组件。
我们可以让主 Tweet
组件成为 TweetUser
和 TweetDetails
组件的父组件。 TweetUser
将显示用户的信息,并且是显示用户头像的 TweetAvatar
组件的父组件。 TweetDetails
将仅显示推文中的附加信息,例如推文文本和提交日期。组件树如下所示:
我们可以首先创建子 TweetAvatar
组件来包含头像图片元素。
html
<template>
<image class="Avatar" :src="author.avatarUrl" :alt="author.name" />
</template>
<script setup>
// ...
</script>
然后我们可以创建 TweetAvatar
组件和相关用户信息的 TweetUser
组件。
html
<template>
<div class="User">
<TweetAvatar />
<div class="User-name">{{ author.name }}</div>
</div>
</template>
<script setup>
import { TweetAvatar } from "./TweetAvatar.vue";
</script>
我们可以创建 TweetDetails
组件来显示推文中的其余信息。
html
<template>
<div class="Details">
<div class="Tweet-text">{{ text }}</div>
<div class="Tweet-date">{{ formatDate(date) }}</div>
<!-- ... -->
</div>
</template>
<script setup>
// ...
</script>
最后,我们可以使用这些新创建的子组件来简化父 Tweet
组件的模板。
html
<template>
<div class="Tweet">
<image class="Tweet-image" :src="image.imageUrl" :alt="image.description" />
<TweetUser :author="author" />
<TweetDetails :text="text" :date="date" />
</div>
</template>
<script setup>
// ...
</script>
提取组件似乎是一项乏味的工作,但是在大型应用的开发过程中使用可重用组件会让开发变得更简单。简化组件时要考虑的一个很好的标准是------如果界面的一部分被多次使用( Button
、 Panel
、 Avatar
),或者组件本身就足够复杂( App
、 FeedStory
、 Comment
),那么就应该考虑对其进行组件的提取。
响应式状态
响应式状态是 Vue 组件中的一个基本概念,它支持动态和响应式用户界面。它允许组件自动更新并反映其数据的变化。
在 Vue 中,我们可以使用 ref()
函数(对于独立的原始值)和 reactive()
函数(对于对象)定义响应式数据属性。让我们考虑一个计数器组件的简单示例:
html
<template>
<div>
<h2>Counter: {{ count }}</h2>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const count = ref(0);
const increment = () => {
count.value++;
};
const decrement = () => {
count.value--;
};
</script>
在上面的示例中,我们定义了一个响应式属性 count
并将其初始化为 0。然后模板使用双大括号 {{ }}
来显示 count
该模板还包括两个按钮: "Increment"
和 "Decrement"
,它们使用 @click
指令分别绑定到 increment()
和 decrement()
方法。在这些方法中,我们访问并修改响应式 count
属性的值。 Vue 检测到更改并自动更新组件的渲染以反映新值。
Vue 组件中的响应式状态提供了一种无缝的方式来管理和跟踪数据变更,从而更轻松地构建交互式动态用户界面。
总结
本文旨在对组件的概念进行简单介绍。在其他文章和指南中,我们将更深入地了解使用 Vue 和 Vue 组件时的常见和重要模式。这包括但不限于:
- 使用
<script setup>
语法 - 创建可组合项以重用状态逻辑
- 通过 provide/inject 将数据传递到多个组件
- 了解应用范围的状态管理
- 使用动态组件在组件之间动态切换
- 使用 JSX 渲染组件模板
- 持续更新中...