开始在Vuex中存储Vue数据
让我们来看看如何使用Vuex来开始在一个地方存储所有的Vue数据。
Vuex是一个状态管理库,它可以让我们处理并最终存储来自UI的数据。在这篇文章中,我们将向你介绍Vuex的概念,如何使用它,以及如何用它在本地存储你的数据。
什么是Vuex?
你可能对状态的概念很熟悉,这只是数据的一种华丽的说法。我们可以在Vue中把状态存储在data() 函数本身。例如,在下面的Vue组件中,我们将切换状态存储为false,每当我们点击模板部分的按钮,我们就将其设置为true。
Vue.js组件
<template>
<button id="myButton" @click="runToggle">My Button</button>
</template>
<script>
export default {
data() {
return {
toggleState: false
}
},
methods: {
runToggle: function() {
this.toggleState = true;
}
}
}
</script>
这对于互动较少的组件来说效果很好,但如果我们有很多不同的组件,都依赖于相同的数据,也许跨越多个页面,我们就开始遇到问题了。为了处理这些数据,我们可以使用Vuex,它可以集中管理我们所有的数据,所以我们可以轻松地操作和访问这些数据。
为什么使用Vuex?
使用Vuex的主要原因是当你的数据结构变得非常复杂,以至于在你的组件之间维护和发送数据变得非常繁重。Vuex提供了一个单一的点来存储、操作和获取你的数据 - 大大简化了这个过程。对于小型项目或小型独立组件,你不一定需要使用Vuex!
开始使用Vuex
要开始使用Vuex,我们首先需要一个有效的Vue项目。如果你是Vue的新手,请阅读我关于创建你的第一个Vue项目的指南。之后,在你的Vue项目文件夹中,通过运行以下命令安装Vuex。
PowerShell
npm i vuex
现在Vuex已经安装完毕,我们可以开始将其添加到我们的项目中。首先,我们将建立一个中央Vuex商店。
在我们的Vue项目中,我们有一个叫做src/main.js的文件。让我们在那里添加我们的商店。你可以更新你的main.js文件,使其看起来像下面这个。
Vue.js组件
import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from './App.vue'
// I'm also using a router
import router from './router'
const app = createApp(App);
// Create a store for our to do list items
const store = createStore({
state() {
},
getters: {
},
mutations: {
}
});
// We can chain use() functions, so our app is now using a router and our Vuex store
app.use(router).use(store).mount('#app')
Vuex商店很容易配置,由于我们在初始化应用程序时使用了use(store) ,所以它在我们的应用程序中立即变得可用。让我们来看看我们的存储空间中的每个对象是做什么的。
state()- 这是我们存储数据的地方(也被称为状态)。对我们数据的任何更新或变化都将反映在这个state()函数中。getters- 这正是你所想的--它让我们从我们的存储中获取数据。mutations- 这些是我们用来更新数据的函数。我们可以在其中添加方法来更新和改变状态数据。
Vuex中的状态和获取器
正如前面所讨论的,state()将存储我们的数据,而getters是用来从我们的状态存储中获取数据的方法。
让我们来看看一个存储的例子。下面,我有一个状态存储,它返回一个叫做users的对象,它是一个不同的数组。我在这里放了一个作为例子,但如果你喜欢,你可以让它空着。
Vue.js组件
const store = createStore({
state () {
return {
users: [
{ id: '123-123-123', name: 'John Doe', email: 'johndoe@fjolt.com' }
]
}
},
getters: {
users (state) {
// state variable contains our state data
return state.users;
}
}
mutations: {
}
});
我们的state() 中的数据可以通过getters中的方法访问。我已经创建了一个getter函数,叫做users。当这个函数被调用时,我们通过state变量访问用户列表,该变量包含了我们状态存储中的所有数据。因此,当我们返回state.users ,我们得到了我们状态存储中的所有用户。
用Vuex突变或改变数据
所以现在我们有了一个保存一些数据的存储空间,以及通过getter函数获得这些数据的方法。我们需要做的最后一件事是创建一个突变方法,以拥有一个完整的存储空间。这些方法允许我们改变state()存储中的数据。
Vue.js组件
mutations: {
addUser(state, newUser) {
if(newUser.id !== undefined && typeof newUser.name == 'string' && typeof newUser.email == 'string') {
state.users.push({
id: newUser.id,
name: newUser.name,
email: newUser.email
})
}
}
}
当我们创建一个新的方法如addUser ,我们创建两个参数--一个是状态,是对状态存储的引用,另一个是我们要用这个突变推送的数据。上面的函数让我们通过这个突变推送一个对象,比如{ id: 'some-id', name: 'Jane Doe', email: 'janedoe@fjolt.com' } ,它将把这个值推送到Vuex商店。
变异是同步的
请注意,所有的突变都是同步的。如果你想使用一个异步事件,你必须使用动作。因此,不要尝试在突变中调用API或返回一个承诺!
关于行动的简短说明
如果你需要在突变中返回一个承诺或使用一个异步事件,你不能使用突变。相反,使用行动。行动在本质上与突变相同,因为它们让我们改变我们的状态存储,但它们返回一个承诺,并且可以是异步的。行动可以被添加到我们的Vuex商店的actions属性中。
Vue.js组件
const store = createStore({
state () {},
getters: {}
mutations: {},
actions: {
waitASecond: function() {
setTimeout(() => {
// Do something here with state()
}, 1000)
}
}
});
由于动作可以是异步的,我们可以用它们来代替各种异步事件,如API调用。所以请记住同步事件的突变和异步事件的动作。
如何使用Vuex的突变和获取器
现在我们已经定义了一个getter和一个mutation,我们需要在我们的应用程序中使用它们。这些函数可以通过this.$store访问。由于我们已经在main.js 中初始化了Vuex商店,我们在这个阶段其实不需要做任何其他事情。
让我们创建一个简单的组件,利用我们的商店。它所做的只是向商店添加一个新的项目,然后控制台将所有项目记录为字符串化的JSON。
Vue.js组件
<template>
<div id="new-user">
<input type="text" placeholder="Add a username.." id="username" ref="username">
<input type="text" placeholder="Add an email.." id="email" ref="email">
<input type="submit" id="submit-user" @click="newUser" value="Submit">
</div>
</template>
<script>
// I am using uuid for the ID for each user
import { v4 as uuidv4 } from 'uuid'
export default {
name: "NewUser",
methods: {
newUser: function() {
// We use "commit" to call mutations in Vuex
this.$store.commit('addUser', {
id: uuidv4(),
name: this.$refs.username.value,
email: this.$refs.email.value
})
// We can access getters via this.$store.getters
let allUsers = JSON.stringify(this.$store.getters.users);
console.log('New User Added!')
console.log(`All Users are here: ${allUsers}`);
}
}
}
</script>
我们可以通过this.$store 来访问我们商店中的几乎所有东西。当用户在我们的模板中点击提交时,我们调用我们的突变。你可能注意到我们已经写了
JavaScript
this.$store.commit('addUser', {});
这是因为我们不直接用Vuex调用突变。相反,我们使用commit()来调用它们。由于我们之前的突变被称为addUser,我们可以使用this.$store.commit('addUser', {}) 来调用该突变,其中第二个对象是我们传递给突变的数据。
然后,我们可以将所有的数据提交给我们的突变,它随后会更新我们在Vuex中的状态存储。现在我们可以很容易地将用户添加到我们的状态存储中,并且可以从我们的Vue应用程序的任何组件中访问它。
使用动作
注意:我们之前提到了异步事件的动作。你可以用与突变相同的方式使用动作,只是你必须调用this.$store.dispatch('actonName', {}) ,其中第一个参数是你想要调用的动作,第二个参数是你要传递给它的数据。
使用获取器
我们还使用了我们的getter来记录所有用户的控制台,只要有一个人被添加。要从Vuex访问任何getter,你只需要使用this.$store.getters 。所有的getter将被存储在该对象上,所以this.$store.getters.users引用了我们之前的user()getter。
如何将Vuex数据保存到本地存储中
现在我们已经建立了我们的Vuex存储,我们可以根据需要操作或改变我们的存储。关于Vuex的(也许是令人惊讶的)事情是它不是持久的。这意味着当你刷新页面时,所有的数据都会消失。解决这个问题的方法之一是把数据保存到数据库中。另一个方法是使用localStorage将数据存储在本地,这将确保应用程序在离线时也能工作。
因此,我们将看看如何将Vuex数据保存到localStorage,这样它在刷新后就会持续存在。你也可以把它保存到有API的数据库中,这将允许用户在登录后访问他们的数据。
我们要做的第一件事是在我们的商店上使用订阅方法。回到main.js ,你可以把这个添加到你的文件的结尾。
JavaScript
store.subscribe((mutation, state) => {
// The code inside the curly brackets fires any time a mutation occurs.
// When a mutation occurs, we'll stringify our entire state object - which
// contains our todo list. We'll put it in the users localStorage, so that
// their data will persist even if they refresh the page.
localStorage.setItem('store', JSON.stringify(state));
})
subscribe() 在Vuex中,当我们的存储发生突变时,就会触发订阅事件--这意味着任何时候数据被添加或删除,都会触发订阅事件。
这个订阅事件将把我们当前所有的状态数据存储在一个叫做store的localStorage项中--这意味着整个Vuex商店将被保存到用户的本地电脑中。
用Vue应用程序维护localstorage链接
保存到localStorage是一回事,但随后在应用程序中显示它又是另一回事。为此,我们需要在我们的Vuex突变中做一个新的突变,这将用我们的localStorage数据替换整个Vuex state()存储,如果它存在的话。
JavaScript
mutations: {
loadStore() {
if(localStorage.getItem('store')) {
try {
this.replaceState(JSON.parse(localStorage.getItem('store')));
}
catch(e) {
console.log('Could not initialize store', e);
}
}
}
// ... other mutations
}
这个函数所做的,是检查localStorage项目,store是否存在,如果存在,我们使用replaceState()--一个可以用任何东西替换整个状态存储的函数--来替换为这个localStorage数据。
由于我们想在应用程序加载时运行这个功能,我们需要将其添加到我们的App.vue 文件的beforeCreate() 钩。
脚本
<script>
import { useStore } from 'vuex'
export default {
beforeCreate() {
// Get our store
const store = useStore()
// use store.commit to run any mutation. Below we are running the loadStore mutation
store.commit('loadStore');
}
}
</script>
再次,请记住,我们使用commit() 来调用突变。我们已经创建了一个名为store的变量,因为它不会在beforeCreate() 钩子中完全设置好。使用它,我们启动了我们的loadStore 突变,同步我们的localStorage 和Vuex存储。
在Vuex中使用模块
由于我们上面的数据存储非常简单,我们没有必要用模块来使它复杂化。但有时,你会有一些独立的数据片段,你不想将它们混合在一起。对于这种情况,我们可以使用模块,它本质上是将我们的数据分离到不同的命名空间,这样我们就可以单独获取、变异和存储它们。
模块遵循与之前相同的原则,唯一的区别是我们可以定义多个Vuex存储。
Vue.js组件
const userStore = {
namespaced: true,
state() {
return {
users: []
}
},
mutations: { // ... }
getters: { // ... }
}
const articleStore = {
namespaced: true,
state() {
return {
articles: []
}
},
mutations: { // ... }
getters: { // ... }
}
const store = createStore({
modules: {
users: userStore,
articles: articleStore
}
})
现在我们有两个逻辑上不同的数据存储。如果我们想访问userStores ,我们会在this.$store ,因为那里仍然保存着我们所有的组合存储。
访问模块获取器
在上面的例子中,由于我们的数据存储方式略有不同,我们需要使用this.store.getters\['user/users'\]来访问我们的用户getter。如果我们有一个名为usernames的获取器,我们同样可以通过使用`this.store.getters['users/usernames']` 来访问它。
访问模块突变
与之前类似,我们仍然可以通过this.store.commit('users/addUser', {})` 。
总结
我希望你喜欢这个Vuex入门指南。我们已经涵盖了加载、保存和持久化你的Vuex存储数据所需的一切。让我们回顾一下我们在这里看到的东西。
- 我们创建了一个新的Vuex存储。
- 我们已经学会了如何创建getter方法来获取Vuex数据。
- 我们已经学会了如何使用突变,并通过commit()调用它们来改变Vuex数据。
- 我们学习了如何使用模块来分离不同的数据存储。
- 我们谈到了行动是异步的,而变异是同步的。
- 我们已经学会了如何使用localStorage来持久化我们的Vuex数据。
如果你想看到更多的Vuex操作,请阅读我的完整指南,在Vue中创建一个待办事项列表应用程序。关于更多的Vue内容,都可以在这里找到。
经Johnny Simpson, DZone MVB许可发表于DZone。点击这里查看原文。