最详细的Vuex教程

转载 (原文地址) 978990968 教程 原生js 420阅读 2018-03-20 19:46:10 举报

这里要完成的功能是通过按钮的加减来动态的处理数据

1、利用npm包管理工具,进行安装 vuex。在控制命令行中输入下边的命令就可以了。
npm install vuex --save
运行如下命令安装相应的依赖和Vuex

安装完之后我们来新建一个 store 文件夹,在该文件夹下面新建一个 store.js 文件,并显式的通过 Vue.use 来安装 Vuex,其代码如下:

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

Vue.use(Vuex)

在src目录下新建components目录,再在该目录下新建一个组件,取名为 Count.vue,其初始化代码为:

<template>
<div>
</div>
</template>
<script></script>

我们再在main.js文件中引入上面的store.js和Count.vue,代码如下:

import Vue from 'vue'
import Count from './components/Count.vue'

import storeConfig from './store/store'

new Vue({
el: '#app',
render: h => h(Count),
storeConfig,
template: <Count/>,
comments: { Count }
})

以上就完成了一个基本结构的搭建,接下来我们来处理相应的基本功能

先完成一个现实数据的功能
首先我们在store.js文件中加入如下代码,其中 count 为我们待加减的数据:

const state = {
count: 0
};
var vuexStore = new Vuex.Store({
state
});

// 使用 export default 封装,让外部可以访问
export default vuexStore;

然后再在我们的 Count.vue文件中加入如下代码来显示上面的count的值

<template>
<div>
<div>{{$store.state.count}}</div>
</div>

</template>
<script>
import store from "../store/store.js";
export default {
store
};
</script>

这样子的话我们运行我们的程序,页面上就会现实count的初始值0了。

接下来我们就来实现一个加减count值的功能
首先我们来自定义两个组件:展示数据和操作按钮

则Count.vue中的代码就变为:

<template>
<div>
<result></result>
<opbutton></opbutton>
</div>
</template>
<script>
import store from "../store/store.js";
export default {
store,
components: {
result: {
template: <div>{{$store.state.count}}</div>
},
opbutton: {
template: <div> <input type="button" value="+" @click="$store.commit('add')"/> <input type="button" value="-" @click="$store.commit('mul')"/> </div>
}
}
};
</script>

我们看到上面的模板中的按钮点击会相应相应的方法,这个方法就是mutations中的方法,需要在store.js中声明

我们在store.js中加入如下代码:

const mutations = {
add(state) {
state.count++;
},
mul(state) {
state.count--;
}
};

var vuexStore = new Vuex.Store({
state,
// 添加 mutations
mutations
});

以上我们就实现了一个简单的加减的功能。

我们如何在Vue组件中获取Vuex的状态值?

通过computed属性直接给对象赋值
比如我们现在想实现的功能是每次点击”+”号并不是加一,我们希望它再加一之后再乘3输出
我们只要把result中的代码改为

result: {
  template: `<div>{{count}}</div>`,
  computed: {
    count() {
      return this.$store.state.count * 3;
    }
  }
}

通过 mapState辅助函数
则result中的代码如下:

result: {
  template: `<div>{{count}}</div>`,
  computed: mapState({
    count: state => state.count * 3 //理解为传入state对象,修改state.count属性
  })
}

当映射的计算属性的名称与state子节点名称相同的时候,可以使用mapState传递一个数组
如上面例子中的计算属性为count与state子节点名称相同,所以可以 映射 this.count 为 store.state.count

如下代码:

result: {
  template: `<div>{{count}}</div>`,
  computed: mapState(['count'])
}

上面代码中我们按钮的代码如下

<input type="button" value="+" @click="$store.commit('add')"/>

如果我们希望能够传递一个参数给 mutation中的方法要怎么做呢?比如说每次都是加3

则上面的代码改为:

<input type="button" value="+" @click="$store.commit('add',3)"/>

则对应的store.js文件中mutation中的add方法只需要添加一个参数即可,如下:

add(state,n) {
    state.count+=n;
}

这种向store.commit 传入额外的参数的行为我们称为 ——mutation 的 提交载荷(payload)

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

<input type="button" value="+" @click="$store.commit('add',{num:3})"/>

add(state,obj) {
    state.count+=obj.num;
}

有的时候我们并不是很想都看到例如@click="$store.commit('add')"这样子的代码,而是想使用直接一个字符串代替,如@click="add"

那么首先我们要像引入mapState一样来引入mapMutations,如下代码

import { mapState,mapMutations } from "vuex";
1
2
然后我们就可以添加methods属性并加入mapMutations,如下

opbutton: {
  template: `
  <div>
    <input type="button" value="+" @click="add"/>
    <input type="button" value="-" @click="mul"/>
  </div>
  `,
  methods:mapMutations ([
      'add',
      'mul'
    ])
}

有时候我们希望在获取数据之前对数据进行一些操作,即对数据进行一层过滤和加工
比如在上面的例子的基础上,我们希望每次在进行加减运算之前,都将count的值增加100
则我们在store.js文件中加入如下代码

const getters = {
count: function (state) {
return state.count += 100;
}
}

var vuexStore = new Vuex.Store({
state,
mutations,
getters
});
在我们的 Count.vue中的代码如下

result: {
  template: `<div>{{count}}</div>`,
  computed: {
    count() {
      return this.$store.getters.count;
    }
  }
},

接下来我们使用mapGetter来简化我们模板中的代码

首先导入mapGetter

import { mapState, mapMutations,mapGetters } from "vuex";

则相应的计算属性中的代码可以简化为:

result: {
  template: `<div>{{count}}</div>`,
  computed: {
    ...mapGetters(["count"])
  }
}

Action 类似于 mutation,不同在于:

Action是异步改变state的状态,而mutation是同步。
Action里面是可以调用Mutation里面的方法的。

如下,我们来声明一个Action,里面加上两个方法分别调用mutation里面的两个加减方法。

const actions = {
addAction(context) {
context.commit('add');
},
mulAction(context) {
context.commit('mul');
}
};
var vuexStore = new Vuex.Store({
state,
mutations,
getters,
actions
});
相应的Count.vue里面引入mapActions,相应的代码变为

<script>
import store from "../store/store.js";
import { mapState, mapMutations, mapGetters, mapActions } from "vuex";

export default {
store,
components: {
result: {
template: <div>{{count}}</div>,
computed: {
...mapGetters(["count"])
}
},
opbutton: {
template: <div> <input type="button" value="+" @click="addAction"/> <input type="button" value="-" @click="mulAction"/> </div> ,
methods: {
...mapMutations(["add", "mul"]),
...mapActions(["addAction", "mulAction"])
}
}
}
};
</script>

那要怎么来验证Action是异步执行的呢?

我们在addAction中添加如下代码

const actions = {
addAction(context) {
setTimeout(() => { context.commit('add') }, 3000);
console.log('我提前执行了');
},
查看控制台就会发现,console.log('我提前执行了');会首先打印出来。

当应用变得非常复杂时,store 对象就有可能变得相当臃肿,所以这个时候我们就需要把我们状态的各种操作进行一个分模块,分模块后再进行按模块编写。这就用到 module —— 状态管理器的模块组操作。
每个模块拥有自己的 state、mutation、action、getter甚至是嵌套子模块——从上至下进行同样方式的分割

在store.js文件中,修改为如下代码:、

const moduleA = {
state,
mutations,
getters,
actions
}
var vuexStore = new Vuex.Store({
modules :{a:moduleA}
});
现在我们要在模板中使用count的状态值,则如下

<div>{{$store.state.a.count}}</div>

或者使用计算属性

result: {
  template: `<div>{{count}}</div>`,
  computed: {
    count() {
      return this.$store.state.a.count;
    }
  }
},
评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复