vuex

1)概念

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

2)什么时候使用Vuex

  多个组件依赖于同一状态

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

3)vuex原理图

  

 

   Vue Components  ==》 Actions ==》 mutations ==》state ==》Vue Components

4)进行环境搭建

  1)我们创建一个store文件,然后在里面创建 index.js,输入以下内容

//引入Vuex
import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

//准备actions---用于相应组件中的的动作
const actions = {}
//准备mutations---用于操作数据(state)
const mutations = {}
//准备state---用于存储数据
const state = {}

//创建store
export default new Vuex.Store({
    actions:actions,
    mutations:mutations,
    state:state,
})
View Code

  这里有一个Vuex的引入问题,本来我们是在main.js进行vuex的引入,但是因为其内部会自动将代码排序,然后导致代码出现错误,所以我们把vuex的引入放到index.js中,然后main.js只需要进行store的引入即可

 

5)制作一个小案例

  对【求和案例纯vue代码】的改进

  本来,在纯vue代码中,我们是将所有方法都配置在count.vue这个类中,但是vuex的情况,则是将这些操作的内容放置在【store】里面的【index.js】

  大致如下

//引入Vuex
import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

//准备actions---用于相应组件中的的动作
const actions = {
    jia(context,value){
        //console.log(context,value)
        context.commit('JIA',value)
    },
    jian(context,value){
        context.commit('JIAN',value)
    },
    jiaOdd(context,value){
        if(context.state.sum%2)
            context.commit('JIAODD',value)
    },
    jiaWait(context,value){
        setTimeout(()=>{
            context.commit('JIAWAIT',value)
        },500)
    }
}
//准备mutations---用于操作数据(state)
const mutations = {
    JIA(state,value){
        console.log('mutations中的JIA被调用了',state,value)
        state.sum += value
    },
    JIAN(state,value){
        console.log('mutations中的JIAN被调用了',state,value)
        state.sum -= value
    },
    JIAODD(state,value){
        console.log('mutations中的JIAODD被调用了',state,value)
        state.sum += value
    },
    JIAWAIT(state,value){
        console.log('mutations中的JIAWAIT被调用了',state,value)
        state.sum += value
    }
    
}
//准备state---用于存储数据
const state = {
    sum:0
}

//创建store
export default new Vuex.Store({
    actions:actions,
    mutations:mutations,
    state:state,
})
View Code

  然后,在count中,则输入对这些内容的一个引用

<template>
    <div>
        <h1>当前求和为:{{$store.state.sum}}</h1>
        <select v-model.number="n">
            <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">当前求和为奇数再加</button>
        <button @click="incrementWait">等一等再加</button>
    </div>
</template>

<script>
    export default {
        name:'Count',
        data(){
            return{
                n:1,    //用户选择的数组
                //sum:0    将数据放置到vuex
            }
        },
        methods:{
            increment(){
                this.$store.dispatch('jia',this.n)
            },
            decrement(){
                this.$store.dispatch('jian',this.n)
            },
            incrementOdd(){
                this.$store.dispatch('jiaOdd',this.n)
            },
            incrementWait(){
                this.$store.dispatch('jiaWait',this.n)
            },
        },
        mounted(){
            console.log('Count',this)
        }
    }
</script>

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

 

6)对getters的一个使用

  当我们想要对某个组件中的某个值(比如n)进行加工处理时,我们的基本做法是:在那个组件当中写上计算属性【computed】,然后在计算属性当中配置大致如下:

computed:{
            newn:{
                get(){
                    return this.n*10;
                }
            }
        }
View Code

  但是,这种做法仅仅只能把这个值保存在当前组件当中,如果想要在其他组件中呈现加工后的值的话,那么我们可以选择vuex中的getters属性,进行如下的配置

//准备getters---用于将state中的数据进行加工
const getters = {
    bigSum(state){
        return state.sum*10
    }
}
View Code

  然后,调用语句大致如下:

<h2>当前n的10倍为:{{$store.getters.bigSum}}</h2>
View Code

 

7)mapState

  通过以上的内容的书写,可以发现,我们要调用vuex上面的属性时,会是这样的

  

 

   即:想调用某个属性的时候,会出现这种要层层进入的情况

   这种情况,vuex给了我们一个解决方法,即:mapState

  我们给出如下例子:

  我们在store下面的index.js配置一个【mingzi】属性

  然后要在count组件里面查看该属性,那么我们就得写 $store.state.mingzi 

  假如我们不想写这么长,可以引入mapState

  步骤为

    1)引入

      import {mapState} from 'vuex'

    2)使用

      

      ...mapState({name:'mingzi'}), //对象写法,可以将mingzi改为其他内容进行映射
      ...mapState(['mingzi']), //数组写法,只能按我们在state中的内容进行呈现

    数组的原理图如下:

        

 

     一个mingzi对应两个地方的定义

    3)调用

      

 

 

 

8)mapGetters

  大致情况如上,步骤如下

  1)引入

import {mapState,mapGetters} from 'vuex'
View Code

  2)使用

...mapGetters(['bigSum']),
View Code

  3)调用

<h2>当前n的10倍为:{{bigSum}}</h2>
View Code

 9)MapActions方法

  

 

 10)mapMutations方法

  

 

  11)多组件共享数据的实现

  1)假如我们没有用vuex的话,在各个组件内自个定义的数据,是很难数据共享的,而vuex将数据定义在某个特定地方【我的是在目录store的index.js之下】,所以我们可以用vuex来进行数据间的交互

  我们的两个组件如下

  count组件

<template>
    <div>
        <h1>当前求和为:{{$store.state.sum}}</h1>
        <h2>当前n的10倍为:{{bigSum}}</h2>
        <h3>{{name}}</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">+</button>
        <button @click="decrement">-</button>
        <button @click="incrementOdd">当前求和为奇数再加</button>
        <button @click="incrementWait">等一等再加</button>
        
        <h3>人员列表的总人数为:{{$store.state.personList.length}}</h3>
    </div>
</template>

<script>
    import {mapState,mapGetters} from 'vuex'
    export default {
        name:'Count',
        data(){
            return{
                n:1,    //用户选择的数组
                //sum:0    将数据放置到vuex
            }
        },
        methods:{
            increment(){
                this.$store.dispatch('jia',this.n)
            },
            decrement(){
                this.$store.dispatch('jian',this.n)
            },
            incrementOdd(){
                this.$store.dispatch('jiaOdd',this.n)
            },
            incrementWait(){
                this.$store.dispatch('jiaWait',this.n)
            },
        },
        computed:{
            /* newn:{
                get(){
                    return this.n*10;
                }
            } */
            /* mingzi(){
                return this.$store.state.mingzi
            }, */
            
            ...mapState({name:'mingzi'}),   //对象写法,可以将mingzi改为其他内容进行映射
            //...mapState(['mingzi']),        //数组写法,只能按我们在state中的内容进行呈现
            ...mapGetters(['bigSum']),
            bigSum(){
                return this.$store.getters.bigSum
            }
        },
        mounted(){
            const x = mapState({mingzi:'mingzi'})
            console.log(x)
        },
    }
</script>

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

  createPerson组件如下

<template>
    <div>
        <input type="text" placeholder="请输入名字" v-model="name">
        <button @click="add">添加</button>
        <ul>
            <li v-for="p in $store.state.personList" :key="p.id">{{p.name}}</li>
        </ul>
        <h3>{{$store.state.mingzi}}</h3>
    </div>
</template>

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

<style>
</style>
View Code

  App组件如下:

<template>
    <div>
        <Count></Count>
        
        <h3>fgdfsgdfgf</h3>
        
        <createPerson></createPerson>
        
    </div>
</template>

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

    export default {
        name:'App',
        components:{Count,createPerson},
        mounted(){
            console.log('App',this)
        }
    }
</script>

<style>
    
</style>
View Code

  然后,想要进行组件间的通信,我们可以这样调用

  

 

posted @ 2021-10-18 19:43  古比  阅读(69)  评论(0编辑  收藏  举报