Vuex 状态管理模式/插件

为什么要使用状态管理?

在开发整站时会有很多数据,也是由许多组件拼成,会共享一些状态,如用户的登录状态,或购物车信息在头部用到了,或在页面等其他位置也有使用到。我在其中一个位置进行增删,相应的在其他位置的购物车信息也要更新。直接的做法是通过事件,如果有其他触发了更新无论是通过计算属性还是watch。需要通过事件和eventBus来传到另外一个组件,这个缺点是当我们的状态非常复杂,组件非常多时,我们需要挨个依次去通知组件状态更新,这样会变得很复杂。所以就产生了状态管理模型。

状态管理的模型

我们有一个统一的数据中心store,用来维护状态数据,每个组件进行更新时就通知,每个组件更新时通知数据中心,数据中心将这样的共享状态再去触发调用它每一个组件的更新,这是一个数据管理模式。

状态管理机制

在Vuex的设计概念中,Vue组件通过Actions的这个动作,Actions去操作mutations,mutations去控制数据中心的状态State,状态更改以后再反映到页面的组件的一个渲染。

在下图的展示为虚线框的为Vuex的操作过程。

Actions可以进行异步操作,比如调用后台数据等异步操作只能在Acitions中进行。

Mutations是同步地更改State数据的一种方法,与Devtools等进行交互。

在这个模型内要保证数据的单向流动,Vue Components通过dispatch去触发Actions,Acitions通过commit来触发mutations,mutations直接操作我们的数据State。

state是动态更新,action是动态操作。能改数据的只有mutations。

如果项目复杂的话,可是使用Vuex,会使项目非常高效。如果是简单的项目,没必要使用这个复杂的事件管理机制。

安装vuex

三种选一种即可:

npm install vuex --save

cnpm install vuex --save 

yarn add vuex

在安装完成后进行使用。

需要创建store文件夹,新建store.js文件

在store.js中导入Vuex,必须使用Vue.use(Vuex); 进行挂载,并实例化一个store。

import Vuex from 'vuex'

Vue.use(Vuex);

实例化一个Store:

let store = new Vuex.Store({
    state: { 
        totalPrice: 0
    },
    mutations: {
        increment(state, price){
            state.totalPrice += price
        },
        decrement(state, price){
            state.totalPrice -= price
        }
    }
})

在实例化完成后一定要在全局使用这个store,这里是我的存放store.js的路径,需要你修改为自己的路径:

import store from './store/store.js';
new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

然后在每个子组件内就可以通过  this.$store去触发里面的方法,或调用里面的状态。

Mutations

在子组件内的调用:

methods:{
    addOne(){
        this.$store.commit('increment',this.price)
    },
    minusOne(){
        this.$store.commit('decrement',this.price)
    }
}

可以看到在子组件内调用时,通过事件内的  this.$store.commit 提交  mutations内的 increment 事件,来修改价格;或者通过子组件内的computed属性获取并计算价格,这两个方法均可修改totalPrice状态值,方法二如下方示例:

computed: {
    totalPrice(){
        return this.$store.state.totalPrice
    }
}

上面的方法均可单独修改完成。

优点:不需要调用各种状态及各种事件,只需要调用数据中心中对应的mutations,就可以实现模块间数据共享。

Actions

当在变量store内添加actions:

actions:{
    increase(conext, price){
        context.commit('increment', price)
    }
}

相应的,在子组件内调用方法修改时需要改为:

methods:{
    addOne(){
        this.$store.dispatch('increment',this.price)
    },
    minusOne(){
        this.$store.dispatch('decrement',this.price)
    }
}

效果与上方未添加actions时的效果一致:

这个方法是子组件 dispatch 了一个actions,actions对事件 increment 进行提交,等于是actions作为一个中介进行传递。

 

mutations和actions的区别:

  • actions是先进行异步操作,然后触发mutations
  • mutations是同步操作数据的一个方式
  • 修改mutations是commit(),修改actions是dispatch()

mutations是不可以发送http请求回调的。

Getters

在store实例内添加getters属性,

getters:{
    getTotal(state){
        return state.totalPrice
    }
}

后面在需要获取totalPrice的地方,可以改为  this.$store.getters.getTotal  最后拿到totalPrice。

Module

可以把状态集分成不同的模型,每一个模型都维护自己的一套数据:

const moduleA = {
    state: {...},
    mutations: {...},
    actions: {...},
    getters: {...}
}
const moduleB = {
    state: {...},
    mutations: {...},
    actions: {...},
    getters: {...}
}
const store = new Vuex.store({
    modules:{
        a: moduleA,
        b: moduleB
    }
})
store.state.a   // -> modulesA's state
store.state.b   // -> modulesB's state

使用Vuex需要注意的问题:

  1. 将所有应用层级的状态集中到同一个store内。
  2. 更改层级的状态只能通过提交(commit) mutation进行更改,mutations是同步的。
  3. 如果需要提交异步的东西,我们需要把逻辑放到actions内部。

State内存储的是全局的一些状态,state的改变会同步展现到组件内。

官方在使用store时,统一对外的接口是 index.js:

在store内存在state,mutations,actions,getters四个属性,可进行使用。

这个是上述部分内完整的store实例如下:

let store = new Vuex.Store({
    state: { 
        totalPrice: 0
    },
    getters:{
        getTotal(state){
            return state.totalPrice
        }
    },
    mutations: {
        increment(state, price){
            state.totalPrice += price
        },
        decrement(state, price){
            state.totalPrice -= price
        }
    },
    actions:{
        increase(conext, price){
            context.commit('increment', price)
    }
}
})

 

在521这一天 进行二次维护:

这个是重新添加的store.js文件及使用store的组件的内容,会更完整一些:

store.js:

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

Vue.use(Vuex);

const store = new Vuex.Store({
    state: { 
        count: 100000,
        isLogin: false    //登录状态
    },
    mutations: {
        increase(state){
            state.count += 1;
        },
        Login(state){
            state.isLogin = true;
        },
        logout(state){
            state.isLogin = false;
        }
    },
    getters:{   //对state中的数据进行加工处理
        money: state => {
            return state.count + '元'
        }
    },
    actions: {   //异步操作时  可以写接后台接口的这个位置
        increaseAsync({commit}){
            setTimeout(() => {
                commit('increase');
            },1000);
        },
        submitLogin({commit}){
            return new Promise( resolve => {
                setTimeout(()=> {
                    commit('login');
                    resolve(true);
                },2000);
            })
            
        }
    }
})


export default store;

可以看到actions是提交的mutations内的内容。

使用store的组件:

<template>
    <div>
        <h3>Dashboard</h3>
        <!-- 父组件必须有一个路由的出口,负责显示子路由 -->
        <router-view></router-view>
        <button @click="inc">increease</button>
        <button @click="incAsync">incAsync</button>
        <p>{{count}}</p>
        <p>您的余额为:{{money}}</p>
    </div>
</template>

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

    export default {
        methods: {
            ...mapMutations(['increase']),
            ...mapActions(['increaseAsync']),
            inc() {
                this.$store.commit('increase');
                // this.increase()
            },
            incAsync() {
                this.$store.dispatch('increaseAsync');
                // this.increaseAsync()
            }
        },
        computed: {
            // mapState是个函数,最终会返回一个对象
            // 下面的等价于{count: this.$store.state.count}
            ...mapState(['count']),   //是count
            ...mapGetters(['money'])
        },
    }
</script>

<style lang="scss" scoped>

</style>

使用时:

this.$store.commit('increase'); 通过提交muations修改store内state中保存的值。

this.$store.dispatch('increaseAsync');通过提交actions修改store内state中保存的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值