vue中的一个重要插件——vuex

目录

一、vuex简介

二、vuex工作原理

三、小案例

四、四个map方法的使用

1、mapState

2、mapGetters

3、mapMutations

4、mapActions

五、vuex实现数据共享案例

1、项目目录

2、源码

六、vuex实现模块化+命名空间

1、步骤:

2、开启命名空间后,读取state数据

①、自己读取

②、借助mapState读取

 3、开启命名空间后,读取getters数据

①、自己读取

②、借助mapState读取

  4、开启命名空间后,组件中调用dispatch

①、自己调用dispatch

②、借助mapActions

 5、开启命名空间后,组件中调用commit

①、自己直接调用commit

②、借助mapMutations

5、案例源码



一、vuex简介:

概念:专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件共享状态进行集中式的管理读/写),也是一种组件间的通讯方式,且适用于任意组件间通讯

何时使用:

①、多个组件依赖同一状态

②、来自不同组件的行为需要变更同一状态

二、vuex工作原理

三、小案例

main.js代码:

// 项目的入口文件

// 引入vue
import Vue from 'vue'
// 引入App,他是所有组件的父组件
import App from './App'
// 引入vuex
import Vuex from 'vuex'
// 引入store
import store from './store'

// 关闭vue的生产提示
Vue.config.productionTip = false
// 使用vuex
Vue.use(Vuex)

// 创建vue实例对象
new Vue({
  el:'#app',
  render: h => h(App),
  store,
})

App.vue代码:

<template>
    <div>
       <Count></Count>
    </div>
</template>

<script>
    import Count from './components/Count.vue'

    export default {
    name: "App",
    components:{Count},
    
}
</script>

Count.vue代码:

<template>
  <div>
    <h1>当前求和为:{
   
   {$store.state.sum}}</h1>
    <select v-model.number="n">
    <!-- 注意:这里要加冒号才能当成表达式,1、2、3才会是数字类型 -->
        <option :value="1">1</option>
        <option :value="2">2</option>
        <option :value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再+1</button>
    <button @click="incrementWait">等一等再+1</button>
  </div>
</template>

<script>
export default {
    name:'Count',
    data(){
        return{
            n:1,
            
        }
    },
    methods:{
        increment(){
            // 由于没有业务逻辑,所以可以让其直接调用mutations中的commit,而不需要再通过actions
            this.$store.commit("JIA",this.n)
        },
        decrement(){
            // 由于没有业务逻辑,所以可以让其直接调用mutations中的commit,而不需要再通过actions
            this.$store.commit("JIAN",this.n)
        },
        incrementOdd(){
            this.$store.dispatch("jiaOdd",this.n)
        },
        incrementWait(){
            this.$store.dispatch("jiaWait",this.n)
        }
    }
}
</script>

<style>
    button{
        margin-left: 5px;
    }
</style>

store/index.js代码:

// 该文件用于创建vuex中最核心的store

// 引入Vue
import Vue from 'vue'

// 引入Vuex
import Vuex from 'vuex'

// 应用Vuex插件
Vue.use(Vuex)

// 准备actions————用于响应组件中的动作
const actions = {
    // 接收两个参数:第一个是mini版的store,第二个是传过来的value值
    
    // 由于没有业务逻辑,所以可以让其直接调用mutations中的commit,而不需要再通过actions
    // jia(context,value){
    //     // 调用mutations中的JIA函数
    //     console.log('actions中的jia被调用了')
    //     context.commit("JIA",value)
    // },
    // jian(context,value){
    //     // 调用mutations中的JIA函数
    //     console.log('actions中的jian被调用了')
    //     context.commit("JIAN",value)
    // },
    jiaOdd(context,value){
        console.log('actions中的jiaOdd被调用了')
        if(context.state.sum % 2){
            // 调用mutations中的JIA函数
            context.commit("JIA",value)
        }
    },
    jiaWait(context,value){
        console.log('actions中的jia被调用了')
        setTimeout(()=>{
        // 调用mutations中的JIA函数
            context.commit("JIA",value)
        },500)
    }
}
// 准备mutations————用于操作数据(state)
const mutations = {
    JIA(state,value){   
        console.log('mutations中的JIA被调用了')
        state.sum+=value
    },
    JIAN(state,value){   
        console.log('mutations中的JIAN被调用了')
        state.sum-=value
    }
}
// 准备state————用于存储数据
const state = {
    sum:0
}



// 创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

四、四个map方法的使用

1、mapState

借助mapState生成计算属性,从state读取数据对象写法

computed:{
        //  借助mapState生成计算属性:sum、school、subject(对象写法)
        ...mapState({sum:'sum',school:'school',subject:'subject'})
    },

 借助mapState生成计算属性,从state读取数据数组写法

computed:{
        // 借助mapState生成计算属性sum、school、subject(数组写法)
        ...mapState(['sum','school','subject'])
    },

2、mapGetters

借助mapGetters生成计算属性,从getters读取数据对象写法

computed:{
        // 借助mapState生成计算属性sum、school、subject(数组写法)
       ...mapGetters({bigSum:'bigSum'}),
    },

借助mapGetters生成计算属性,从getters读取数据数组写法

computed:{
        // 借助mapState生成计算属性sum、school、subject(数组写法)
       ...mapGetters(['bigSum'])
    },

3、mapMutations

借助mapMutations生成对应的方法,方法中会调用commit去联系mutations;

(1)、对象方法

注意:

这里调用increment和decrement方法会传入一个默认的参数events,所以需要在调用它的html结构中手动传入参数n

<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
methods:{
        // 借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象方法)
        // 注意:这里调用increment和decrement方法会传入一个默认的参数events,所以需要在调用它的html结构中手动传入参数n
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),

    },

(2)、数组方法

注意:

这里需要将html结构中调用的位置都改为JIAJIAN

<button @click="JIA(n)">+</button>
<button @click="JIAN(n)">-</button>
methods:{
        
        // 借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组方法)
        // 注意:这里使用的是JIA和JIAN,需要在html结构中改为JIA和JIAN
         ...mapMutations(['JIA','JIAN']),

    },

4、mapActions

 帮我们生成与Actions对话的方法,即:包含$store.dispatch(xxx)的函数;

借助mapActions生成对应的方法,方法中会调用commit去联系mutations;

(1)、对象方法

注意:

这里调用iincrementOdd和incrementWait方法会传入一个默认的参数events,所以需要在调用它的html结构中手动传入参数n

<!-- 手动传入参数n -->
    <button @click="incrementOdd(n)">当前求和为奇数再+1</button>
    <button @click="incrementWait(n)">等一等再+1</button>
methods:{
        // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象方法)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),

    },

(2)、数组方法

注意:

这里需要将html结构中调用的位置都改为jiaOddjiaWait

<!-- 数组方法 -->
    <button @click="jiaOdd(n)">当前求和为奇数再+1</button>
    <button @click="jiaWait(n)">等一等再+1</button>
methods:{
        
        // 借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组方法)
        ...mapActions(['jiaOdd','jiaWait'])

    },

五、vuex实现数据共享案例

1、项目目录

2、源码:

App.vue

<template>
    <div>
       <Count></Count>
       <Person></Person>
    </div>
</template>

<script>
    import Count from './components/Count.vue'
     import Person from './components/Person.vue'

    export default {
    name: "App",
    components:{Count,Person},
    
}
</script>

store/index.js

// 该文件用于创建vuex中最核心的store

// 引入Vue
import Vue from 'vue'

// 引入Vuex
import Vuex from 'vuex'

// 应用Vuex插件
Vue.use(Vuex)

// 准备actions————用于响应组件中的动作
const actions = {
    jiaOdd(context,value){
        console.log('actions中的jiaOdd被调用了')
        if(context.state.sum % 2){
            // 调用mutations中的JIA函数
            context.commit("JIA",value)
        }
    },
    jiaWait(context,value){
        console.log('actions中的jia被调用了')
        setTimeout(()=>{
        // 调用mutations中的JIA函数
            context.commit("JIA",value)
        },500)
    }
}
// 准备mutations————用于操作数据(state)
const mutations = {
    JIA(state,value){   
        console.log('mutations中的JIA被调用了')
        state.sum+=value
    },
    JIAN(state,value){   
        console.log('mutations中的JIAN被调用了')
        state.sum-=value
    },
    ADD_PERSON(state,value){
        console.log('mutations中的ADD_PERSON被调用了')
        state.personList.unshift(value)
    }
}
// 准备state————用于存储数据
const state = {
    sum:0,
    school:'尚硅谷',
    subject:'前端',
    personList:[
        {id:'001',name:'张三'}
    ]
}
// 准备getters————用于存储加工后的数据
const getters = {
    bigSum(state){
        return state.sum*10
    }
}



// 创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

Count.vue

<template>
  <div>
    <h1>当前求和为:{
   
   {sum}}</h1>
    <h1>当前求和扩大10倍为:{
   
   {bigSum}}</h1>
    <h3>我在{
   
   {school}},学习{
   
   {subject}}</h3>
    <!-- 实现数据共享 -->
    <h3 style="color:red;">Person组件的总人数为:{
   
   {personList.length}}</h3>
    <select v-model.number="n">
    <!-- 注意:这里要加冒号才能当成表达式,1、2、3才会是数字类型 -->
        <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)">当前求和为奇数再+1</button>
    <button @click="incrementWait(n)">等一等再+1</button>
  </div>
</template>

<script>
import {mapState,mapGetters, mapMutations, mapActions} from 'vuex'
export default {
    name:'Count',
    data(){
        return{
            n:1,
            
        }
    },
    computed:{
        ...mapState(['sum','school','subject','personList']),
        ...mapGetters(['bigSum'])
    },
    methods:{
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),
    },
    mounted(){
        const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
    }
}
</script>

<style>
    button{
        margin-left: 5px;
    }
</style>

Person.vue

<template>
  <div>
    <h1>人员列表</h1>
    <h3 style="color:red;">Count组件求和为:{
   
   {sum}}</h3>
    <input type="text" placeholder="请输入名字" v-model="name">
    <button @click="add">添加</button>
    <ul>
        <li v-for="p in personList" :key="p.id">{
   
   {p.name}}</li>
    </ul>
  </div>
</template>

<script>
import {nanoid} from 'nanoid'
export default {
    name:'Person',
    data(){
        return{
            name:''
        }
    },
    computed:{
        personList(){
            return this.$store.state.personList
        },
        sum(){
            return this.$store.state.sum
        }
    },
    methods:{
        add(){
            const personObj = {id:nanoid(),name:this.name}
            this.$store.commit('ADD_PERSON',personObj)
            this.name = ''
        }
    }
}
</script>

六、vuex实现模块化+命名空间

目的:让代码更好维护,让多种数据分类更加明确

1、步骤:

①、在store文件夹中,将不同内容分模块化进行分类一种内容存储在一个js文件中,通过index.js文件进行import和模块化定义

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

// 创建并暴露store
export default new Vuex.Store({
    modules:{
        countAbout:countOptions,
        personAbout:personOptions
    }
})

②、将不同内容放在不同js文件中,并开启命名空间

person.jscount.js文件结构如下:

// 个人相关的配置
export default  {
    namespaced:true,
    actions:{
        // ...
    },
    mutations:{
        // ...
    },
    state:{
        // ...
    },
    getters:{
        // ...
    }

2、开启命名空间后,读取state数据

①、自己读取

this.$store.state.personAbout.list

②、借助mapState读取

...mapState('countAbout',['sum','school','subject'])

 3、开启命名空间后,读取getters数据

①、自己读取

this.$store.getters['personAbout/firstPersonName']

②、借助mapState读取

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

  4、开启命名空间后,组件中调用dispatch

①、自己调用dispatch

this.$store.dispatch('personAbout/addPersonWang',person)

②、借助mapActions

...mapActions('countAbout',(incrementOdd:'jiaOdd',incrementWait:'jiaWait'))

 5、开启命名空间后,组件中调用commit

①、自己直接调用commit

this.$store.commit('personAbout/ADD_PERSON',person)

②、借助mapMutations

...mapActions('countAbout',(increment:'JIA',decrement:'JIAN'))

5、案例源码

目录结构:

App.vue

<template>
    <div>
       <Count></Count>
       <Person></Person>
    </div>
</template>

<script>
    import Count from './components/Count.vue'
     import Person from './components/Person.vue'

    export default {
    name: "App",
    components:{Count,Person},
    
}
</script>

main.js

// 项目的入口文件

// 引入vue
import Vue from 'vue'
// 引入App,他是所有组件的父组件
import App from './App'
// 引入vuex
import Vuex from 'vuex'
// 引入store
import store from './store'

// 关闭vue的生产提示
Vue.config.productionTip = false
// 使用vuex
Vue.use(Vuex)

// 创建vue实例对象
new Vue({
  el:'#app',
  render: h => h(App),
  store,
})

components/Count.vue

<template>
  <div>
    <h1>当前求和为:{
   
   {sum}}</h1>
    <h1>当前求和扩大10倍为:{
   
   {bigSum}}</h1>
    <h3>我在{
   
   {school}},学习{
   
   {subject}}</h3>
    <!-- 实现数据共享 -->
    <h3 style="color:red;">Person组件的总人数为:{
   
   {personList.length}}</h3>
    <select v-model.number="n">
    <!-- 注意:这里要加冒号才能当成表达式,1、2、3才会是数字类型 -->
        <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)">当前求和为奇数再+1</button>
    <button @click="incrementWait(n)">等一等再+1</button>
  </div>
</template>

<script>
import {mapState,mapGetters, mapMutations, mapActions} from 'vuex'
export default {
    name:'Count',
    data(){
        return{
            n:1,
            
        }
    },
    computed:{
        ...mapState('countAbout',['sum','school','subject']),
        ...mapState('personAbout',['personList']),
        ...mapGetters('countAbout',['bigSum'])
    },
    methods:{
        ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
        ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),
    },
    mounted(){
        const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
    }
}
</script>

<style>
    button{
        margin-left: 5px;
    }
</style>

components/Person.vue

<template>
  <div>
    <h1>人员列表</h1>
    <h3 style="color:red;">Count组件求和为:{
   
   {sum}}</h3>
    <h3>列表中第一个人的名字是:{
   
   {firstPersonName}}</h3>
    <input type="text" placeholder="请输入名字" v-model="name">
    <button @click="add">添加</button>
    <button @click="addWang">添加一个姓王的人</button>
    <button @click="addPersonServer">添加一个人,名字随机</button>
    <ul>
        <li v-for="p in personList" :key="p.id">{
   
   {p.name}}</li>
    </ul>
  </div>
</template>

<script>
import {nanoid} from 'nanoid'
export default {
    name:'Person',
    data(){
        return{
            name:''
        }
    },
    computed:{
        personList(){
            // 添加了personAbout
            return this.$store.state.personAbout.personList
        },
        sum(){
            // 添加了countAbout
            return this.$store.state.countAbout.sum
        },
        firstPersonName(){
            return this.$store.getters['personAbout/firstPersonName']
        }
    },
    methods:{
        add(){
            const personObj = {id:nanoid(),name:this.name}
            this.$store.commit('personAbout/ADD_PERSON',personObj)
            this.name = ''
        },
        addWang(){
            const personObj = {id:nanoid(),name:this.name}
            this.$store.dispatch('personAbout/addPersonWang',personObj)
            this.name = ''
        },
        addPersonServer(){
            this.$store.dispatch('personAbout/addPersonServer')
        }
    }
}
</script>

<style>

</style>

store/count.js

// 求和相关的配置
export default {
    namespaced:true,
    actions:{
        jiaOdd(context,value){
            console.log('actions中的jiaOdd被调用了')
            if(context.state.sum % 2){
                // 调用mutations中的JIA函数
                context.commit("JIA",value)
            }
        },
        jiaWait(context,value){
            console.log('actions中的jia被调用了')
            setTimeout(()=>{
            // 调用mutations中的JIA函数
                context.commit("JIA",value)
            },500)
        }
    },
    mutations:{
        JIA(state,value){       
            console.log('mutations中的JIA被调用了')
            state.sum+=value
        },
        JIAN(state,value){   
            console.log('mutations中的JIAN被调用了')
            state.sum-=value
        },
    },
    state:{
        sum:0,
        school:'尚硅谷',
        subject:'前端',
    },
    getters:{
        bigSum(state){
            return state.sum*10
        }
    }
}

store/index.js

// 该文件用于创建vuex中最核心的store

// 引入Vue
import Vue from 'vue'

// 引入Vuex
import Vuex from 'vuex'

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

// 应用Vuex插件
Vue.use(Vuex)





// 创建并暴露store
export default new Vuex.Store({
    modules:{
        countAbout:countOptions,
        personAbout:personOptions
    }
})

store/person.js

import axios from 'axios'
import { nanoid } from 'nanoid'

// 个人相关的配置
export default  {
    namespaced:true,
    actions:{
        addPersonWang(context,value){
            if(value.name.indexOf('王') === 0){
                context.commit('ADD_PERSON',value)
            }else{
                alert('添加的人必须姓王!')
            }
        },
        addPersonServer(context){
            // 地址是一个随机自动显示文字的api
            axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
                response => {
                    context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
                },
                error => {
                    alert(error.message)
                }
            )
        }
    },
    mutations:{
        ADD_PERSON(state,value){
            console.log('mutations中的ADD_PERSON被调用了')
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'张三'}
        ]
    },
    getters:{
        firstPersonName(state){
            return state.personList[0].name
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46376652/article/details/125858614