[译]Managing Vue.js State with Vuex

原文

准备

安装

Vuex, 是Vue官方出的package, 它不是Vue内置的。需要另外安装。

npm install vuex --save

然后,需要在应用启动文件启用Vuex

main.js

import Vue from 'vue';
import Vuex from 'vues';
import App from 'App.vue';

Vue.use(Vuex);

new Vue({
    el: '#app',
    render: h => h(app)
});

创建一个Store

store.js

export const store = new Vuex.store({
    state: {
        safelyStoredNumber: 0
    }
});

为了使用这个store你必须在你所有要使用其的component里面import这个store。 或者你可以将它注入到跟Vue实例中,这样应用的其他组件都可以使用这个store了。

main.js

import Vue from 'vue';
import Vuex from 'vuex';
import App from 'App.vue';
import { store } from './store.js';

Vue.use(Vuex);

new Vue({
    store, 
    el: '#app',
    render: h => h (App)
});

访问State

下载创建getter来从store中读取数据。

使用Getters

在store中getter是一个简单的函数,它接收一个state对象返回它的一个值。在component中,可以通过this.$store.getters.property做为一个计算属性(不是函数)来获取。如果getter需要接受一个参数,可以返货一个接受参数的函数。

store.js

export const store = new Vuex.store({
    state: {
        safelyStoredNumber: 0
    },
    getters: {
        safelyStoredNumber: state => state.safelyStoredNumber,
        storedNumberMatches(state) {
            return matchNumber => {
                return state.safelyStoredNumber === matcheNumber;
            }
        }
        // 简写
        storedNumberMatches: state => matchedNumber => state.safelyStoreNumber === matcheNumber
    }
});

在components最简单的访问getters的方法是通过Vuex的mapGetters方法。它让你可以在component中直接使用safelyStoreNumber而不是this.$store.getters.safelyStoreNumber

App.vue

<template>
    <p>The safely stored number: {{safelyStoredNumber}}</p>
</template>

<script>
    import { mapGetters } from 'vuex'
    
    export default {
        computed: {
            ...mapGetters([
                'safelyStoredNumber'
            ])
        }
    }
</script>

修改state

Synchronous Mutations

调用mutation的函数来修改state。mutation接受一个当前的state和一个可选的payload。payload可以是任何对象。mutation必须是同步的,并且不应该返回任何值。使用this.$store.commit('mutationName', payload)来调用mutation。

store.js

export const store = new Vuex.Store({
    state: {
        safelyStoredNumber: 0
    },
    ...
    mutations: {
        incrementStoredNumber(state) {
            state.safelyStoredNumber++;
        },
        setStoredNumber(state, newNumber) {
            state.saftlyStoredNumber = newNumber;
        }
    }
});

和getters一样,Vuex有一个使用mutation的简便方法,那就是mapMutations方法。

App.vue

<template>
    <p>The safely stored number: {{safelyStoredNumber}}</p>
</template>

<script>
    import { mapMutations } from 'vuex'

    export default {
        ...
        methods: {
            ...mapMutations([
                'incrementStoredNumber',
                'setStoredNumber'
            ])
        }
    }
</script>

异步Actions

在一些复杂的应用中,你可能需要执行一些异步方法来修改state。Vues使用actions来处理这个。action接受一个state context,使得在action里面可以访问getter和commit mutations。
action最好(非必需)是返回一个Promise指明完成状态。使用ES2017的async/await,可以轻松的检出async action。在component中通过this.$store.dispatch('actionName', payload).then(response => {})使用action。

在action中通过context.commit('mutationName', payload)修改state。

store.js

import myRemoteService from './my-remote-service.js'

export const store = new Vuex.store({
    state: {
        safelyStoredNumber: 0
    },
    ...
    actions: {
        async setNumberToRemoteValue(context) {
            // commit 'setStoredNuymber' mutation
            context.commit('setStoredNumber', await myRemoteService.getRemoteValue());
            return Promise.resolve();
        },
    }
});

和getters一样,Vuex有一个使用action的简便方法,那就是mapActions方法。

App.vue

<template>
    <p> The safely stored number: {{safelyStoredNumber}}</p>
</template>

<script>
    import { mapActions } from 'vuex'
    export default {
        ...
        methods: {
            ...mapActions([
                'setNumberToRemoteValue',
            ])
        }
    }
</script>

模块化

随着actions,mutations, getters越来越多你需要按照模块来分割它们。Vuex提供了Modules来实现这个。

my-store-module.js

export const myModule = {
    // This makes your getters, mutations, and actions accessed by, eg: 'myModule/myModularizedNumber' instead of mounting getters, mutations, and actions to the root namespace.
    namespaced: true,
    state: {
        myModularizedNumber: 0
    },
    getters: {
        myModularizedNumber: state => state.myModularizedNumber
    },
    mutations: {
        setModularizedNumber(state, newNumber) {
            state.myModularizedNumber = newNumber
        }
    }
}

store.js

import { myModule } from  './my-store-module.js';

export const store = new Vuex.store({
    modules: {
        myModule
    },
    state: {
        safelyStoredNumber: 0
    },
    ...
});

mapGetters, mapMutations, mapActions可以接受第一个参数来标明module的命名空间。

...mapGetters([
    'myModule/nestedModule/subNestedModule/exampleGetter',
    'myModule/nestedModule/subNestedModule/anotherGetter',
])

可以使用上面的代码来替代上面的代码:

...mapGetters('myModule/testedModule/subNestedModule', [
    'exampleGetter',
    'anotherGetter'
])
原文地址:https://www.cnblogs.com/irocker/p/intro-to-vuex.html