Vuex
Vuex
官方文档:https://vuex.vuejs.org/zh/
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式(全局数据存储,多组件共享数据)。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
npm install vuex --save
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
使用 this.$store.state.count 访问全局数据,this.$store.commit('increment') 执行全局方法。
this.$store.commit('increment')
this.$store.state.count // -> 1
State 数据
那么我们如何在 Vue 组件中展示状态呢?
方法一:
<h1>{{this.$store.state.count}}</h1>
方法二:计算属性
<h1>{{count}}</h1>
computed:{
count : function(){
return this.$store.state.count
}
}
方法三:mapState 使用数组
<template>
<h1>{{count}}</h1>
</template>
<script>
import { mapState } from 'vuex' //导入mapState
export default {
computed: mapState([
'count'
])
}
</script>
方法四:mapState 使用对象
<template>
<h1>{{count1}}</h1>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: mapState({
count1: 'count'
}
)
}
</script>
方法五:mapState与其他计算属性混合
<template>
<h1>{{count1}}</h1>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
count1: 'count'
}
)
}
}
</script>
Getter 计算属性
getters:{
reverseMsg:function (state) {
return state.msg.split('').reverse().join('');
}
mapGetters辅助函数
<template>
<h1>{{reverseMsg}}</h1>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed: mapGetters(['reverseMsg'])
}
</script>
计算属性如何传参?
getters:{
mixMsg:function (state) {
return function(val) {
return val+state.msg;
}
}
}
<h1>{{mixMsg}}</h1>
computed: {
mixMsg:function(){
return this.$store.getters.mixMsg("vuex ");
}
}
Mutation 同步方法
用来变更state数据的值。
mutations: {
addCount:function (state,val) {
state.count+=val;
}
<template>
<div>
<h1>{{count}}</h1>
<button @click="clickEvent(3)">点我</button>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'HelloWorld',
methods:{
clickEvent:function(val){
//向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
this.$store.commit('addCount',val);
}
},
computed: mapState([
'count'
])
}
</script>
在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:
mutations: {
addCount:function (state,payload) {
state.count+=payload.val;
}
}
methods:{
clickEvent:function(val){
this.$store.commit('addCount',{val:val});
}
}
mapMutations辅助函数
methods: {
...mapMutations(['increment']), // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
Action
异步请求服务器来获取数据,修改state数据依然用Mutation。
actions: {
setduanzi:function (context) { //context为store对象
var httpUrl = '../duanzi.json';
Vue.axios.get(httpUrl).then(
function (response) {
context.commit('setduanzi',response.data); //调用mutation里的setduanzi方法
}
)
}
mutations: {
setduanzi:function (state,payload) {
state.duanzi = payload
}
}
<template>
<div>
<button @click="clickEvent">获取段子</button>
<ul v-for="item in duanzi">
<li >{{item.msg}}</li>
<li >{{item.time}}</li>
</ul>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: mapState([
'duanzi'
]),
methods: {
clickEvent: function () {
this.$store.dispatch('setduanzi') // dispatch调用store的action方法
}
}
}
</script>
mapActions 辅助函数
<template>
<div>
<button @click="setduanzi">获取段子</button>
<ul v-for="item in duanzi">
<li >{{item.msg}}</li>
<li >{{item.time}}</li>
</ul>
</div>
</template>
<script>
import {mapState,mapActions} from 'vuex'
export default {
computed: {
...mapState(['duanzi'])
},
methods: {
...mapActions(['setduanzi'])
}
}
</script>
Module
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
不开启命名空间:
- 在store目录下新建一个模块product.js,写product特有的state数据,getter计算属性,mutations修改数据的方法,actions异步修改数据的方法,并导出。
import Vue from 'vue'
export default {
state: {
productNum:10,
products:null
},
getters:{
productNumMsg:function (state) {
return state.productNum+"件商品";
}
},
mutations: {
addProductNum:function (state) {
state.productNum++;
},
showProduct:function (state,payload) {
state.products=payload;
}
},
actions: {
showProduct:function (context) {
var url = "../product.json";
Vue.axios.get(url).then(
function (response) {
context.commit("showProduct",response.data);
}
)
}
}
}
- 在index.js中的modules块中引入
import product from "./product";
modules: {
product
}
- 编写测试页面,mapState映射的是modules块中的product名称,通过product.products继续获得对应的数据。
<template>
<div>
<button @click="showProduct">获取产品</button>
<ul v-for="item in product.products">
<li>{{item.name}}</li>
<li>{{item.price}}</li>
<li>{{productNumMsg}}</li>
</ul>
<button @click="addProductNum">添加数量</button>
</div>
</template>
<script>
import {mapGetters, mapState,mapMutations,mapActions} from "vuex";
var mapStateObj = new mapState(['product']);
var mapGettersObj = new mapGetters(['productNumMsg']);
var mapMutationsObj = new mapMutations(['addProductNum','showProduct']);
var mapActionsObj = new mapActions(['showProduct']);
export default {
computed: {
...mapStateObj,
...mapGettersObj
},
methods:{
...mapMutationsObj,
...mapActionsObj
}
}
</script>
开启命名空间:
- 在product.js中加入 namespaced: true
export default {
namespaced: true,
...
- 修改测试页面,在各个map对象前面加入命名空间名称。
import {mapGetters, mapState,mapMutations,mapActions} from "vuex";
var mapStateObj = new mapState('product',['products']);
var mapGettersObj = new mapGetters('product',['productNumMsg']);
var mapMutationsObj = new mapMutations('product',['addProductNum','showProduct']);
var mapActionsObj = new mapActions('product',['showProduct']);

浙公网安备 33010602011771号