_ 作者选择了 开源精神疾病 作为 写给捐赠 计划的一部分的捐赠。
介绍
在使用 [Vue.js] (https://vuejs.org/] 创建网络应用程序时,将您的应用程序构建在小而模块化的代码块中是一种最佳做法. 这不仅保持了应用程序部分的焦点,也使得应用程序随着复杂性的增加而更容易更新. 由于由Vue CLI生成的应用程序需要一个构建步骤,所以您可以访问_Single-File组件_(SFC),将模块化引入您的应用程序. SFCs拥有'.vue'扩展并包含一个HTML QTemplate , QQscript 和 QQstyle 标记,可以在其他组件中执行.
SFCs为开发人员提供了一种方式来为每个组件创建自己的 HTML标签,然后在他们的应用程序中使用它们。就像<p>
HTML标签在浏览器中渲染一个段落,并保持非渲染的功能一样,组件标签将渲染SFC在Vue模板中的任何地方。
在本教程中,您将创建一个SFC,并使用props
来传输数据,并将slots
用于在标签之间注入内容。
前提条件
- 节点.js版本`14.16.0'或更多安装在您的计算机上。 要在 macOS 或 Ubuntu 20. 04 上安装此功能,请遵循 [如何在 macOS (https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos) 上安装节点并创建本地开发环境 或使用 [如何在 Ubuntu 20. 04 上安装节点.js (https://andsky.com/tech/tutorials/how-to-install-node-js-on-ubuntu-20-04 的 部分 PPA 中的** 。
- [Vue CLI已安装] (https://andsky.com/tech/tutorials/how-to-generate-a-vue-js-single-page-app-with-vue-create)在您的机器上,并生成了一个新项目. 由于此教程使用 Vue 3 组成 API, 请在生成应用程序时确保您选择
3. x (Preview)
选项 。 本项目的名称将是 " sfc-project " ,它将作为根目录。 - 联合国 您还需要JavaScript, HTML, CSS 的基本知识, 您可以在 [How To Build a website With HTML (https://www.digitalocean.com/community/tutorial_series/how-to-build-a-website-with-html) 系列, [How To Build a website With CSS (https://www.digitalocean.com/community/tutorial_series/how-to-build-a-website-with-css) 系列, 以及 [How To Code in JavaScript (https://www.digitalocean.com/community/tutorial_series/how-to-code-in-javascript) 中找到这些知识 。 .
步骤1 - 设置项目
在本教程中,您将创建一个机场卡组件,该组件将显示数个机场及其代码在一系列的卡片中。 遵循前提部分后,您将有一个名为sfc-project
的新Vue项目。 在本节中,您将导入数据到这个生成的应用程序。
一旦项目生成,打开您的终端和cd
或更改目录到根文件夹src
:
1cd sfc-project/src
从那里,使用mkdir
命令创建一个名为data
的新目录,然后使用touch
命令创建一个名为us-airports.js
的新文件:
1mkdir data
2touch data/us-airports.js
在您所选择的文本编辑器中,打开这个新的JavaScript文件并添加以下本地数据:
1[label sfc-project/data/us-airports.js]
2export default [
3 {
4 name: 'Cincinnati/Northern Kentucky International Airport',
5 abbreviation: 'CVG',
6 city: 'Hebron',
7 state: 'KY'
8 },
9 {
10 name: 'Seattle-Tacoma International Airport',
11 abbreviation: 'SEA',
12 city: 'Seattle',
13 state: 'WA'
14 },
15 {
16 name: 'Minneapolis-Saint Paul International Airport',
17 abbreviation: 'MSP',
18 city: 'Bloomington',
19 state: 'MN'
20 }
21]
這個數據是 array 的 objects 由幾個機場在美國組成. 這將會在一個單一檔案組成部分後來在教程。
保存和退出文件。
接下来,您将创建另一组机场数据,这些数据将包括欧洲机场,使用触摸
命令创建一个名为eu-airports.js
的新JavaScript文件:
1touch data/eu-airports.js
然后打开文件并添加以下数据:
1[label sfc-project/data/eu-airports.js]
2export default [
3 {
4 name: 'Paris-Charles de Gaulle Airport',
5 abbreviation: 'CDG',
6 city: 'Paris',
7 state: 'Ile de France'
8 },
9 {
10 name: 'Flughafen München',
11 abbreviation: 'MUC',
12 city: 'Munich',
13 state: 'Bavaria'
14 },
15 {
16 name: 'Fiumicino "Leonardo da Vinci" International Airport',
17 abbreviation: 'FCO',
18 city: 'Rome',
19 state: 'Lazio'
20 }
21]
此数据集适用于法国、德国和意大利的欧洲机场。
保存和退出文件。
接下来,在 root 目录中,在终端中运行以下命令,在本地开发服务器上启动 Vue CLI 应用程序:
1npm run serve
这将打开您的浏览器中的应用程序在localhost:8080
。
请访问您的浏览器中的地址,您将看到以下启动屏幕:
接下来,开始一个新的终端,并在你的src
文件夹中打开你的App.vue
文件. 在这个文件中,删除img
和HelloWorld
标签在<template>
和components
部分和import
声明在<script>
。
1[label sfc-project/src/App.vue]
2<template>
3
4</template>
5
6<script>
7export default {
8 name: 'App',
9}
10</script>
11
12<style>
13#app {
14 font-family: Avenir, Helvetica, Arial, sans-serif;
15 -webkit-font-smoothing: antialiased;
16 -moz-osx-font-smoothing: grayscale;
17 text-align: center;
18 color: #2c3e50;
19 margin-top: 60px;
20}
21</style>
在此之后,导入您之前创建的 us-airports.js
文件. 为了使此数据具有反应性,因此您可以在 <template>
中使用它,您需要从 vue
中导入 ref
函数。
添加以下突出的线条:
1[label sfc-project/src/App.vue]
2<template>
3 <div class="wrapper">
4 <div v-for="airport in airports" :key="airport.abbreviation" class="card">
5 <p>{{ airport.abbreviation }}</p>
6 <p>{{ airport.name }}</p>
7 <p>{{ airport.city }}, {{ airport.state }}</p>
8 </div>
9 </div>
10</template>
11
12<script>
13import { ref } from 'vue'
14import data from '@/data/us-airports.js'
15
16export default {
17 name: 'App',
18 setup() {
19 const airports = ref(data)
20
21 return { airports }
22 }
23}
24</script>
25...
在此片段中,您已导入数据并使用模板中的 <div>
元素和 v-for
指令 进行渲染。
在此时,数据已被导入并准备在App.vue
组件中使用,但首先添加一些样式,以便用户更容易阅读数据。
1[label sfc-project/src/App.vue]
2...
3<style>
4#app { ... }
5
6.wrapper {
7 display: grid;
8 grid-template-columns: 1fr 1fr 1fr;
9 grid-column-gap: 1rem;
10 max-width: 960px;
11 margin: 0 auto;
12}
13
14.card {
15 border: 3px solid;
16 border-radius: .5rem;
17 padding: 1rem;
18 margin-bottom: 1rem;
19}
20
21.card p:first-child {
22 font-weight: bold;
23 font-size: 2.5rem;
24 margin: 1rem 0;
25}
26
27.card p:last-child {
28 font-style: italic;
29 font-size: .8rem;
30}
31</style>
在这种情况下,您正在使用 CSS 网格将这些机场代码卡组成一个网格的三个。 请注意这个网格是如何设置在 .wrapper
类。 .card
类是包含每个机场代码,名称和位置的卡或部分。 如果您想了解更多关于 CSS 的信息,请查看我们的 如何使用 CSS 来设计 HTML.
打开您的浏览器并导航到localhost:8080
。你会发现一些卡片与机场代码和信息:
现在您已经设置了初始应用程序,您可以在下一步将数据重塑为单个文件组件。
步骤 2 — 创建单个文件组件
由于 Vue CLI 使用 Webpack来构建您的应用程序成浏览器可以读取的东西,您的应用程序可以使用 SFC 或 .vue
文件,而不是简单的 JavaScript. 这些文件是您创建可扩展和可重复使用的代码的小块的方式。
这些.vue
组件通常由以下三种元素组成:<template>
,<script>
和<style>
元素。SFC组件可以具有 _scoped_
或 _unscoped_
风格。当一个组件有scopeed
风格时,这意味着style<>
标签之间的CSS只会影响同一个文件中的<template>
中的HTML。
随着您的项目的成功设置,您现在将将这些机场卡分解为一个名为AirportCards.vue
的组件。 正如现在所说,在App.vue
中的HTML不太可重复使用。
在您的终端中,在组件
目录中创建此.vue 文件:
1touch src/components/AirportCards.vue
在文本编辑器中打开AiportCards.vue
组件. 为了说明如何使用组件重新使用代码块,请将大部分代码从App.vue
文件移动到AirportCards.vue
组件:
1[label sfc-project/src/components/AirportCards.vue]
2<template>
3 <div class="wrapper">
4 <div v-for="airport in airports" :key="airport.abbreviation" class="card">
5 <p>{{ airport.abbreviation }}</p>
6 <p>{{ airport.name }}</p>
7 <p>{{ airport.city }}, {{ airport.state }}</p>
8 </div>
9 </div>
10</template>
11
12<script>
13import { ref } from 'vue'
14import data from '@/data/us-airports.js'
15
16export default {
17 name: 'Airports',
18 setup() {
19 const airports = ref(data)
20
21 return { airports }
22 }
23}
24</script>
25
26<style scoped>
27.wrapper {
28 display: grid;
29 grid-template-columns: 1fr 1fr 1fr;
30 grid-column-gap: 1rem;
31 max-width: 960px;
32 margin: 0 auto;
33}
34
35.card {
36 border: 3px solid;
37 border-radius: .5rem;
38 padding: 1rem;
39 margin-bottom: 1rem;
40}
41
42.card p:first-child {
43 font-weight: bold;
44 font-size: 2.5rem;
45 margin: 1rem 0;
46}
47
48.card p:last-child {
49 font-style: italic;
50 font-size: .8rem;
51}
52</style>
保存并关闭文件。
接下来,打开您的App.vue
文件,现在您可以清理App.vue
组件并导入AirportCards.vue
:
1[label sfc-project/src/App.vue]
2<template>
3 <AirportCards />
4</template>
5
6<script>
7import AirportCards from '@/components/Airports.vue'
8
9export default {
10 name: 'App',
11 components: {
12 AirportCards
13 }
14}
15</script>
16
17<style scoped>
18#app {
19 font-family: Avenir, Helvetica, Arial, sans-serif;
20 -webkit-font-smoothing: antialiased;
21 -moz-osx-font-smoothing: grayscale;
22 text-align: center;
23 color: #2c3e50;
24 margin-top: 60px;
25}
26</style>
现在AirportCards
是一个独立的组件,你已经把它放在<template>
的HTML中,就像你想要一个<p>
的标签一样。
當您在瀏覽器中開啟「localhost:8080」時,沒有什麼會改變. 相同的三張機場卡仍然會顯示,因為您正在在「
接下来,再次将该组件添加到模板中,以说明组件的可重复使用性:
1[label /src/App.vue]
2<template>
3 <AirportCards />
4 <airport-cards />
5</template>
6...
您可能会注意到这个新的AirportCards.vue
实例正在使用 kebab-case 对 PascalCase 进行引用。在引用组件时,Vue 并不在乎您使用哪个组件。
<$>[注] 注: 您使用的案例取决于个人偏好,但一致性很重要。
打开浏览器并访问localhost:8080
。你会发现卡片的重复:
这为您的应用程序增加了模块化性,但数据仍然是静态的. 如果您想要显示相同的三个机场,卡的行是有用的,但更改数据源将需要更改硬编码的数据。
步骤 3 – 利用特许权来传输数据
在之前的步骤中,您创建了一个AirportCards.vue
组件,该组件从us-airports.js
文件中的数据中渲染了一些卡片,此外,您还翻番了相同的组件参考,以说明您如何通过在<模板>
中添加该组件的另一个实例来轻松复制代码。
但是,如果数据保持静态,将使未来更改数据变得困难。当您使用 SFC 时,如果您将组件视为函数,则可以有所帮助。这些函数是可以包含参数(props)并返回某些东西(HTML)的组件。
在文本编辑器中打开AirportCards.vue
组件. 您正在从us-airports.js
文件中导入数据
。 删除此导入声明以及在<script>
标签中的设置
函数:
1[label sfc-project/src/components/AirportCards.vue]
2...
3<script>
4
5export default {
6 name: 'Airports',
7}
8</script>
9...
保存文件. 在此时刻,浏览器中不会显示任何东西。
接下来,通过定义 prop 向前迈进,这个 prop 可以被命名为任何东西;它只是描述进入的数据并将其与一个名称相关联。
要创建一个 prop,请在组件中添加props
属性。 此值为一系列的密钥/值对。 密钥是 prop的名称,值是数据的描述。
1[label sfc-project/src/components/AirportCards.vue]
2...
3<script>
4
5export default {
6 name: 'Airports',
7 props: {
8 airports: {
9 type: Array,
10 required: true
11 }
12 }
13}
14</script>
15...
现在,在AirportCard.vue
,属性机场
是指传输的数据。
接下来,在文本编辑器中打开App.vue
组件,如前所述,您将需要从us-airports.js
文件中导入
数据,并从Vue中导入``ref
函数,使其对HTML模板具有反应性:
1[label sfc-project/src/App.vue]
2<template>
3 <AirportCards :airports="usAirports" />
4 <airport-cards />
5</template>
6
7<script>
8import { ref } from 'vue'
9import AirportCards from '@/components/Airports.vue'
10import usAirportData from '@/data/us-airports.js'
11
12export default {
13 name: 'App',
14 components: {
15 AirportCards
16 },
17 setup() {
18 const usAirports = ref(usAirportData)
19
20 return { usAirports }
21 }
22}
23</script>
如果您打开浏览器并访问localhost:8080
,您将发现与之前相同的美国机场:
您的模板中还有另一个AirportCards.vue
实例。由于您在该组件中定义了代理,您可以传输具有相同结构的任何数据,以返回来自不同机场的几张卡片。
在App.vue
中,导入eu-airports.js
文件,将其包装在ref
函数中,使其反应性,然后返回:
1[label /src/App.vue]
2<template>
3 <AirportCards :airports="usAirports" />
4 <airport-cards :airports="euAirports" />
5</template>
6
7<script>
8...
9import usAirportData from '@/data/us-airports.js'
10import euAirportData from '@/data/eu-airports.js'
11
12export default {
13 ...
14 setup() {
15 const usAirports = ref(usAirportData)
16 const euAirports = ref(euAirportData)
17
18 return { usAirports, euAirports }
19 }
20}
21</script>
22...
打开您的浏览器并访问localhost:8080
。下方您将找到美国机场数据的欧洲机场数据:
您现在已成功地将不同的数据集转移到同一个组件中. 使用props
,您基本上正在将数据重新分配到新的名称中,并使用该新名称来引用子组件中的数据。
在这一点上,这个应用程序开始变得更加动态,但你仍然可以做一些其他事情来使这一点更加集中和可重复使用。在Vue.js中,你可以使用名为 slots 的东西。
步骤4 — 使用插槽创建通用卡片组件
插槽是创建可重复使用的组件的好方法,特别是如果你不知道该组件中的HTML是否会是相似的。在上一个步骤中,你创建了另一个AirportCards.vue
实例,具有不同的数据。
打开终端并使用触摸
命令创建一个新文件. 这个文件将被命名为Card.vue
:
1touch src/components/Card.vue
在您的文本编辑器中,打开新的Card.vue
组件.您将从AirportCards.vue
中取一些CSS并将其添加到这个新组件中。
创建一个<style>
标签,并在以下CSS中添加:
1[label sfc-project/src/components/Card.vue]
2<style>
3.card {
4 border: 3px solid;
5 border-radius: .5rem;
6 padding: 1rem;
7 margin-bottom: 1rem;
8}
9</style>
接下来,为该组件创建 HTML 模板。在<style>
标签之前,添加一个<template>
标签,包含以下内容:
1[label sfc-project/src/components/Card.vue]
2<template>
3 <div class="card">
4
5 </div>
6</template>
7...
在<div class="card">
之间,添加<slot />
组件,这是Vue为您提供的组件,无需导入这个组件,它由Vue.js在全球范围内导入:
1[label sfc-project/src/components/Card.vue]
2<template>
3 <div class="card">
4 <slot />
5 </div>
6</template>
此插槽
是Card.vue
组件的标签之间位置的HTML,当它在其他地方引用时。
保存和退出文件。
现在回到AirportCards.vue
组件. 首先,导入您刚刚创建的新Card.vue
SFC:
1[label sfc-project/src/components/AirportCards.vue]
2...
3<script>
4import Card from '@/components/Card.vue'
5
6export default {
7 name: 'Airports',
8 props: { ... },
9 components: {
10 Card
11 }
12}
13</script>
14...
现在剩下的就是把div
代替为card
:
1[label /src/components/AirportCards.vue]
2<template>
3 <div class="wrapper">
4 <card v-for="airport in airports" :key="airport.abbreviation">
5 <p>{{ airport.abbreviation }}</p>
6 <p>{{ airport.name }}</p>
7 <p>{{ airport.city }}, {{ airport.state }}</p>
8 </card>
9 </div>
10</template>
11...
由于您在Card.vue
组件中有<slot />
,所以在<card>
标签之间注入了HTML,同时保留了与卡片相关联的所有风格。
当你在localhost:8080上打开浏览器时,你会发现你以前使用过的相同卡片。 现在的区别是你的AirportCards.vue现在引用了Card.vue
组件:
要显示插槽的强度,请在应用程序中打开App.vue
组件,然后导入Card.vue
组件:
1[label sfc-project/src/App.vue]
2...
3<script>
4...
5import Card from '@/components/Card.vue'
6
7export default {
8 ...
9 components: {
10 AirportCards,
11 Card
12 },
13 setup() { ... }
14}
15</script>
16...
在<模板>
中,在<机场卡>
实例中添加下列内容:
1[label sfc-project/src/App.vue]
2<template>
3 <AirportCards :airports="usAirports"/>
4 <airport-cards :airports="euAirports" />
5 <card>
6 <p>US Airports</p>
7 <p>Total: {{ usAirports.length }}</p>
8 </card>
9 <card>
10 <p>EU Airports</p>
11 <p>Total: {{ euAirports.length }}</p>
12 </card>
13</template>
14...
保存文件并访问浏览器中的localhost:8080
。您的浏览器现在将显示数据集中的机场数量的额外元素:
在<card />
标签之间的HTML并不完全相同,但它仍然呈现出一种通用卡片。
结论
在本教程中,您创建了单个文件的组件,并使用props
和slots
来创建可重复使用的代码块。在项目中,您创建了一个AirportCards.vue
组件,该组件可渲染多个机场卡片。
您最终发现了一些组件是动态的,可以用于许多不同的用途,所有这些都保持代码可维护,并符合软件原则(https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)。
要了解更多关于 Vue 组件的信息,建议您通过 Vue 文档进行准备。 有关 Vue 的更多教程,请参阅 如何使用 Vue.js 系列开发网站页面。