作者选择了 开源精神疾病以作为 写给捐赠计划的一部分获得捐赠。
介绍
Vuex是由Evan You创建的第一方开发状态管理库,目前由Vue.js核心团队维护,与许多其他国家管理库一样,Vuex遵循了过去几年中Redux(https://redux.js.org/)普及的原则:数据流向一个方向,行动和突变在一个单一的真理来源中修改数据,称为商店。
Vuex store 是不同的方法和数据的集合,其中一些方法,例如 actions,可以在发送到突变之前获取和处理数据。 mutation 是一种方法,通过提供的值来突变或更新商店属性。 Getters 是可以修改或组合数据来创建一个新的状态属性的方法。 这些 getters 只能读取并且不会改变数据。 这些方法类似于 Vue.js 组件中的计算属性。 Vuex 的最后一个组件是 state 或作为您的单一真理来源的数据集。
在本教程中,您将创建一个应用程序,该应用程序将显示有机场信息的卡片列表。在点击时,这些卡片将执行Vuex工作流程,将所选的机场添加到喜爱的列表中。
前提条件
- Node.js 版本
14.16.0’ 或更高版本安装在您的计算机上。 要在 macOS 或 Ubuntu 20.04 上安装此功能,请按照 [How To Install Node.js and Create a Local Development Environment on macOS](https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos) 或 [How To Install Node.js on Ubuntu 20.04](https://andsky.com/tech/tutorials/how-to-install-node-js-on-ubuntu-20-04) 部分的 **Installing Using a PPA** 选项(https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos) 的步骤,在您的计算机上执行 [How To Install Node.js and Create a Local Development Environment on macOS](https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos) 并且新生成的项目。 请确保在生成应用程序时选择
Default (Vue 3 Preview)选项。 该项目的名称将是
步骤 1 – 设置示例应用程序
为了帮助您可视化如何使用 Vuex 管理状态,请设置一个包含某些数据的项目,以便在视图中显示。
一旦创建了最喜欢的机场
项目,如在前提条件
部分中所述,请创建一个目录,以存储该项目的所有本地数据。
1mkdir src/data
2touch src/data/airports.js
这将创建一个数据
目录和一个空的airports.js
文件。
在您所选择的文本编辑器中,打开新创建的 airports.js
文件,并添加以下内容:
1[label favorite-airports/src/data/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 {
22 name: 'Louis Armstrong New Orleans International Airport',
23 abbreviation: 'MSY',
24 city: 'New Orleans',
25 state: 'LA',
26 },
27 {
28 name: `Chicago O'hare International Airport`,
29 abbreviation: 'ORD',
30 city: 'Chicago',
31 state: 'IL',
32 },
33 {
34 name: `Miami International Airport`,
35 abbreviation: 'MIA',
36 city: 'Miami',
37 state: 'FL',
38 }
39]
这是由美国几个机场组成的 object的数组(https://andsky.com/tech/tutorials/understanding-arrays-in-javascript)。 在此应用程序中,您将通过这些数据进行迭代,以生成包括名称
,缩写
,城市
和州
属性的卡片。当用户点击卡片时,您将执行发送
方法,将该机场添加到您的Vuex状态作为您最喜欢的机场。
保存数据/airports.js
并返回终端。
完成此步骤后,创建一个名为AirportCard.vue
的单个文件组件(SFC)。该文件将生活在您的项目的组件
目录中。该组件将包含机场卡的所有风格和逻辑。在您的终端中,使用触摸
命令创建.vue
文件:
1touch src/components/AirportCard.vue
在文本编辑器中打开AirportCard.vue
,并添加以下内容:
1[label favorite-airports/src/components/AirportCard.vue]
2<template>
3 <div class="airport">
4 <p>{{ airport.abbreviation }}</p>
5 <p>{{ airport.name }}</p>
6 <p>{{ airport.city }}, {{ airport.state }}</p>
7 </div>
8</template>
9
10<script>
11export default {
12 props: {
13 airport: {
14 type: Object,
15 required: true
16 }
17 }
18}
19</script>
20
21<style scoped>
22.airport {
23 border: 3px solid;
24 border-radius: .5rem;
25 padding: 1rem;
26 margin-bottom: 1rem;
27}
28
29.airport p:first-child {
30 font-weight: bold;
31 font-size: 2.5rem;
32 margin: 1rem 0;
33}
34
35.airport p:last-child {
36 font-style: italic;
37 font-size: .8rem;
38}
39</style>
在AirportCard.vue
组件中,包装器<div>
包含了机场
的类别。本CSS通过添加边界来为每个机场提供卡片
的外观,为生成的HTML添加了一些风格。:第一个孩子
和:最后一个孩子
是应用于div
中的HTML中第一个和最后一个p
标签的不同风格的pseudo
选择器。
保存和退出文件。
在包装安装之前,请用以下代码更换现有App.vue
组件:
1[label favorite-airports/src/App.vue]
2<template>
3 <div class="wrapper">
4 <div v-for="airport in airports" :key="airport.abbreviation">
5 <airport-card :airport="airport" />
6 </div>
7 </div>
8</template>
9
10<script>
11import { ref } from 'vue'
12import allAirports from '@/data/airports.js'
13import AirportCard from '@/components/AirportCard.vue'
14
15export default {
16 components: {
17 AirportCard
18 },
19 setup() {
20 const airports = ref(allAirports)
21 return { airports }
22 }
23}
24</script>
25
26<style>
27#app {
28 font-family: Avenir, Helvetica, Arial, sans-serif;
29 -webkit-font-smoothing: antialiased;
30 -moz-osx-font-smoothing: grayscale;
31 text-align: center;
32 color: #2c3e50;
33 margin-top: 60px;
34}
35
36.wrapper {
37 display: grid;
38 grid-template-columns: 1fr 1fr 1fr;
39 grid-column-gap: 1rem;
40 max-width: 960px;
41 margin: 0 auto;
42}
43
44p,
45h3 {
46 grid-column: span 3;
47}
48</style>
此代码包含一个 v-for
循环,它通过 airports.js
数据进行迭代,并通过 prop :airport
传输的机场数据,返回一系列 AirportCards.vue
组件。
在项目设置时,使用终端中的npm run serve
命令运行本地开发服务器:
1npm run serve
这将启动您的本地主机
上的服务器,通常在端口8080
,打开您所选择的网页浏览器,然后访问本地主机:8080
,以查看以下内容:
现在你的示例应用程序已设置,在下一步,你将安装Vuex库,并创建一个商店
。这个商店是一个收藏的几个不同的Vuex项目,包括:状态,突变,行动,和Getters。
第2步:安装Vuex
当您在基于 Web 的应用程序上工作时,您通常会使用 state 工作。 状态是特定时间的数据集合。 这种状态可以通过发送
和承诺
方法通过用户交互来更改。
有些开发人员跳过动作
并直接进入参数
。然而,为了这个教程,你总是会执行一个动作
,这反过来叫做突变
。这样你就可以在动作中有多个突变。Vuex的基本规则是,突变只有一项工作,只有一项工作:更新商店。动作可以做很多不同的事情,包括组合数据、收集数据和运行JavaScript逻辑。
除了操作之外,还有 getters。一个 getter 是将多个状态值合并为一个值的一种方法. 如果您熟悉 Vue.js 中的计算属性,则 getters 可以被认为是特定状态的计算属性。
使用 Vuex 术语,开始安装和集成 Vuex. 打开终端并执行以下命令:
1npm install vuex@next --save
此命令将安装与 Vue.js 3.x 最兼容的 Vuex 版本,并将其保存到您的 package.json
文件中。接下来,为您的商店创建一个目录和索引文件。
1mkdir src/store
2touch src/store/index.js
打开文本编辑器,在您的store/index.js
文件中,开始您的Vuex商店。 要做到这一点,您需要利用Vuex的createStore
函数:
1[label airport-favorites/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5
6})
您还将导出
,因为您将在以后将其导入到您的main.js 文件中。
此时,您已设置了 Vuex 商店,但应用程序尚未了解它或如何使用它. 要完全初始化商店,请将其导入
到您的 main.js
文件中。
立即在「createApp(App)」之後,連鎖「使用」方法並傳入您正在輸入的商店,如下標示的代碼所示:
1[label favorite-airports/src/main.js]
2import { createApp } from 'vue'
3import App from './App.vue'
4import store from './store'
5
6createApp(App).use(store).mount('#app')
一旦你链接了使用
方法,保存此文件。使用
方法告诉Vue应用程序在构建应用程序时要组合哪个代码。
在您进入下一个部分之前,请在App.vue
文件中添加状态值,并引用它。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5state: {
6 firstName: 'John',
7 lastName: 'Doe'
8 },
9mutations: {
10
11},
12actions: {
13
14},
15getters: {
16
17}
18})
这些属性反映了商店所持有的数据类型:状态
是指状态(全球数据),突变
是指数据突变的承诺,行动
是指突变的发送,getters
是指商店
的计算属性。
保存store/index.js
,然后在文本编辑器中打开App.vue
文件,并添加以下内容:
1[label favorite-airports/src/App.vue]
2<template>
3 <div class="wrapper">
4 <p>{{ $store.state.firstName }} {{ $store.state.lastName }}</p>
5 <div v-for="airport in airports" :key="airport.abbreviation">
6 <airport-card :airport="airport" />
7 </div>
8 </div>
9</template>
10...
在这种情况下,$store
是您在main.js
文件中初始化的全球商店. 如果您将this.$store
登录到控制台,您将看到商店object
。
保存App.vue
,然后打开您的网页浏览器。在机场卡上,您将看到您在Vuex商店中保存的姓名和姓名。
在此步骤中,您安装了 Vuex 并创建了一个 Vuex 商店. 您添加了一些默认的商店数据,并使用点概念在$store
对象视图中显示它. 在下一步中,您将通过行动
和突变
更新您的 Vuex 商店,并将与getters
组合数据。
步骤 3 – 创建行动,突变和接收器
在第 2 步中,您手动安装了 Vuex 并将其集成到您的项目中。在此步骤中,您仍然在浏览器中渲染了您的姓名和姓名,但您将创建一个 Vuex getter 来渲染数据作为一个字符串。
要创建一个ghetter,请在所选的文本编辑器中打开src/store/index.js
文件。一旦打开,请在getters
对象中创建一个具有函数值的属性。
添加以下突出的代码:
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe'
8 },
9 ...
10 getters: {
11 fullName: function () {
12
13 }
14 }
15})
在这种情况下,您将使用该函数组合第一名和最后名称,并将结果的属性存储为fullName
。在函数内部,您将需要输入位于 Vuex 商店内的状态
对象。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe'
8 },
9 ...
10 getters: {
11 fullName: function (state) {
12 return `${state.firstName} ${state.lastName}`
13 }
14 }
15})
您正在使用模板字母在这里将FirstName
和LastName
放在一个字符串中。
保存此文件,然后返回App.vue
。在此文件中,删除第一个和最后一个值,并用getter替换它们:
1[label favorite-airports/src/App.vue]
2<template>
3 <div class="wrapper">
4 <p>{{ $store.getters.fullName }}</p>
5 <div v-for="airport in airports" :key="airport.abbreviation">
6 <airport-card :airport="airport" />
7 </div>
8 </div>
9</template>
10...
一旦你做這個變更並保存檔案,你的瀏覽器將 熱重載。你會像以前一樣在你的瀏覽器中看到你的名字和姓名,但現在你正在利用ghetter。
正如在最后一步中提到的,为了这个教程,你总是会使用一个操作,而不是直接突变数据。
在这个项目中,当用户点击该卡时,您将将机场的数据添加到最喜欢
列表中,您将首先获得创建的动作和突变,然后使用v-on
指令将其分配给一个点击事件。
要创建一个动作,请在文本编辑器中打开src/store/index.js
文件,在商店的动作
部分创建一个函数,就像getter
一样,函数名称将是您后来引用该动作的方式。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe',
8 favorites: [] // will store favorites here
9 },
10 mutations: {
11
12 },
13 actions: {
14 addToFavorites() {
15
16 }
17 },
18 getters: {
19 fullName: function (state) {
20 return `${state.firstName} ${state.lastName}`
21 }
22}
23})
一个动作接受两个参数:背景
,或Vue应用程序本身,和负载
,或您想要添加到商店的数据。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe',
8 favorites: []
9 },
10 mutations: {
11
12 },
13 actions: {
14 addToFavorites(context, payload) {
15 context.commit('UPDATE_FAVORITES', payload)
16 }
17 },
18 getters: {
19 fullName: function (state) {
20 return `${state.firstName} ${state.lastName}`
21 }
22 }
23})
委托
方法还接受两个论点:要调用的突变的名称和负载
或突变将取代状态的数据。
在这个代码中,你正在命名突变UPDATE_FAVORITES
。 突变名应该是无知的,而不是根据特定操作命名。 例如,像ADD_FAVORITE
和REMOVE_FAVORITE
这样的突变意味着一个逻辑,比如删除或添加数据片段。 这不是理想的,因为突变应该有一个工作和一个工作:更新状态。 要区分添加和删除数据,你可以有两个不同的行动
,从数组中删除或添加一个最喜欢的机场,然后执行一个单一的突变,名为UPDATE_FAVORITES
,以更新数组与任何经过的内容。 尽量减少你在你的商店中有多少突变将有助于你的Vuex商店更容易管理它,因为它
接下来,为此操作添加一些逻辑。当您将机场添加为最喜欢
时,您将将该效用量(机场数据)添加到现有数组中。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe',
8 favorites: []
9 },
10 mutations: {
11
12 },
13 actions: {
14 addToFavorites(context, payload) {
15 const favorites = context.state.favorites
16 favorites.push(payload)
17 context.commit('UPDATE_FAVORITES', favorites)
18 }
19 },
20 getters: {
21 fullName: function (state) {
22 return `${state.firstName} ${state.lastName}`
23 }
24 }
25})
在此时,您的操作将设置为将盈利负载
添加到您的喜爱
数组中,然后将具有变异数组的突变称为新数据。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5 state: {
6 firstName: 'John',
7 lastName: 'Doe',
8 favorites: []
9 },
10 mutations: {
11 UPDATE_FAVORITES(state, payload) {
12 state.favorites = payload
13 }
14 },
15 actions: {
16 addToFavorites(context, payload) {
17 const favorites = context.state.favorites
18 favorites.push(payload)
19 context.commit('UPDATE_FAVORITES', favorites)
20 }
21 },
22 getters: {
23 fullName: function (state) {
24 return `${state.firstName} ${state.lastName}`
25 }
26 }
27})
现在你有你的行动和突变,你可以保存这个文件。
要执行此操作,您可以在用户点击卡片时调用发送
事件,您将使用v-on
指令这样做。
在您的文本编辑器中打开App.vue
文件. 在<airport-card />
组件上,添加v-on
指令的短语语法(@
)以事件为点击
:
1[label favorite-airports/src/App.vue]
2<template>
3 <div class="wrapper">
4 <p>{{ $store.getters.fullName }}</p>
5 <div v-for="airport in airports" :key="airport.abbreviation">
6 <airport-card :airport="airport" @click="$store.dispatch('addToFavorites', airport)" />
7 </div>
8 <h2 v-if="$store.state.favorites.length">Favorites</h2>
9 <div v-for="airport in $store.state.favorites" :key="airport.abbreviation">
10 <airport-card :airport="airport" />
11 </div>
12 </div>
13</template>
14...
发送
函数接受两个参数:该动作的名称和您发送到该动作的负载数据。
现在,当你点击机场地图时,行动将调用变异,更新状态并将机场添加到喜爱的财产。
在此步骤中,您扩展了您之前创建的 Vuex 商店. 您创建了一项操作,该操作复制一个数组并将新项目推向该数组. 该操作被称为突变,从而更新了状态。
在最后一步中,您将部署Vuex模块。模块是将您的Vuex商店分割成更小的Vuex商店的绝佳方式。
步骤 4 – 构建 Vuex 模块
模块是较小的Vuex商店,这些商店被合并成一个Vuex商店,这类似于多种Vue.js组件被导入一个单一的.vue 文件,如 App.vue。在这个步骤中,您将把这个Vuex商店分为两个单独的模块。一个模块将用于用户
状态,另一个模块将针对机场
状态、行动和突变。
在您的终端中,进入商店
目录,并使用触摸
命令创建两个单独的文件。
1touch src/store/user.module.js
2touch src/store/airports.module.js
在 user.module.js
文件中,通过添加以下代码创建一个将默认导出的对象:
1[label favorite-airports/src/store/user.module.js]
2export default {
3 namespaced: true
4}
您还将添加名称空间
属性,其值为真
。名称空间
属性将这样做,以便您在稍后访问有点符号的属性时可以参考模块名称。
在此对象中,您将添加与用户相关的状态
和接收
信息:
1[label favorite-airports/src/store/user.module.js]
2export default {
3 namespaced: true,
4 state: {
5 firstName: 'John',
6 lastName: 'Doe'
7 },
8 getters: {
9 fullName: function (state) {
10 return `${state.firstName} ${state.lastName}`
11 }
12 }
13}
用户模块包含所有您需要的用户信息. 保存和退出文件。
在您的文本编辑器中打开airports.module.js
文件并添加以下内容:
1[label favorite-airports/src/store/airports.module.js]
2export default {
3 state: {
4 favorites: []
5 },
6 mutations: {
7 UPDATE_FAVORITES(state, payload) {
8 state.favorites = payload
9 }
10 },
11 actions: {
12 addToFavorites(context, payload) {
13 const favorites = context.state.favorites
14 favorites.push(payload)
15 context.commit('UPDATE_FAVORITES', favorites)
16 }
17 },
18}
现在你已经把机场
相关的突变,行动和状态,你可以保存你的airports.module.js
。
接下来,将这两个文件导入
到主store/index.js
文件中,在文本编辑器中打开store/index.js
文件,然后删除state
,mutations
,actions
和getters
属性。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3
4export default createStore({
5
6})
要注册模块,您需要将它们导入到这个index.js
文件中,并使用以下突出代码:
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3import UserModule from './user.module.js'
4import AirportsModule from './airports.module.js'
5
6export default createStore({
7
8})
从这里开始,您需要有一个名为模块
的属性,其值为一个对象。该对象内部的属性名称将是Vuex模块的名称。
1[label favorite-airports/src/store/index.js]
2import { createStore } from 'vuex'
3import UserModule from './user.module.js'
4import AirportsModule from './airports.module.js'
5
6export default createStore({
7modules: {
8 user: UserModule,
9 airports: AirportsModule
10}
11})
一旦您保存了此文件,您的模块现在已注册并合并到您的单一Vuex商店。保存商店/index.js
,然后打开App.vue
文件并更新它以参考新创建的模块:
1[label favorite-airports/src/App.vue]
2<template>
3 <div class="wrapper">
4 <p>{{ $store.getters['user/fullName'] }}</p>
5 <div v-for="airport in airports" :key="airport.abbreviation">
6 <airport-card :airport="airport" @click="$store.dispatch('addToFavorites', airport)" />
7 </div>
8 <h2 v-if="$store.state.airports.favorites.length">Favorites</h2>
9 <div v-for="airport in $store.state.airports.favorites" :key="airport.abbreviation">
10 <airport-card :airport="airport" />
11 </div>
12 </div>
13</template>
14...
现在你有一个模块化版本的Vuex设置。
在此步骤中,您将现有的Vuex商店分割成更小的块,称为模块,这些模块是将相关商店属性组合为更小的Vuex商店的绝佳方法,您还更新了App.vue
,以参考每个模块中的状态和发送事件。
结论
在这个设置中,状态中的数据在整个应用程序中都是全球性的,作为一个单一的真理来源,只能以行动和突变的形式进行明确的功能更新。
要了解更多关于 Vuex 的操作、突变和模块,请查看 Vue.js 核心团队撰写的 官方 Vuex 文档 有关 Vue 的更多教程,请参阅 如何使用 Vue.js 系列开发网站页面 。