天天看点

vuex技术多组件共享数据-vuex模块化+namespace

天空是连着的,如果我们也能各自发光的话,无论距离有多远,都能看到彼此努力的身影。

vuex技术多组件共享数据-vuex模块化+namespace

  • ​​index.js​​
  • ​​count.js​​
  • ​​person.js​​
  • ​​Person.vue​​
  • ​​Count.vue​​
  • ​​App.vue​​
  • ​​main.js​​

我们知道每一个组件都有自己的 data,那么多个组件如何共享数据?这就引出了 state 的概念,可以把多个组件共有的属性统一由state进行管理。但是组件并不能直接访问或操作state里的数据源,而是通过 mutations 来对数据源进行操作。而改变数据的行为触发由 Actions 来完成,Vue 为 actions的触发提供了一个 commit 的概念,由action 触发通过 mutations 对数据进行操作,从而改变 state 数据源。

vuex技术多组件共享数据-vuex模块化+namespace

通过:​

​import { nanoid } from 'nanoid'​

​来生成一个ID属性。

核心代码块:

methods:{
            add(){
                const personObj = {id:nanoid(),name:this.name};
                this.$store.commit('ADD_PERSON',personObj)
                console.log(personObj);
                this.name = ''
            }
        }      

当我们开发的项目比较大时,store中的数据就可能比较多,这时我们store中的数据就可能变得臃肿,为了解决这一问题,我们就需要将store模块化(module),

即每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块

vuex模块化核心代码示例

开启命名空间,简化代码示例:

const countOptions = {
    namespaced: true,
    state: {
        sum: 0,
        name: '勇敢牛牛,不怕困难',
    },
    actions: {
        jiaodd(context,) {
            context.commit("JIAODD", value)
        },
        jiaWait(context,) {
            context.commit('JIAWAIT', value)
        }
    },
    mutations: {
        JIA(state,) {
            state.sum += value
        },
        JIANJIAN(state,) {
            state.sum -= value

        },
        JIAODD(state,) {
            if (state.sum % 2 != 0) {
                state.sum += value
            }
        },
        JIAWAIT(state,) {
            setTimeout(() => {
                state.sum += value
            }, 500)
        },
    },
    getters: {
        bigSum(tate) {
            return state.sum * 10
        }
    }
}      

才可以使用简写,直接获取属性值

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

在person组件中如果直接对commit操作。就在属性值前面加这个模块的名称

this.$store.commit('b/ADD_PERSON',personObj)      

例如:

add(){
                const personObj = {id:nanoid(),name:this.name};
                this.$store.commit('b/ADD_PERSON',personObj)
                console.log(personObj);
                this.name = ''
            }      

在【person中联系muttion修改数据】

this.$store.commit('b/ADD_PERSON',personObj);      

最终的数据结构

vuex技术多组件共享数据-vuex模块化+namespace

index.js

//引入Vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
//使用插件
Vue.use(Vuex)

//计算相关配置
import countOptions from './count'

// 人员相关配置
import personOptions from './person'

// 创建store
export default new Vuex.Store({
    modules: {
        a: countOptions,
        b: personOptions
    }
})

// export default store      

count.js

const countOptions = {
    namespaced: true,
    state: {
        sum: 0,
        name: '勇敢牛牛,不怕困难',
    },
    actions: {
        jiaodd(context,) {
            context.commit("JIAODD", value)
        },
        jiaWait(context,) {
            context.commit('JIAWAIT', value)
        }
    },
    mutations: {
        JIA(state,) {
            state.sum += value
        },
        JIANJIAN(state,) {
            state.sum -= value

        },
        JIAODD(state,) {
            if (state.sum % 2 != 0) {
                state.sum += value
            }
        },
        JIAWAIT(state,) {
            setTimeout(() => {
                state.sum += value
            }, 500)
        },
    },
    getters: {
        bigSum(state) {
            return state.sum * 10
        }
    }
}
export default      

person.js

import axios from "axios";
import { nanoid } from 'nanoid'
const personOptions = {
    namespaced: true,
    state: {
        personList: [
            { id: '001', name: '张安' }
        ]
    },
    actions: {
        addPersonWang(context,) {
            if (value.name.indexOf('王') === 0) {
                context.commit('ADD_PERSON', value)
            } else {
                alert('添加的人必须是姓王')
            }
        },
        addPersonServer(context) {
            axios.get('https://api.uixsj.cn/hitokoto/get?tyoe=social').then(
                response => {
                    context.commit('ADD_PERSON', { id: nanoid(), name: response.data })
                },
                error => {
                    alert(error.message)
                }

            )
        }
    },
    mutations: {
        ADD_PERSON(state,) {
            console.log('muttion中的ADD_preson被调用了');
            state.personList.unshift(value)
        }
    },
    getters: {
        firstPersonName(state) {
            return state.personList[0].name
        }
    }
}
export default      

Person.vue

<template>
    <div>
        <h1>person</h1>
        <h2 class="one">count组件的求和为{{sum}}</h2>
        <h2>列表中第一个信息是:{{ firstPersonName }}</h2>
        <input type="text" name="" id="" placeholder="请输入名字" v-model="name">
        <button @click="add()">添加</button>
        <button @click="addWang()">添加一个姓王的人</button>
        <button @click="addServer()">添加一随机语句</button>
        <ul>
            <li v-for="p in personList" :key='p.id'>
                {{p.name}}
            </li>
        </ul>
    </div>
</template>

<script>import {mapState } from 'vuex'
    import { nanoid } from 'nanoid'
    export default {
        name:'Person',
        data(){
            return {
                name:'',
            }
        },
        computed:{
            // personList(){
            //     return this.$store.state.personList
            // }
            ...mapState('a', ['sum']),
            ...mapState('b', ['personList']),
            firstPersonName(){
                return this.$store.getters['b/firstPersonName']
            }
        },
        methods:{
            add(){
                const personObj = {id:nanoid(),name:this.name};
                this.$store.commit('b/ADD_PERSON',personObj);
                console.log(personObj);
                this.name = ''
            },
            addWang(){
                const personObj = { id: nanoid(), name: this.name };
                this.$store.dispatch('b/addPersonWang', personObj)
                this.name = ''
            },
            addServer(){
                this.$store.dispatch('b/addPersonServer')
            }
        },
        mounted() {
            console.log(this.$store);
        }

    }</script> 
<style>.one{
        color: rgb(68, 156, 233);
    }</style>      

Count.vue

<template>
    <div>
        <h1>当前数值为:{{sum}}</h1>
        <h2>放大10倍后的数值是:{{bigSum}}</h2>
        <h3>{{name}}</h3>
        <h3 class="tow">person组件总人数是:{{ personList.length }}</h3>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment(n)">+</button>
        <button @click="decrement(n)">-</button>
        <button @click="incrementOdd(n)">当前数和为奇数再加</button>
        <button @click="incrementWait(n)">延时时间后再加</button>
    </div>
</template>

<script>import {mapGetters, mapState , mapMutations,mapActions} from 'vuex'

    export default {
        name:'Count',
        data() {
            return{
                n:1
            }
        },
        methods:{
            ...mapMutations('a', { increment: 'JIA', decrement: 'JIANJIAN' }),
            ...mapActions('a', {incrementOdd : 'jiaodd',incrementWait:'jiaWait'}),
            
        },
        computed:{
           
            // ...mapGetters(['bigSum']),
            // ...mapState(['a','b'])
            ...mapState('a',['sum','name']),
            ...mapState('b', ['personList']),
            ...mapGetters('a',['bigSum']),
            

        },
        mounted(){                                                                          
            const x = mapState({name:'name'});
            
        }
       
    }</script>  

<style scoped>button{
        margin-left: 10px;
    }
    .tow{
        color: rgb(68, 156, 233);
    }</style>      

App.vue

<template>
   <div>
       <Count/>
       <Person/>
   </div>
</template>
<script>import Count from './components/Count.vue';
    import Person from './components/Person.vue'
   export default {
    name: "App",
    data() {
        return {
            data:1
        };
    },
    components: {Count, Person},
    mounted(){
        // console.log('app',this);
    }
}</script>
<style scoped>
    

</style>      

main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'

// 也就是创建了一个store
// 引入store
import store from './store/index'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
  el: '#app',
  render: h => h(App),
  store: store,
  beforeCreate() {
    Vue.prototype.$bus = this
  }
})