components

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Components

组件

Table of Contents

目录

Vue components are the building blocks of Vue apps by allowing us to couple markup (HTML), logic (JS), and styles (CSS) within them.
When working within a Vue application, it's important to understand that almost every element displayed in the UI is oftentimes part of a Vue component. This is because a Vue application is often composed of components nested within components, forming a hierarchical structure.
Vue组件是Vue应用的构建块,它允许我们将标记(HTML)、逻辑(JS)和样式(CSS)封装在其中。
在Vue应用中开发时,需要明白UI中展示的几乎每个元素通常都是某个Vue组件的一部分。这是因为Vue应用通常由嵌套的组件构成,形成一个层级结构。

When to Use

适用场景

  • Use this as foundational knowledge for building any Vue application
  • This is helpful for understanding how to structure, compose, and reuse UI elements in Vue
  • 将此作为构建任何Vue应用的基础知识
  • 这有助于理解如何在Vue中构建、组合和复用UI元素

Instructions

操作指南

  • Use single-file components (
    .vue
    files) with
    <template>
    ,
    <script setup>
    , and
    <style>
    sections
  • Extract reusable parts of large components into smaller child components
  • Use
    ref()
    for reactive primitive values and
    reactive()
    for reactive objects
  • Pass data from parent to child using props; emit events from child to parent
  • 使用包含
    <template>
    <script setup>
    <style>
    部分的单文件组件(
    .vue
    文件)
  • 将大型组件中可复用的部分提取为更小的子组件
  • 使用
    ref()
    处理响应式原始值,使用
    reactive()
    处理响应式对象
  • 通过props将数据从父组件传递到子组件;子组件通过触发事件向父组件传递信息

Details

详细说明

Reusability and maintainability are some of the main reasons why building an application with well-structured components are especially important.
To get a better understanding of components, we'll go ahead and create one. The simplest way to create a Vue component in an application that doesn't contain a build process (e.g. Webpack) is to create a plain JavaScript object that contains Vue specific options.
js
export default {
  props: ["name"],
  template: `<h1>Hello, my name is {{ name }}</h1>`,
};
The component has a
props
property defined, which accepts a single prop named
name
. Props are a way to pass data into a component from its parent component.
The
template
property defines the HTML template for the component. In this case, it contains an
<h1>
heading tag that displays the text
"Hello, my name is"
followed by the value of the
name
prop, which is rendered using Vue's double curly braces syntax
{{ }}
.
Aside from defining components as plain JavaScript objects, the most common way of creating components in Vue are with single-file components (SFCs). Single-file components are components that allow us to define the HTML, CSS, and JS of a component all within a special
.vue
file, as shown below:
html
<template>
  <h1>Hello, my name is {{ name }}</h1>
</template>

<script setup>
  const { name } = defineProps(["name"]);
</script>
Note: Single-file components in Vue are made possible due to build tools like Vite. These tools help compile
.vue
components to plain JavaScript modules that can be understood in browsers.
可复用性和可维护性是使用结构良好的组件构建应用的主要原因之一。
为了更好地理解组件,我们来创建一个组件。在没有构建流程(如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"
,并通过Vue的双大括号语法
{{ }}
渲染
name
prop的值。
除了将组件定义为普通JavaScript对象外,Vue中最常见的创建组件的方式是使用单文件组件(SFC)。单文件组件允许我们在一个特殊的
.vue
文件中定义组件的HTML、CSS和JS,如下所示:
html
<template>
  <h1>Hello, my name is {{ name }}</h1>
</template>

<script setup>
  const { name } = defineProps(["name"]);
</script>
注意:Vue中的单文件组件是通过Vite等构建工具实现的。这些工具会将
.vue
组件编译为浏览器可以理解的普通JavaScript模块。

Components = building blocks

组件=构建块

We'll go through a simple exercise to illustrate how components can be split into smaller components. Consider a fictional
Tweet
component.
The component can be implemented with something as follows:
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>
One can look at the above component and consider it difficult to manipulate because of how clustered it is, and reusing individual parts of it may also prove difficult. To make things more composable, we can extract a few components from this one component.
We can have the main
Tweet
component be the parent to the
TweetUser
and
TweetDetails
components.
TweetUser
will display the user's information and be a parent to a
TweetAvatar
component that displays the user's avatar.
TweetDetails
will simply display additional information in the tweet such as the tweet text and the date of submission.
We can first create the child
TweetAvatar
component to contain the avatar image element.
html
<template>
  <image class="Avatar" :src="author.avatarUrl" :alt="author.name" />
</template>

<script setup>
  // ...
</script>
We can then create the
TweetUser
component that renders the
TweetAvatar
component and relevant user information.
html
<template>
  <div class="User">
    <TweetAvatar />
    <div class="User-name">{{ author.name }}</div>
  </div>
</template>

<script setup>
  import { TweetAvatar } from "./TweetAvatar.vue";
</script>
We can create the
TweetDetails
component to render the remaining information in the tweet.
html
<template>
  <div class="Details">
    <div class="Tweet-text">{{ text }}</div>
    <div class="Tweet-date">{{ formatDate(date) }}</div>
    <!-- ... -->
  </div>
</template>

<script setup>
  // ...
</script>
Finally, we can use these newly created child components to simplify the template of the parent
Tweet
component.
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>
Extracting components seems like a tedious job, but having reusable components makes things easier when coding for larger apps. A good criterion to consider when simplifying components is this — if a part of your UI is used several times (
Button
,
Panel
,
Avatar
), or is complex enough on its own (
App
,
FeedStory
,
Comment
), it is a good candidate to be extracted into a separate component.
我们通过一个简单的练习来说明如何将组件拆分为更小的组件。考虑一个虚构的
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>
然后,我们创建
TweetUser
组件,它会渲染
TweetAvatar
组件和相关用户信息。
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>
提取组件看似繁琐,但拥有可复用的组件会让大型应用的开发变得更轻松。判断是否需要简化组件的一个标准是——如果UI的某一部分被多次使用(如
Button
Panel
Avatar
),或者本身足够复杂(如
App
FeedStory
Comment
),那么它就适合被提取为独立组件。

Reactive state

响应式状态

Reactive state is a fundamental concept in Vue components that enables dynamic and responsive user interfaces. It allows components to update and reflect changes in their data automatically.
In Vue, we can define reactive data properties with the
ref()
function (for standalone primitive values) and the
reactive()
function (for objects). Let's consider a simple example of a counter component:
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>
In the above example, we define a reactive property
count
and initialize it with a value of 0. The template then uses double curly braces
{{ }}
to display the current value of
count
.
The template also includes two buttons:
"Increment"
and
"Decrement"
, which are bound to the corresponding
increment()
and
decrement()
methods using the
@click
directive. Inside these methods, we access and modify the value of the reactive
count
property. Vue detects the changes and automatically updates the component's rendering to reflect the new value.
Reactive state in Vue components provides a seamless way to manage and track data changes, making it easier to build interactive and dynamic user interfaces.
响应式状态是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组件中的响应式状态提供了一种无缝的方式来管理和跟踪数据变化,使构建交互式和动态的用户界面变得更加容易。

Conclusion

总结

This article aims to be a simple introduction to the concept of components. In the other articles and guides, we'll be taking a deeper dive into understanding common and important patterns when working with Vue and Vue components. This includes but is not limited to:
本文旨在简单介绍组件的概念。在其他文章和指南中,我们将更深入地探讨使用Vue和Vue组件时常见且重要的模式,包括但不限于:

Source

来源

References

参考资料