vuex状态管理

44 篇文章 0 订阅
43 篇文章 0 订阅
vuex优点
存缓存的话容易修改和暴露,vuex的话就没那么容易了
存缓存的话刷新浏览器缓存不会被重置,vuex会被重置
vuex用于组件之间的传值,localstorage,sessionstorage则主要用于不同页面之间的传值。
但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage,sessionstorage无法做到

新建store/index.js

npm install vuex --save
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex)
const Store = new Vuex.Store({
    state:{
        count:1
    }
})
export default Store;

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index.js' //新增


new Vue({
  el: '#app',
  router,
  store,//新增
  components: { App },
  template: '<App/>'
})

 

子组件引用
{{this.$store.state.count}}   //1   
容易混淆
mutation是同步的  即不进行axios或者promise之类的异步请求操作
actions是异步的  即进行axios或者promise之类的异步请求操作 但本质上也是通过commit改变state的值
使用vuex修改state时,有两种方式:
可以直接使用 this.$store.state.变量 = xxx;
this.$store.dispatch(actionType, payload) 
或者:this.$store.commit(commitType, payload)
使用dispatch 和 commit的区别在于,前者是异步操作,后者是同步操作,所以 一般情况下,推荐直接使用commit,
 即 this.$store.commit(commitType, payload),以防异步操作会带来的延迟问题。

异同点
共同点: 能够修改state里的变量,并且是响应式的(能触发视图更新)
不同点:
若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过
mutation的函数,vue就会  throw error :    [vuex] Do not mutate vuex store state outside mutation handlers。

使用commit提交到mutation修改state的优点:
vuex能够记录每一次state的变化记录,保存状态快照,实现时间漫游/回滚之类的操作。
 (实际本人未用到,暂时未遇到使用该特性的需求)
结论: 官方推荐最好设置严格模式,并且每次都要commit来修改state,而不能直接修改state,以便于调试等。

getters

getters  可以减少代码量,如果其他组件需要,
getters  在通过方法访问时,每次都会去进行调用,而不会缓存结果

和计算属性一样,getter 的返回值会根据它的依赖被缓存起来

且只有当它的依赖值发生了改变才会被重新计算。

store 对象注入到根实例后,在所有的子组件中,就可以用this.$store 来指向store 对象,获取state。在子组件中,computed 属性是根据它的依赖自动更新的。所以只要store中的state发生变化,它就会自动变化。
 getters: {
        //得到状态值
        getCountAdd:state=>{
            state.count = state.count+999;
        },
    },
//and
computed: {
        fn() {
          return this.$store.getters.getCountAdd
        }
      }

子组件引用   
this.$store.getters.getCountAdd //  1+999

 

 

mutations(同步操作)

actions是异步操作(本身也是操作mutation)
改变state唯一方法是提交 mutation即commit
如果直接调用mutation方法跟直接改变store.state是一样,这样vuex跟踪不到数据的变化,无法做到响应式了
commit是响应式的
你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload) 传参数
store/index.js
 // 不建议在mutations修改 建议在action修改
mutations:{
        add(state,n){
            state.count = state.count+n;
        }
    },
子组件  
 clickAdd:function(){
     this.$store.commit("add",1)
},

 

分发actions(异步操作)

Action 提交的是 mutation,而不是直接变更状态。
Action 通过 store.dispatch 方法触发

mutations:{
        add(state,n){
            state.count = state.count+n.count;
        }
    }, 
actions:{
        addFun:function(context,n){
            context.commit("add",n.count)
        },
    }
子组件引用

 this.$store.dispatch("addFun",{
   count:1
   })//actions


es6 解构赋值
{ commit } 的 commit= context.commit 

在action中调用其他action(用处不大)

module

引用: this.$store.state.moduleA.name

moduleA.js
const moduleA = {
    state:{
        count:1
    },
    getters: {},
    // 不建议在mutations修改 建议在action修改
    mutations:{
        addModule(state,n){
            // state.count = state.count+n.count;
            console.log("module 分组件引用")
        }
    },
    actions:{
        addModuleFun:function(context,n){
            context.commit("addModule",n)
        }
    }
}
export default moduleA;


store/index.js

import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
    state:{},
    getters: {},
    // 不建议在mutations修改 建议在action修改
    mutations:{},
    actions:{},
    modules:{
        moduleA:moduleA
    }
})
export default Store;


子组件引用
 console.log(this.$store.dispatch("addModuleFun",2))//actions 
 //打印 'module 分组件引用'
  但是引用modules里面的state要用: this.$store.state.login.useName
其他getters mutations actions 都可以通过全局引用 在其引用的函数里默认参数却不是全局的,都是局部的比如state引用全局需引用rootState
rootState.job 就是全局里面的state里面的job等于 'web' 字符串
const actions = {
  // actions 中的context参数对象多了 rootState 参数
  changeName ({commit, rootState},anotherName) {
    if(rootState.job =="web") {
      commit("change_name", anotherName)
    }
  }
};
如果想局部使用commit之类的得用namespaced:true限定到模块的命名空间
// namespaced 属性,限定命名空间
export default {
  namespaced:true,
  state,
  mutations,
  actions,
  getters
}
例子

methods: {
  changeName() {
   this.$store.dispatch("login/changeName", "Jason")
  },
  alertName() {
   this.$store.dispatch("login/alertName")
  }

辅助函数

mapState 与 mapGetters 要放在计算属性computed中。

(computed只能使用属性)this.state or this.gettters

mapMutations与mapActions要放在methods中。

(methods只能使用方法)this.mutations() or this.action() or  this.gettters()

//正常
computed: {
    orderList(){
        return this.$store.state.orderList;
    },
    login(){
        return this.$store.state.login;
    }
}
//mapState
computed: {
    ...mapState([
        'orderList',
        'login'
    ]),
}
切记:mapState的属性的时候,一定要和state的属性值相对应,也就是说 state中定义的属性值叫add,那么mapState就叫add,如果我们改成add2的话,就获取不到add的值了,并且add2的值也是 undefined   

computed: {
        ...mapState({
          add: state => state.add,
          counts: state => state.counts
        })
    },
    mounted() {
      console.log(this.add); // 打印出 0
      console.log(this.counts); // 打印 0 
    }
this.incrementStep

 

import { mapGetters } from 'vuex'
       //数组形式
      //...mapGetters([
     //'getCountAdd',
    //'getCountAdd2'
   //]),
  //对象形式
     ...mapGetters({
       getCountAdd:"getCountAdd",
       getCountAdd2:"getCountAdd2"
     })
//相当于 => this.$store.getters("getCountAdd")  this.$store.getters("getCountAdd2")

...mapState同理

  ...mapState({
          counts: state => console.log( "mapStateL:"+state.count)
        }),

...mapMutations同理

...mapActions同理

 

test() {
        // 调用
        Promise.all([this.commonActionGet(['getPower', {}])]).then((res) => {

        });
      },
      // mapActions 使用方法一 将 this.commonActionGet() 映射为 this.$store.dispatch('commonActionGet')
      ...mapActions(['commonActionGet', 'commonActionGetJSON', 'commonActionPost', 'commonActionPostJSON'])
      /*
       // 第二种方式
       ...mapActions({
         'commonActionGet': 'commonActionGet',
         'commonActionGetJSON': 'commonActionGetJSON',
         'commonActionPost': 'commonActionPost',
         'commonActionPostJSON': 'commonActionPostJSON'
       })
      */
    }
事件名字和action一样的时候
 ...mapActions({
     'increment'
    })
事件名字和action不一样的时候
 ...mapActions({
      add: 'increment'
    })
<button @click="addFun({count:123})">add</button>
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
    state:{
        count:1
    },
    getters: {},
    // 不建议在mutations修改 建议在action修改
    mutations:{
        add(state,n){
            state.count = state.count+n.count;
        }
    },
    actions:{
        addFun:function(context,n){
            context.commit("add",n)
            // context.commit("add",{count:1})
        }
    },
    modules:{
        moduleA:moduleA
    }
})
export default Store;

子组件
 methods:{
     ...mapActions({
       addFun:"addFun",
     }),
//this.$store.dispatch("addFun",{count:123})
}

如果需要传值就用  事件绑定@的方式     或者this.$store.dispatch("addFun",{count:1})

//较完整的例子
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA.js";
import moduleB from "./moduleB.js";
Vue.use(Vuex)
const Store = new Vuex.Store({
    state:{
        count:1
    },
    getters: {
        //得到状态值   只能通过 mutations 改变 state 的值
        getCountAdd:(state)=>{
            state.count = state.count+999;
            console.log(state.count )
        },
        getCountAdd2:(state)=>{
            state.count = state.count+1000;
            console.log(state.count )
        },
    },
    // 不建议在mutations修改 建议在action修改
    mutations:{
        add(state,n){
            state.count = state.count+n.count;
        },
        remove(state,n){
            state.count = state.count-n;
        }
    },
    actions:{
        addFun:function(context,n){
            context.commit("add",{count:1})
            context.commit("add",{count:1})
        },
        removeFun:function(context,n){
            context.commit("remove",n)
        }
    },
    modules:{
        moduleA:moduleA,
        moduleB
    }
})
export default Store;


vuex辅助函数简单实用demo

//Mutations
const increment = (state) => {
  state.count++
}
const decrement = (state) => {
   state.count--
}

// action处理一些异步操作  Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
let incrementAsync = (content) => {
  setTimeout(() => {
    content.commit('increment')
  }, 1000)
}
let decrementAsync = (content) => {
  setTimeout(() => {
    content.commit('decrement')
  }, 1000)
}
export {increment ,decrement ,incrementAsync, decrementAsync}

<template>
  <div>
    <button @click="decrementAsync">-</button>
    <span>{{count}}</span>
    <button @click="incrementAsync">+</button>
  </div>
</template>
 
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
/*
 mapState辅助函数和你要调用的this.data的参数一样 必须在computed里
 普通写法:this.$store.state.count
 mapMutations, mapActions辅助函数的名字必须和事件的名字一样 必须在methods里
普通写法:this.$store.commit("increment ")//this.$store.commit("increment",2)
普通写法:this.$store.dispatch("incrementAsync")//this.$store.dispatch("incrementAsync",2)
*/
export default {
  computed: {
    ...mapState(['count'])
  },
  methods: {
    ...mapMutations(['increment', 'decrement']),
    ...mapActions(['incrementAsync', 'decrementAsync']) //这里用了辅助函数
  }
}
</script>
 
<style>
</style>


 

 

this.$store.dispatch() 与 this.$store.commit()方法的区别
this.store.dispatch( ) 与this. store.dispatch() 与 this.store.dispatch()与this.store.commit()方法的区别总的来说他们只是存取方式的不同,两个方法都是传值给vuex的mutation改变state
this.store.dispatch() : 含 有 异 步 操 作 , 例 如 向 后 台 提 交 数 据 ,写 法:this. store.dispatch() :含有异步操作,例如向后台提交数据,写法:this.store.dispatch():含有异步操作,例如向后台提交数据,写法:this.store.dispatch(‘action方法名’,值)
this.store.commit( ) : 同 步 操 作 , 写 法 : this. store.commit():同步操作,,写法:this.store.commit():同步操作,,写法:this.store.commit(‘mutations方法名’,值)
commit: 同步操作
存储 this.$store.commit('changeValue',name)
取值 this.$store.state.changeValue
dispatch: 异步操作
存储 this.$store.dispatch('getlists',name)
取值 this.$store.getters.getlists

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值