Vue2.0 Vuex Vuex模块化+namespace

到这里就可以使用Vuex编写业务了但是如果你想写的再好一点强烈看一下本文

Vuex模块化编码

我们看一下index.js

store > index.js

import Vuex from 'vuex'
import Vue from 'vue'

Vue.use(Vuex)

const actions = {
    //这俩个好像与求和有关
    jia(context,value){
        context.mutations('JIA',value)
    },
    jian(context,value){
        context.mutations('JIAN',value)
    },

}

const mutations = {
    //这里有三个mutations
    //JIA和JIAN服务于求和,但是ADD_PERSON服务于Person组件
    JIA(state,value){
        state.sum += value
    },
    JIAN(state,value){
        state.sum -= value
    },
    ADD_PERSON(state,value){
        state.personList.unshift(value)
    }
}

const state = {
    sum:0,
    school:'bilibili',
    subject: 'Vue',
    personList:[
        {id:'001',name:'张三'}
    ]
}

//准备getters:用于将state中的数据进行加工
const getters = {
    //给你要实现运算的值取一个名字
    bigSum(state){ //能接收到state的值
        return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
    }
}

export default new Vuex.Store({
    actions,mutations,state,
    getters
})

mutations里如果业务一旦多起来,都写在mutations会很凌乱,而且难以维护。 我们的目的是把不同分类的mutations放在不同的位置:

store > index.js

//求和功能相关的配置
const countOptions = {
    actions:{},
    mutations:{},
    state:{},
    getters:{},
}
//人员管理功能相关的配置
const PersonOptions = {
    actions:{},
    mutations:{},
    state:{},
    getters:{},
}

把配置放入:

//求和功能相关的配置
const countOptions = {
    actions:{
        jia(context,value){
            context.mutations('JIA',value)
        },
        jian(context,value){
            context.mutations('JIAN',value)
        },
    },
    mutations:{
        JIA(state,value){
            state.sum += value
        },
        JIAN(state,value){
            state.sum -= value
        },
    },
    state:{
        sum:0,
        school:'bilibili',
        subject: 'Vue',
    },
    getters:{
        //给你要实现运算的值取一个名字
        bigSum(state){ //能接收到state的值
            return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
        }
    },
} 
//人员管理功能相关的配置
const PersonOptions = {
    actions:{},
    mutations:{
        ADD_PERSON(state,value){
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'张三'}
        ]
    },
    getters:{},
}

这样里面没有actions,mutations,state,getters这么一些

怎么使用:

export default new Vuex.Store({
    modules:{//模块的复数
        //这么写的含义就是Store里面所保存的东西都开始分类了
        a:countOptions,
        b:PersonOptions
    }
})

原来的Vuex.Store里面:

Store  	-> Actions
		-> Mutations
		-> State
		-> getters

模块化编码后就是:

store	->	a(分类名自己取)	->Actions
							->Mutations
							->State
							->getters
				
		->	b(分类名自己取)	->Actions
							->Mutations
							->State
							->getters

*可以触发对象的简写形式

因为这样要访问得写$store.a.state.sum形式,所以就先不用简写形式

先分析一个组件

App.vue






借助mapState生成的personList

...mapState(['sum','personList']),里面用到的都得是在store里面有的东西

看看store里面到底长啥样:

mountde(){
    console.log(this.$store)
}
Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
    commit: ƒ boundCommit(type, payload, options)
        length: 3
        name: "boundCommit"
        prototype: {constructor: ƒ}
        arguments: (...)
        caller: (...)
        [[FunctionLocation]]: vuex.esm.js?2f62:408
        [[Prototype]]: ƒ ()
        [[Scopes]]: Scopes[4]
    dispatch: ƒ boundDispatch(type, payload)
        length: 2
        name: "boundDispatch"
        prototype: {constructor: ƒ}
        arguments: (...)
        caller: (...)
        [[FunctionLocation]]: vuex.esm.js?2f62:405
        [[Prototype]]: ƒ ()
        [[Scopes]]: Scopes[4]
    getters:
        bigSum: (...)
        get bigSum: ƒ ()
        [[Prototype]]: Object
    registerModule: (e,t,r)=> {…}
    replaceState: e=>{l.initialState=A(e),t(e)}
    strict: false
    unregisterModule: e=> {…}
    _actionSubscribers: (2) [{…}, {…}]
    _actions: {jia: Array(1), jian: Array(1)}
    _committing: false
    _devtoolHook: {enabled: undefined, _buffer: Array(0), store: Store, initialState: {…}, Vue: ƒ, …}
    _makeLocalGettersCache: {}
    _modules: ModuleCollection {root: Module}
    _modulesNamespaceMap: {}
    _mutations: {JIA: Array(1), JIAN: Array(1), ADD_PERSON: Array(1)}
    _subscribers: [ƒ]
    _vm: Vue {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    _watcherVM: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    _wrappedGetters: {bigSum: ƒ}
    state: Object
        a: Object
            school: (...)
            subject: (...)
            sum: (...)
            __ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
            get school: ƒ reactiveGetter()
            set school: ƒ reactiveSetter(newVal)
            get subject: ƒ reactiveGetter()
            set subject: ƒ reactiveSetter(newVal)
            get sum: ƒ reactiveGetter()
            set sum: ƒ reactiveSetter(newVal)
            [[Prototype]]: Object
        b: Object
            personList: (...)
            __ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
            get personList: ƒ reactiveGetter()
            set personList: ƒ reactiveSetter(newVal)
            [[Prototype]]: Object
        __ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
        get a: ƒ reactiveGetter()
        set a: ƒ reactiveSetter(newVal)
        get b: ƒ reactiveGetter()
        set b: ƒ reactiveSetter(newVal)
        [[Prototype]]: Object
    [[Prototype]]: Object

state里面的。所以说知道怎么修改了(先修改state):






那能不能像之前那样写?

是可以的

...mapState('a',['sum']),

这样写会报一个错误:

[vuex] module namespace not found in mapState(): a/
模块的名字空间没有找到在mapsState里面:a
module:模块
namespace:名字空间
not found:没有找到

你如果想在mapState里面通过第一个参数去指定分类。你想这么写,你得有个前提:在配置Vuex的时候在配置里面加上一个配置项:namespaced

const countOptions = {
    namespaced: true,
    actions:{
        jia(context,value){
            context.mutations('JIA',value)
        },
        jian(context,value){
            context.mutations('JIAN',value)
        },
    },
    mutations:{
        JIA(state,value){
            state.sum += value
        },
        JIAN(state,value){
            state.sum -= value
        },
    },
    state:{
        sum:0,
        school:'bilibili',
        subject: 'Vue',
    },
    getters:{
        //给你要实现运算的值取一个名字
        bigSum(state){ //能接收到state的值
            return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
        }
    },
} 

如果不写默认为false。你只有写了,你这个a才能被mapState里面所认识

所有的简写都是有代价的


person同理

store > index.js

//人员管理功能相关的配置
const PersonOptions = {
    namespaced: true,
    actions:{},
    mutations:{
        ADD_PERSON(state,value){
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'张三'}
        ]
    },
    getters:{},
}

App.vue

computed:{
    ...mapState('a',['sum']),
    ...mapState('b',['personList']),
    ...mapGetters(['bigSum'])
},

但是一点+:

[vuex] unknown mutation type: JIA

你没说明白,所以还是上面的操作:

methods:{
    ...mapMutations('a',['JIA','JIAN']),
},
得说明白谁的Actions谁的Mutations谁的State谁的getters

[vuex] unknown getter: bigSum

同理:

...mapGetters('a',['bigSum'])

结合上面我们去修改person.vue里的求和

查看this.$store

Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
    commit: ƒ boundCommit(type, payload, options)
    dispatch: ƒ boundDispatch(type, payload)
    getters: {}
    registerModule: (e,t,r)=> {…}
    replaceState: e=>{l.initialState=A(e),t(e)}
    strict: false
    unregisterModule: e=> {…}
    _actionSubscribers: (2) [{…}, {…}]
    _actions: {a/jia: Array(1), a/jian: Array(1)}
    _committing: false
    _devtoolHook: {enabled: undefined, _buffer: Array(0), store: Store, initialState: {…}, Vue: ƒ, …}
    _makeLocalGettersCache: {a/: {…}, b/: {…}}
    _modules: ModuleCollection {root: Module}
    _modulesNamespaceMap: {a/: Module, b/: Module}
    _mutations: {a/JIA: Array(1), a/JIAN: Array(1), b/ADD_PERSON: Array(1)}
    _subscribers: [ƒ]
    _vm: Vue {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    _watcherVM: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
    _wrappedGetters: {a/bigSum: ƒ}
    state: Object
        a: (...)
        b: (...)

state

state里面只有ab所以这么改:

computed:{
    personList(){
        return this.$store.state.b.personList
    },
    sum(){
        return this.$store.state.a.sum
    }
}

点击添加,控制台报错:

[vuex] unknown mutation type: ADD_PERSON
this.$store.commit('b','ADD_PERSON',personObj)

你觉得这样可以,但是:

[vuex] unknown mutation type: b

也就是它不支持这个写法,得这么写:

Mutation(commit)

methods:{
    add(){
        //id可以用nanoid生成
        const personObj = {id: nanoid(),name: this.name}
        this.$store.commit('b/ADD_PERSON',personObj)
        this.name = ''//清空输入框
    }
},

dispatch

store > index.js

actions:{
    addPersonWang(context,value){
        if(value.name.indexOf('王') === 0){
            context.commit('ADD_PERSON',value)
        }
    }
},

Person.vue

<button @click="addWang">添加一个姓王的人button>

错误写法:

addWang(){
    const personObj = {id:nanoid(),name: this.name}
    this.$store.dispatch('addPersonWang',personObj)
    this.name = ''
}

报的错:

[vuex] unknown action type: addPersonWang

你就知道怎么写了:

addWang(){
    const personObj = {id:nanoid(),name: this.name}
    this.$store.dispatch('b/addPersonWang',personObj)
    this.name = ''
}

输入李四没添加进去,但是这不太好(提示):

actions:{
    addPersonWang(context,value){
        if(value.name.indexOf('王') === 0){
            context.commit('ADD_PERSON',value)
        }else{
            alert('添加的人必须姓王')
        }
    }
},

getters

getters:{
    fristPersonName(state){//这个state拿到的只是自己的state,不是全部的state
        return state.personList[0].name
    }
},
computed:{
    personList(){
        return this.$store.state.b.personList
    },
    sum(){
        return this.$store.state.a.sum
    },
    fristPersonName(){
        return this.$store.getters.b.fristPersonName
    }
}

控制台出现:

[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'fristPersonName')"

说明你在getters里那不到b

Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
    commit: ƒ boundCommit(type, payload, options)
    dispatch: ƒ boundDispatch(type, payload)
    getters:
        a/bigSum: (...)
        b/fristPersonName: (...)
        get a/bigSum: ƒ ()
        get b/fristPersonName: ƒ ()
        [[Prototype]]: Object

getters的分类与state里的分类有所不同

所以得这么取:

fristPersonName(){
    return this.$store.getters.b/fristPersonName.fristPersonName
}

但是你这么写不行啊。有./。所以得这么写:

fristPersonName(){
    return this.$store.getters['b/fristPersonName']
}

拆解的意义

如果a中有一个user

但是b中也有一个user属性

它俩一点也不冲突。解决命名冲突问题

而且a和b中的countOptionsPersonOptions也不是非得写在一起:

store > 创建count.js

//求和功能相关的配置
export default{
    namespaced: true,
    actions:{
        jia(context,value){
            context.mutations('JIA',value)
        },
        jian(context,value){
            context.mutations('JIAN',value)
        },
    },
    mutations:{
        JIA(state,value){
            state.sum += value
        },
        JIAN(state,value){
            state.sum -= value
        },
    },
    state:{
        sum:0,
        school:'bilibili',
        subject: 'Vue',
    },
    getters:{
        //给你要实现运算的值取一个名字
        bigSum(state){ //能接收到state的值
            return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
        }
    },
} 

store > 创建person.js

//人员管理功能相关的配置
export default{
    namespaced: true,
    actions:{
        addPersonWang(context,value){
            if(value.name.indexOf('王') === 0){
                context.commit('ADD_PERSON',value)
            }else{
                alert('添加的人必须姓王')
            }
        }
    },
    mutations:{
        ADD_PERSON(state,value){
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'张三'}
        ]
    },
    getters:{
        fristPersonName(state){//这个state拿到的只是自己的state,不是全部的state
            return state.personList[0].name
        }
    },
}

store > index.js

import Vuex from 'vuex'
import Vue from 'vue'

import countOptions from './count'
import PersonOptions from './person'

Vue.use(Vuex)

export default new Vuex.Store({
    modules:{//模块的复数
        //这么写的含义就是Store里面所保存的东西都开始分类了
        a:countOptions,
        b:PersonOptions
    }
})

还有一条线没走过,就是服务器的线(带有网络请求)

store > person.js

import axios from 'axios'//引入axios
addPersonForServer(context){
    axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
        response=>{
            console.log('成功了',response.data)
            context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
        },
        error=>{
            console.log('报错了,信是:',error.message)
        }
    )
}

person.vue

<button @click="addPersonServer">添加一个人,名字随机button>
addPersonServer(){
    this.$store.dispatch('b/addPersonForServer')
}

总结

模块化 + 命名空间

1.目的: 让代码更好维护,让多种分类更加明确。

2.store > index.js开启命名空间:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)//使用Vuex插件
const name1 = {
    namespaced: true,
    actions:{...},
    mutations:{...},
    state:{...},
    getters:{...}
}
const name2 = {
    namespaced: true,
    actions:{...},
    mutations:{...},
    state:{...},
    getters:{...}
}
...
export default new Vuex.Store({
	modules:{
    	a:name1,
        b:name2
    }
})

3.开启命名空间后,组件读取state数据:

//方式一: 自己直接读取
this.$store.state.a.list
//方式二: 借助mapState读取
...mapState('a',['sum'])

4.开启命名空间后,组件中读取getters数据

//方式一: 自己直接读取
this.$store.getters[a/方法名]
//方式二: 借助mapGetters读取
...mapGetters('a',['bigSum'])

5.开启命名空间后,组件中读取dispatch

//方式一: 自己直接读取
this.$store.dispatch('a/方法名',value)
//方式二: 借助mapActions读取
...mapActions('a',{add:'sum',jian:'jian'})

6.开启命名空间后,组件中调用commit

//方式一: 自己直接commit
this.$store.commit('a/方法名',value)
//方式二: 借助mapMutations:
...mapMutations('a',{add:'JIA',jian:'JIAN'})

(重点中的重点)网络请求传数据

你可能感兴趣的:(#,vue2,vue.js,javascript,前端)