一. 安装
1.npm安装
cmd指令:npm install vuex --save
2.其他方法
Vuex安装
二. 使用
1、在一个单独的文件store.js里面,导入Vuex,然后注册可供使用的Vuex插件,而后创建一个新的状态存储库store并传入一个对象来配置这个存储库,这里的state相当于Vue实例里面的data,保存初始的属性值
import Vue from 'vue'
import Vuex from 'vuex'
//注册vuex插件
Vue.use(Vuex);
//创建一个新的状态存储库
//store是一个方法,我们要传入一个对象来配置这个存储库
export const store = Vuex.Store({
//state属性是一个对象,可以用来保存应用中需要的全部状态
state: {
counter: 0
}
});
2、获取state中的数据,例如counter,可以直接使用this.$store.state.counter
调用,若是在其他页面,则需要在根示例的文件中导入存储库store,并在根实例内注册它就可以通过前面的语句访问存储库了,而且由于在根实例内导入注册了,故不需要在其他子组件中再导入存储库,就可以直接访问调用
import Vue from 'vue'
import App from './App.vue'
//导入存储库
import { store } from './store/store.js'
//在根Vue实例内注册vuex,然后才能在整个应用内使用
new Vue({
el: '#app',
store: store,
render: h => h(App)
})
3、对于getter的使用,就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。对于getters的理解主要作用是对state属性进行计算,可以理解类似于Vue中computed,getters里面装的是计算方法。
import Vue from 'vue'
import Vuex from 'vuex'
//注册vuex插件
Vue.use(Vuex);
//创建一个新的状态存储库
//store是一个方法,我们要传入一个对象来配置这个存储库
export const store = Vuex.Store({
//state属性是一个对象,可以用来保存应用中需要的全部状态
state: {
counter: 0
},
//使用getters会使得应用更加高效
getters: {
//doubleCounter实际上是一个函数,这个函数有一个参数state,当该函数别调用的时候,vue会自动传入state
doubleCounter: state => {
return state.counter * 2;
},
stringCounter: state => {
return state.counter + ' Clicks';
}
}
});
调用方法分两种:一种是直接this.$store.getters.(getter方法名称)调用;另外一种是引用store来调用,在需要引用的组件里面导入使用,当然调用为store.getters.(getter方法名称)
<script>
export default {
computed: {
counter() {
return this.$store.getters.doubleCounter;
},
clicks() {
return this.$store.getters.stringCounter;
}
}
}
</script>
注意:当调用的getter变多时,代码会变得冗余,这个时候Vuex提供了一个辅助函数mapGetters,它能自动创建所有计算属性方法,供我们进行计算属性的重写,而且这属于对象展开运算符的内容,在npm中可以添加一个包使用,npm install --save-dev babel-preset-stage-2(为…语法提供支持),并且在添加完这个包后,还需要进入.babelrc的文件,在presets数组中添加一个新项目即为[“stage-2”]
<script>
//mapGetters自动创建所有计算属性方法
import { mapGetters } from 'vuex';
export default {
//mapGetters的参数是一个数组
computed: {
...mapGetters([
//会在后台自动生成计算属性,然后会被映射到getter
'doubleCounter',
//当然也可以对计算属性的名称进行重写,使用对象形式
sc: 'stringCounter'
])
}
}
</script>
4、Vuex的五大核心概念之一的mutation:更改Vuex的store中的状态的唯一方法是提交mutation。是存放处理数据的方法的集合。
其使用方法是,先在创建的store存储库中添加mutations属性,然后往里面添加需要的方法,方法参数为store中的state,因为mutation就是主要就是为了修改state状态。
import Vue from 'vue'
import Vuex from 'vuex'
//注册vuex插件
Vue.use(Vuex);
//创建一个新的状态存储库
//store是一个方法,我们要传入一个对象来配置这个存储库
export const store = new Vuex.Store({
//state属性是一个对象,可以用来保存应用中需要的全部状态
state: {
counter: 0
},
//使用getters会使得应用更加高效
getters: {
//doubleCounter实际上是一个函数,这个函数有一个参数state,当该函数别调用的时候,vue会自动传入state
doubleCounter: state => {
return state.counter * 2;
},
stringCounter: state => {
return state.counter + ' Clicks';
}
},
//mutation也是保留属性,就是一个列表,或者说是一些可执行的方法
//mutation的优点在于同步跟踪存储库中属性的变化,但是不能异步执行
mutations: {
//传入state作为参数输入
increment: state => {
state.counter ++;
},
decrement: state => {
state.counter --;
}
}
});
若想要在其它组件中调用这些个修改state状态的方法,使用语法this.$store.commit(‘方法名称’)来触发修改方法
<script>
export default {
methods: {
increment() {
this.$store.commit('increment');
},
decrement() {
this.$store.commit('decrement');
}
}
}
</script>
当然,为了代码简洁也有和mapGetters类似的辅助函数,比如mapMutations,用法和mapGetters几乎一模一样(而且也有mapState,本文不做描述,详情参考:mapState)
<script>
import { mapMutations } from 'vuex';
export default {
methods: {
...mapMutations([
'increment',
'decrement'
])
}
}
</script>
5、actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据(但是还是通过mutation来操作,因为只有它能操作)。Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
使用方法:先在创建的store存储库中添加actions属性,然后添加一个函数方法,这个方法函数的参数为context,因为能提交mutation的对象方法commit是在action属性的context对象中。语法为:context.commit('需要调用的mutation中的方法名');
例如:
actions: {
//context由vuex自动传入,有了context就能访问到commit方法
//context里面有很多方法
increment: context => {
context.commit('increment');
}
}
另一种写法(使用参数解构来简化代码):
actions: {
//就可以直接使用对象方法了
increment: ({ context }) => {
commit('increment');
}
}
进行异步操作:
actions: {
//就可以直接使用对象方法了
increment: ({ context }) => {
commit('increment');
},
asyncIncrement: ({ commit }) => {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
当然,为了代码简洁也有和mapMutations类似的辅助函数,比如mapActions,用法和mapMutations几乎一模一样。
<script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions([
'increment',
'decrement'
])
}
}
</script>
为了能够调用通过mapActions映射创建的方法,我们使用语句this.$store.dispatch('mapActions中需要调用的方法名')
<script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions([
'increment',
'decrement'
]),
increment() {
this.$store.dispatch('increment');
}
}
</script>
我们也可以在每个action中传入一个参数,action把传入的参数传递给mutation,因为mutation不仅可以访问state,其第二个参数就可以是action传递过来的参数。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
counter: 0
},
getters: {
doubleCounter: state => {
return state.counter * 2;
},
stringCounter: state => {
return state.counter + ' Clicks';
}
},
mutations: {
increment: (state, payload) => {
state.counter += payload;
},
decrement: (state, payload) => {
state.counter -= payload;
}
},
actions: {
//payload作为传入的参数传递给触发的mutation方法
increment: ({ commit }, payload) => {
commit('increment', payload);
},
decrement: ({ commit }, payload) => {
commit('decrement', payload);
},
asyncIncrement: ({ commit }, payload) => {
setTimeout(() => {
commit('increment');
}, 1000);
},
asyncDecrement: ({ commit }, payload) => {
setTimeout(() => {
commit('decrement');
}, 1000);
}
}
});
<template>
<div>
<button class="btn btn-primary" @click="increment(100)">Increment</button>
<button class="btn btn-primary" @click="decrement(50)">Decrement</button>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions([
'increment',
'decrement'
])
}
}
</script>
我们也可以把对象当做一个参数传入,这样做的好处是一个对象可以有多个属性,不会被写死。
例如:asyncIncrement里面设置了两个属性,分别为by(用来设置步长)和duration(设置间隔时间)。
<template>
<div>
<button class="btn btn-primary" @click="asyncIncrement({by: 50, duration: 500})">Increment</button>
<button class="btn btn-primary" @click="asyncDecrement({by: 50, duration: 500})">Decrement</button>
</div>
</template>
然后在回调函数中就直接调用。
actions: {
//payload作为传入的参数传递给触发的mutation方法
increment: ({ commit }, payload) => {
commit('increment', payload);
},
decrement: ({ commit }, payload) => {
commit('decrement', payload);
},
asyncIncrement: ({ commit }, payload) => {
setTimeout(() => {
commit('increment', payload.by);
}, payload.duration);
},
asyncDecrement: ({ commit }, payload) => {
setTimeout(() => {
commit('decrement', payload.by);
}, payload.duration);
}
}