如何在Vuex中存储Vue数据

780 阅读7分钟

开始在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()访问所有的突变只是,我们还需要添加我们的命名空间。要想在userStore中使用一个名为addUser的突变,我们要写this.store.commit()访问所有的突变--只是,我们还需要添加我们的命名空间。要想在`userStore` 中使用一个名为 addUser 的突变,我们要写`this.store.commit('users/addUser', {})` 。

总结

我希望你喜欢这个Vuex入门指南。我们已经涵盖了加载、保存和持久化你的Vuex存储数据所需的一切。让我们回顾一下我们在这里看到的东西。

  • 我们创建了一个新的Vuex存储。
  • 我们已经学会了如何创建getter方法来获取Vuex数据。
  • 我们已经学会了如何使用突变,并通过commit()调用它们来改变Vuex数据。
  • 我们学习了如何使用模块来分离不同的数据存储。
  • 我们谈到了行动是异步的,而变异是同步的。
  • 我们已经学会了如何使用localStorage来持久化我们的Vuex数据。

如果你想看到更多的Vuex操作,请阅读我的完整指南,在Vue中创建一个待办事项列表应用程序。关于更多的Vue内容,都可以在这里找到

经Johnny Simpson, DZone MVB许可发表于DZone。点击这里查看原文。