【学习笔记】vuex

1.getter

store中的计算属性
比如:初始的状态值为0

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:0}
})

通过计算属性改变count的值,如果不用vuex的话

<div id='ex1'>
<p>Computed count:"{{addCount}}"</p>
</div>
var vm = new Vue({
el:"#ex1",
data:{count:0},
computed:{
addCount:funtion(){
return this.count + 3
}
})

结果:
Computed count:3
现在,使用vuex,就要在store里的getters来改变count

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:0},
getters:{
addCount:state => {
return state.count + 3;}
}
})

原本写在计算属性里面的addCount方法,写在了getters里面,然后computed属性里面直接返回store.getters对象的addCount

const Counter={
template:"<div id='ex1'>
<p>Computed count:{{addCount}}</p>
</div>",
computed:{
addCount(){
return this.$store.getters.addCount}
}

1.1 mapGetters辅助函数

已知有getter方法addCount

export default new Vuex.Store({
  state: {
    count: 0,
    name: "xixi"
  },
  getters: {
    addCount: state => {
      return state.count + 3;
    }
  },
  //.......

不使用mapGetters时

computed: {
    addCount() {
      return this.$store.getters.addCount;
    }
  },
 

使用mapGetters时
首先在组件中导入mapGetters

import {mapGetters} from 'vuex';

然后在mapGetters里面建立addCount方法的映射,这里取名为myAddCount

 computed: { ...mapGetters({ myAddCount: "addCount" }) },

那么相应的,在模板里

<div class="c">{{ myAddCount }}</div>

1.2mapState辅助函数

已知state里面有count为1

export default new Vuex.Store({
  state: {
    count: 1,
    name: "xixi"
  },

不使用mapState的情况下

computed: {
  count() {
      return this.$store.state.count;
    }
  },

同时模板中

<div class="d">{{ count }}</div>

使用mapState的情况下
在组件中引入mapState

import { mapState } from "vuex";

然后用展开运算符讲mapState里面的对象混入到computed属性里面

computed: {
    ...mapGetters({ myAddCount: "addCount" }),

    ...mapState({
      count: state => state.count
    })
  },

2.mutation

1.mutation翻译过来有改变,转变的意思,即用来改变状态。
2.更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
3.类似store中的事件
4.mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),并且它会接受 state 作为第一个参数
5.Mutation 必须是同步函数

比如:初始值状态为1

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:1}
})

如果不使用vuex来改变

<div id="ex2">
<p>subtractCount count:{{count}}</p>
<button @click="subtractCount">subtractCount</button>
</div>
var vm2 = new Vue({
el:'#ex2',
data:{count:1},
methods:{
subtractCount:function(){
return this.count-3}
}
})

使用vuex,把methods的回调写到mutations里面,相当于事件注册

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:1},
mutations:{
subtractCount(state){
state.count-=3}
}
})

然后用commit方法提交mutation(这里是同步触发的)

const count2 = {
template:'<div>
<p>subtractCount count:{{count}}</p>
<button @click="$store.commit('subtractCount')">subtractCount</button>
</div>'
}

提交载荷

可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)

//...
mutations:{
subtractCount(state,n){
state.count-=n}
}

store.commit('subtractCount',3)

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

3.action

1.action类似于mutation
2.action提交的是mutation,而不是直接变更状态
3.action可以包含任意异步操作

如果想异步的触发mutations里面的事件,那么就要在action里面写一个异步函数来提交mutations里面的事件

比如:初始状态为2

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:2},
mutations:{
subtractCount(state){
state.count-=3}
},
actions:{
subtractCountAsync(context){ 
//Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
//因此你可以调用 context.commit 提交一个 mutation
//或者通过 context.state 和 context.getters 来获取 state 和 getters。
setTimeout(()=>{context.commit("subtractCount")},1000)
}
}
})

实践中,我们会经常用到 ES2015 的 参数解构 来简化代码

actions: {
  increment ({ commit }) {
   setTimeout(()=>{commit("subtractCount")},1000)
  }
}

然后Action 通过 store.dispatch 方法触发

const count2 = {
template:'<div>
<p>subtractCount count:{{count}}</p>
<button @click="$store.dispatch('subtractCountAsync')">subtractCountAsync</button>
</div>'
}

载荷形式

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state:{
count:2},
mutations:{
subtractCount(state,n){
state.count-=n}
},
actions:{
subtractCountAsync({commit},n){ 
setTimeout(()=>{commit("subtractCount",n)},1000)
}
}
})

同样以载荷形式分发

store.dispatch('incrementAsync', 3)

异步操作如何得到结果

store.dispatch可以处理action里面的函数所返回的Promise,并且store.dispatch 仍旧返回 Promise

假如state里面有个name属性,点击按钮会在一段时间后弹出欢迎弹窗,

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
   name: "xixi"
  },
  mutations:{
   greet(state) {
      alert("Hello" + state.name);
    }
  },
  actions:{
  greetAsync({ commit }) {
      return new Promise(resolve => {
        setTimeout(() => {
          commit("greet");
          resolve();//将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)
          //在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
        }, 10000);
      });
}
})

然后用then方法处理成功后的回调函数

const showname = {
template:'<div><button @click="$store.dispatch('greetAsync')then(() => showName())"> 点击弹出欢迎</button></div>',
methods: {
    showName: function() {
      console.log(this.$store.state.name);
    }
  }
}

mapActions

已知actions里面有一个gerrtAsync方法

actions: {
   greetAsync({ commit }) {
      return new Promise((resolve, reject) => {
        if (
          setTimeout(() => {
            commit("greet");
          }, 10000)
        ) {
          resolve();
        } else {
          reject(1);
        }
      });
    }
  },

如果不使用mapActions

 </button>
    <button @click="$store.dispatch('greetAsync').then(() => showName())">

如果使用mapActions
那么先引入mapActions

import { mapActions } from "vuex";

在methods里面吧$store.dispatch(‘greetAsync’)映射为"greetAsync"

 methods: {
  ...mapActions(["greetAsync"])
  }
};

然后再html里面用greetAsync()代替$store.dispatch(‘greetAsync’)

 <button @click="greetAsync().then(() => showName())">
      点击弹出欢迎
    </button>

mapActions里面带参数的用法

已知actions里面有multiplyAsync方法他带有一个参数playload

actions: {
    multiplyAsync({ commit }, playload) {
      setTimeout(() => {
        commit("multiplyCount", playload);
      }, 1);
    }}

不用mapactions的情况

 <button @click="$store.dispatch('multiplyAsync', { amount: 3 })">

如果使用mapActions
首先引入mapActions

import { mapActions } from "vuex";

在方法里面把$store.dispatch(‘multiplyAsync’, { amount: 3 })映射为"multiplyAsync"
这里是分发多个actions

 methods: {
    showName: function() {
      console.log(this.$store.state.name);
    },
    ...mapActions(["greetAsync", "multiplyAsync"])
  }

最后在html里面把$store.dispatch(‘multiplyAsync’, { amount: 3 })改为multiplyAsync({ amount: 3 })

  <button @click="multiplyAsync({ amount: 3 })">
      点击得到3的倍数
    </button>

Module

module是模块的意思
为了解决单一状态数造成store变得复杂臃肿的问题,我们可以将store分割成模块。
每个模块都拥有自己的mutation、action、getter、甚至是嵌套子模块。

在工程中新建一个名为modules的文件夹
里面放入需要分割的模块文件,这里为Blog.js
在这里插入图片描述
我们来看Blog.js内部

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);
// eslint-disable-next-line no-unused-vars
const Blog = {
  state,
  actions,
  mutations,
  getters
};
export default Blog;

const state = {
  blogTitle: "雯雯Blog",
  views: 10,
  blogNumber: 100,
  total: 0,
  todos: [
    { id: 1, done: true, text: "我是lala" },
    { id: 2, done: false, text: "我是feifei" },
    { id: 3, done: true, text: "我是xixi" }
  ]
};

const mutations = {
  addViews(state) {
    state.views++;
  },
  blogAdd(state) {
    state.blogNumber++;
  },
  clickTotal(state) {
    state.total++;
  }
};

const getters = {
  getToDo(state) {
    return state.todos.filter(item => item.done === true);
  }
};
const actions = {
  addViews({ commit }) {
    commit("addViews");
  },
  clickTotal({ commit }) {
    commit("clickTotal");
  },
  blogAdd({ commit }) {
    commit("blogAdd");
  }
};

能够看出他拥有自己的mutation、action、getter等,一定要记得导出

export default Blog;

模块写好之后在index.js里面的modules里面导入,前面的部分省略了

import Vue from "vue";
import Vuex from "vuex";
import Blog from "./modules/Blog";

Vue.use(Vuex);

export default new Vuex.Store({
 //......
  modules: {
    Blog//这里使用了es6的新特性,未指定属性名,默认属性值和属性名同名,相当于Blog:Blog
  }
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值