Vuex教程

一、概览
1、Vuex是什么

  • 专为Vue.js应用程序开发的状态管理模式(状态即数据,即数据管理)
  • 采用集中式存储管理应用的所有组件的状态
  • 以相应的规则保证状态以一种可预测的方式发生变化
    2、状态
  • 组件内部状态:仅在一个组件内使用的状态( 即data字段里的数据,不能共享,只在本组件使用 )
  • 应用级别状态:多个组件共用的状态(将这个状态放入vuex中进行管理)
    3、什么情况下使用Vuex
  • 多个视图(组件)依赖同一状态
  • 来自不同视图(组件)的行为需要变更同一状态

二、Vuex核心概念
1、store:类似容器,包含应用的大部分状态

  • 一个页面只能有一个容器
  • 状态存储是响应式的
  • 不能直接改变store中的状态,唯一途径显示地提交mutations
    2、State:包含所有应用级别状态的对象
    3、Getters:在组件内部获取store中状态的函数
    4、Mutations:唯一修改状态的事件回调函数,默认是同步的,如果要异步就使用Actions
    5、Actions:包含异步操作、提交mutations改变状态
    6、Modules:将store分割成不同的模块

三、案例

**index.js**

let store = new Vuex.Store({
    state:{  //对象,应用所需要的状态数据都放在这里面
        count:100
    },
    mutations:{  //对象,显示的同步提交mutations
        addIncrement(state,payload){  //这里是自定义addIncrement事件
            state.count+ = payload.n
        }
    },
    actions:{
        addAction( context ){  //这里新加自定义事件addAction
            setTimeout( ()=>{  /模拟异步操作
            //改变状态,提交mutations,仍然是上面mutations里面定义的事件addIncrement
                context.commit('addIncrement',{n:15})
                context.dispatch('textAction',{test:'测试'})  //这里执行该异步操作
            },1000 )
        },
        textAction(context,obj){  //定义第二个异步操作
            console.log(obj)  //{test:'测试'}
        },
        getListAction( context ){  //这里定义了异步接口action,在子组件created里面调用
            axios.get('url')
            .then( (data)=>{
                console.log(data);  //得到了接口数据
            } )
        }
    },
    getters:{  //对store里面的数值进行逻辑操作
        filterState(state){
            return state.count>=120?120:state.count
        }
    }
})
export default store

**increment组件:**

<template>
    <p>{{num}}</p>
    <span>{{filterNewNum}}</span>
    <input type="button" value="+" @click="addHandle" />
</template>
<script>
    computed:{
        num(){
            rerurn this.$store.state.count
        },
        filterNewNum(){  //这里面接收过滤后的,仓库里面的数据
            return this.$store.getters.filterState //注意是return,不要漏了
        }
    },
    methods:{
        addHandle(){  //改变状态,提交mutations
            this.$store.commit('addIncrement',{  //这里是commit addIncrement
                n:5                //参数
            });
        }
        //这里是异步触发一个action,注意和上面同步的不同之处
        this.$store.dispatch.commit('addAction') //这里是dispatch addAction
    },
    created(){
        this.$store.dispatch('getListAction');  //dispatch
    }
    也可以这样写:
    methods:{
        addHandle(){
            this.$store.commit({
                type:'addIncrement',  //改变的状态类型
                n:5                             //参数
            })
        }
    }
</script>
//上面是同步操作数据,使用mutations,如果要异步操作数据,就用到Actions,注意,不管是同步还是异步操作,改变数据前都得先提交mutations
//向后端发送ajax请求就放在Actions里面。在methods里面创建方法,通过axios获取数据,然后更新到store里面定义的变量,这一系列操作都在index.js文件里面完成
  • 如果要对store里面的数值进行逻辑判断(数据过滤、数据的加减乘除),那么就用到getters,用法类似于计算属性computed,getters可以看做是Vuex的计算属性

  • 在Store仓库里,state就是用来存放数据,在Vue里面若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中。但是如果很多组件都使用这个过滤后的数据,比如饼状图组件和曲线图组件,我们是否可以把这个数据抽提出来共享?这就是getters存在的意义。我们可以认为,【getters】是store的计算属性。因为getters是对数据进行逻辑运算,而不是新添加的方法或功能,仅仅是是数据的逻辑运算,所以要始终返回一个新值,可以先在getters下面的方法里面定义一个新值变量,经过计算,然后return出这个新变量

  • getters比较死板,如果你的百度钱包只有在金额为100才能提现,那么你在写提现页面,它是早已固定好的,而Mutation不一样,当你点击百度钱包提现,你哪怕是一元,它只要你点击了便可以提现,而且getters它是不需要什么点击,它就存在,只要你写了,这是什么意思,就是说假设你百度钱包为0,你存在了getter它就有100元,而你如果写许多百度经验,百度再次发红包0.5元时它就是100+0.5+100

四、Vuex辅助函数
mapState
mapGetters
mapMutations
mapActions
改写上面的代码:

Increment.vue组件
<template>
    <p>{{count}}</p>
    <span>{{filterNum}}</span>
    <input type="button" value="+" @click="add" />
    <input type="button" value="-" @click="reduce({n:11})"/>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
export default {
        data(){
        },
     computed:{
        abc(){
            return 123  //普通的计算属性
        },
        ...mapState(['count'])  //这里的count就是store里面定义的仓库里面的count
        ...mapGeters(['filterNum'])  //从getters里面取值(经过逻辑处理的值)
     },
    methods:{

        /*reduce(){  //同步触发action
            this.$store.commit('reduceAction',{n:5})  //同步每次减5
        }*/

        ...mapMutations({  //改写mutations,要传参,参数在模板里面添加reduce({n:11})
            reduce:'reduceAction'
        })

        /*add(){  //异步触发actions
            this.$store.dispatch('addAction')
        }*/

        ...mapActions({  //改写actions
            add:'addAction'
        })
    }
}
</script>

index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

let store = new Vuex.Store({
    state:{
        count:100
    },
    mutations:{
        addHandle(state,payload){  //payload是参数
            state.count+=payload.n;
        },
        reduceAction(state,payload){
            state.count-=payload.n
        }
    },
    actions:{
        addAction(context){
            setTimeout(()=>{
                context.commit('addHandle',{n:15})  //异步每次加15
            },1000)
        }
    },
    getters:{
        filterNum(state){
            return state.count>=102?102:state.count
        }
    }
})

export default store

五、在vue-cli里面使用Vuex
1、npm install vuex --save
2、在src目录下面新建store文件夹,里面新建index.js
3、store/index.js代码:

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
let store = new Vuex.Store({
    state:{
        shopCarData:[]  //购物车的数据默认数据格式是数组,使用Vuex对这个数组进行操作
    },
    mutations:{
        addShopCarData(state,data){
            //do something
        }
    },
    getters:{

    }
})
export default store

4、main.js代码

import store from './store'
new Vue({
    el:'#app',
    router,
    store,
    template:'<App/>',
    components:{
        App
    }
})
上一篇:vuex的安装和基本使用


下一篇:vuex