Vuex下Store的模块化拆分实践

前言 最近的项目用到了 vue js + vuex + vue-router 全家桶,版本为 >2 0,在搞Store的时候发现,圈子里大部分关于vuex的文章都是

前言

最近的项目用到了 vue.js + vuex + vue-router 全家桶,版本为 >2.0,在搞Store的时候发现,圈子里大部分关于vuex的文章都是比较基础的Demo搭建方式,很少有涉及到比较复杂的模块化拆分的Store实践,而且事实上也有朋友在实践中问到过这方面的内容,vuex自身提供了模块化的方式,因此在这里总结一下我自己在项目里的心得。

模块化拆分

vue.js的项目文件结构在这里就不说了,大家可以通过 vue-cli

初始化项目,脚手架会为你搭建一个start项目的最佳实践。

默认你已经搭架好了一个项目,而且需要建立或者已经是一个复杂的Store,但是还没有进行模块拆分,你可以尝试对其进行模块拆分,当然在一开始你不必一定需要这么做。

1. 安装Vuex,建立文件结构

在项目根目录下安装vuex:

npm install vuex -S

安装完毕后,在项目的 src

文件夹下新建一个 store

文件夹,并且分别在其中新建 modules

, actions

, mutations

, getters

, constants

子文件夹和一个 index.js

文件。

目录结构如下:

--demo

-----build

-----config

-----node_modules

-----src

--------assets

--------components

--------store

-----------actions

--------------aAction.js

--------------bAction.js

--------------cAction.js

-----------constants

--------------types.js

-----------getters

--------------aGetter.js

-----------modules

--------------aModules.js

--------------bModules.js

--------------cModules.js

--------------index.js

-----------mutations

--------------aMutation.js

--------------bMutation.js

--------------cMutation.js

-----------index.js

--------App.vue

--------main.js

-----static

-----utils

-----test

-----index.html

好了,基本的文件结构大概就是上面:point_up_2:这样的。

2. 编写模块A

在编写模块之前,首先设定一些type类,例如:

types.js

module.exports = keyMirror({

FETCH_LIST_REQUEST: null,

FETCH_LIST_SUCCESS: null,

FETCH_LISR_FAILURE: null

})

function keyMirror (obj) {

if (obj instanceof Object) {

var _obj = Object.assign({}, obj)

var _keyArray = Object.keys(obj)

_keyArray.forEach(key => _obj[key] = key)

return _obj

}

}

上面:point_up_2:自己实现keyMirror的方法,大家也可以使用下面这个包:

github.com/STRML/keyMirror

keyMirror的作用就是下面这个一个形式��,作用其实也不是很大:

Input: {key1: null, key2: null}

Output: {key1: key1, key2: key2}

actions/aAction.js

import { FETCH_LIST_REQUEST, FETCH_LIST_SUCCESS, FETCH_LISR_FAILURE } from  '../constants/types'

import { toQueryString } from '../../utils'

import axios from 'axios'

export const fetchListAction = {

fetchList ({ commit, state }, param) {

commit(FETCH_LIST_REQUEST)

axios.get('http://youdomain.com/list')

.then(function (response) {

commit(FETCH_LIST_SUCCESS, {

data: response.data

})

console.log(response);

})

.catch(function (error) {

commit(FETCH_LIST_FAILURE, {

error: error

})

console.log(error);

});

}

}

getters/aGetter.js

export const = fetchListGetter = {

hotList (state) {

return state.fetchList.data.slice(0, 10)

}

}

mutations/aMutation.js

import { FETCH_LIST_REQUEST, FETCH_LIST_SUCCESS, FETCH_LISR_FAILURE } from  '../constants/types'

export const fetchListMutation = {

[FETCH_LIST_REQUEST] (state) {

state.isFetching = true

},

[FETCH_LIST_SUCCESS] (state, action) {

state.isFetching = false

state.data = action.data

state.lastUpdated = (new Date()).getTime()

},

[FETCH_LIST_FAILURE] (state, action) {

state.isFetching = false

state.error = action.error

}

}

modules/aModule.js

import { fetchListAction } from '../actions/aAction'

import { fetchListGetter } from '../getter/aGetter'

import { fetchListMutation } from '../mutation/aMutation'

export const list = {

state: {

isFetching: false,

data: []

}

actions: fetchListAction,

getters: fetchListGetter,

mutations: fetchListMutation

}

modules/index.js

import { list } from './aModule'

module.exports = {

list: list

}

3. 挂载store

index.js

import Vue from 'vue'

import Vuex from 'vuex'

import createLogger from 'vuex/dist/logger'

import { list } from './modules'

Vue.use(Vuex)

const store = new Vuex.Store({

modules: {

list: list

},

plugins: [createLogger()],

strict: process.env.NODE_ENV !== 'production'

})

if (module.hot) {

module.hot.accept(['./modules'], () => {

const newMutations = require('./modules').default

store.hotUpdate({

mutations: newMutations

})

})

}

export default store

4. store注入vue实例

main.js

····

import store from './store'

····

var vue = new Vue({

store,

····

})

vue.$mount('#app')

5. 在Component中使用

Vue 提供了组件中使用的 mapState

, mapAction

, mapGetter

方法,因此可以很方便的调用。

Example.vue

<template>

·········

</template>

<script>

import { mapState, mapActions, mapGetters } from 'vuex'

module.exports = {

·······

methods: {

...mapActions([

'fetchList'

])

},

computed: {

...mapState{

list: state => state.list

},

...mapGetter{[

'hotList'

]}

}

}

</script>

<style>

·······

</style>

复用模块

模块化拆分之后可以实现较为复杂的数据流,特别地,如果对action和mutation稍加改造,就可以复用模块:

比如我们在Example.vue中发起Action:

Example.vue

<template>

·········

</template>

<script>

import { mapState, mapActions, mapGetters } from 'vuex'

module.exports = {

·······

mounted () {

this.fetchList({

request: 'week'

})

},

methods: {

...mapActions([

'fetchList'

])

},

computed: {

...mapState{

list: state => state.list

},

...mapGetter{[

'hotList'

]}

}

}

</script>

<style>

·······

</style>

在上面的例子中,我们在组件挂载完成之后发起了一个fetchList的action,并添加了一个名为 week

的参数,接下来对aAction.js做一些修改。

actions/aAction.js

import { FETCH_LIST_REQUEST, FETCH_LIST_SUCCESS, FETCH_LISR_FAILURE } from  '../constants/types'

import { toQueryString } from '../../utils'

import axios from 'axios'

export const fetchListAction = {

fetchList ({ commit, state }, param) {

commit(FETCH_LIST_REQUEST, {

request: param.request

})

axios.get(`http://youdomain.com/${param['request']}list`)

.then(function (response) {

commit(FETCH_LIST_SUCCESS, {

request: param['request']

data: response.data

})

console.log(response);

})

.catch(function (error) {

commit(FETCH_LIST_FAILURE, {

request: param.request

error: error

})

console.log(error);

});

}

}

请求成功之后,在 commit()中加入了一个request的参数,这样Mutation就可以从里面获取相应的参数,最后对aMutation做一些修改。

mutations/aMutation.js

import { FETCH_LIST_REQUEST, FETCH_LIST_SUCCESS, FETCH_LISR_FAILURE } from  '../constants/types'

export const fetchListMutation = {

[FETCH_LIST_REQUEST] (state, action) {

state[action.request].isFetching = true

},

[FETCH_LIST_SUCCESS] (state, action) {

state[action.request].isFetching = false

state[action.request].data = action.data

state[action.request].lastUpdated = (new Date()).getTime()

},

[FETCH_LIST_FAILURE] (state, action) {

state[action.request].isFetching = false

state[action.request].error = action.error

}

}

state加入了[action.request],以区分不同的接口数据。

完成以上修改后,只需要在组件调用相应的action时加入不同的参数,就可以调用相同类型但数据不同的接口。

总结

以上是我在Vuex实践中总结的一些东西,分享给大家,如果有不合理或者错误:x:的地方,也希望各位老司机不吝赐教:pray::pray:,有机会多交流。

微信号:pasturn

Github: https://github.com/pasturn

未登录用户
全部评论0
到底啦