0
点赞
收藏
分享

微信扫一扫

Vue3之Vuex

Villagers 2022-04-04 阅读 79

1. Vuex的基本使用

vuex的安装:

vuex的配置,@/store/index.js:

import {createStore} from 'vuex'//导入createStore构造函数
export default createStore({ 
    state:{ //Vuex的状态,实际上就是存数据的地方
        person:{
            name:'jack',
            age:200
        }
    },
    getters:{ //提供获取Vux状态的方式, 注意在组件中调用时getPerson是以属性的方式被访问
        getPerson(state){
            return state.person
        }
    },
    mutations:{ //提供直接操作Vuex的方法,注意mutations里的方法中不能有任何异步操做
        ageGrow(state, value){
            //第一个参数state为Vuex状态;第二个参数为commit函数传来的值
            state.person.age += value
        }
    },
    actions:{ //提供通过mutations方法来简介操作Vuex的方法
        ageGrow(context, value){ 
            //第一个参数context为上下文,提供一些方法;第二个参数为dispatch函数传来的值
            context.commit('ageGrow', value)
        }
    }, 
})

在@/main.js中引入:

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app = createApp(App)
app.use(store)
app.mount('#app')

在组件中使用Vuex:

<template>
    <h1>名字:{{person.name}}--年龄:{{person.age}}</h1>
    <input type="text" v-model="value">
    <button @click="ageGrow(value)">增加年龄</button>
    <!-- 在input框输入一个数字,点击按钮,可以看到年龄发生变化,说明Vuex正常工作 -->
</template>

<script>
    import {useStore} from 'vuex' 
    import {ref} from 'vue'
    export default {
        setup(){
            const store = useStore()    //获取store对象
            let person = store.getters.getPerson    //从组件中获取状态(数据)person 方式一
            // let person = store.state.person      //从组件中获取状态(数据)person 方式二
            let value = ref('输入年龄的增量')
            function ageGrow(ageGrowth){
                ageGrowth = parseInt(ageGrowth)
                if(isNaN(ageGrowth)){
                    ageGrowth = 0
                }
                store.dispatch('ageGrow', ageGrowth)
                //通过dispatch来调用actions里的'ageGrow'方法,参数为ageGrowth
            }   //actions的方法又会通过commit来调用mutations里的方法,从而引起状态(数据)的变化
            return {
                person, 
                value,
                ageGrow
            }
        }
    }
</script>
<style></style>

把代码复制粘贴到脚手架中运行,可以看到直观的效果,有助于理解。

2. Module

什么叫单一状态树呢,其实就是上文中的state对象。在Vuex的基本使用中,我们使用state对象来存储Vuex的状态,state对象里面可以嵌套其他的对象,它是一个树形的结构,而且这个state对象是唯一的,所有的状态都要存储在这一个对象里。因此,我们称之为单一状态树。
这种单一状态树的弊端是显而易见的,对于中大型项目来说,要托管给Vuex的状态有很多,把这些海量的数据如果都塞到一个文件里面的一个对象里面,未免显得过于臃肿,不管是开发起来还是维护起来都会有很多不变。
对此,官方给出了解决方案:

2.1 vuex中模块化的基本使用

vuex的模块化没什么难理解的,就是把store给拆开,一个对象拆成多个对象,一个文件拆成多个文件,并且彼此可以拥有独立的命名空间。
道理很简单,所以直接看样例:

文件结构

├──src
   ├── components
   │   └── Test.vue
   └── store
       ├── index.js
       └── modules
           ├── male.js
           └── female.js

index.js

import {createStore} from 'vuex'
import female from './modules/female'   //导入模块
import male from './modules/male'       //导入模块
export default createStore({ 
    modules:{   //使用模块
        female,
        male
    }
})

male.js

export default {
    namespaced:true,    //namespaced:true代表该模块带有独立命名空间
    state:{             //否则,默认是处于全局命名空间,就和非模块化一样
        personList:[
            {name:'张飞', id:'004'},
            {name:'武则天', id:'005'},
            {name:'秀吉', id:'006'},
        ]
    },
    mutations:{
        addMutation(state, value){      //往personList中添加一个人
            state.personList.push(value)
        },
        removeMutaion(state, value){    //往personList中删除一个人
            state.personList = state.personList.filter((el) => el.id != value.id)
        }
    },
    actions:{
        addAction(context, value){
            setTimeout(() => {
                context.commit('addMutation', value) // ->'male/addMutation'
            }, 1000);
        },
        removeAction(context, value){
            context.commit('removeMutaion', value)
        }
    },
    getters:{
        personList(state){
            return state.personList
        }
    }
}

female.js

export default {
    namespaced:true,    //namespaced:true代表该模块带有独立命名空间
    state:{             //否则,默认是处于全局命名空间,就和非模块化一样
        personList:[
            {name:'李白', id:'001'},
            {name:'孙尚香', id:'002'},
            {name:'大乔', id:'003'},
        ]
    },
    mutations:{
        addMutation(state, value){      //往personList中添加一个人
            state.personList.push(value)
        },
        removeMutaion(state, value){    //往personList中删除一个人
            state.personList = state.personList.filter((el) => el.id != value.id)
        }
    },
    actions:{
        addAction(context, value){
            setTimeout(() => {
                context.commit('addMutation', value) // ->'female/addMutation'
            }, 1000);
        },
        removeAction(context, value){
            context.commit('removeMutaion', value)
        }
    },
    getters:{
        personList(state){
            return state.personList
        }
    }
}

Test.vue

<template>
    <h1>女人:</h1>
    <li v-for="femalePerson in femalePersons" :key="femalePerson.id">
        {{femalePerson.name}}
        <button @click="addToMale(femalePerson)">添加到男人</button>
    </li>
    <h1>男人:</h1>
    <li v-for="malePerson in malePersons" :key="malePerson.id">
        {{malePerson.name}}
        <button @click="addToFemale(malePerson)">添加到女人</button>
    </li>
    <!-- 有两个列表,分布是男人和女人,通过点击按钮可以把列表中的某些项添加到另一个列表中 -->
    <!-- 建议粘贴复制并运行代码,这样更直观 -->
</template>

<script>
    import { computed } from '@vue/runtime-core';
    import {useStore} from 'vuex'
    export default {
        setup(){
            let store = useStore()
            let malePersons = computed(() => store.getters['male/personList']) //通过getter获取state
            let femalePersons = computed(() => store.state.female.personList)   //直接获取state
            function addToMale(person){
                store.dispatch('male/addAction', person)
                store.dispatch('female/removeAction', person)
                //如果模块中namespaced === true,那么要在方法名前面添加模块的逻辑路径
                //index.js里使用的模块为路径的起点。
                //比如index里面有一个moduleA,moduleA有一个子模块moduleB,module有一个action是actionx
                //那么调用方式为 store.dispatch('moduleA/moduleB/actionx', value)
            }
            function addToFemale(person){
                store.dispatch('female/addAction', person)
                store.dispatch('male/removeAction', person)
            }
            return {
                malePersons,
                femalePersons,
                addToMale,
                addToFemale
            }
        }
    }
</script>
<style></style>
举报

相关推荐

0 条评论