vuex基本使用
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
import module1 from './modules/module1'
import module2 from './modules/module2'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1
},
// 必须是同步的
mutations: {
increase(state){
state.count+=1;
}
},
// 异步的mutations,处理异步数据,比如处理与后端的请求
actions: {
// 获取到的时store实例,直接解构出state,commit使用, 同时还可以进行传参
increaseAsync({state,commit},args){
// 异步处理很多时候需要得到异步结果,返回一个Promise对象
// return new Promise(resolve=>{
// })
}
},
// 类似于组件中的computed,对state中数据进行加工
getters: {
money: state=>{
return state.count+'元'
}
},
// 当store中数据和操作过多,可以进行分模块
modules: {
module1,
module2
},
})
// page.vue
<template>
<button @click=incAsync() >increaseAsync</button>
<button @click=inc() >increase</button>
<!--
<p></p>
<p></p>
-->
<!-- 使用map帮助方法后-->
<p>8</p>
<p></p>
</template>
<script>
// 引入vuex的帮助方法mapState用于映射状态=>mapState是个函数,返回的是一个对象
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
methods: {
// increase(){
// // 执行mutations里面的increase方法
// this.$store.commit('increase');
// },
// incAsync(){
// // 执行mutations里面的increase方法
// this.$store.dispatch('increaseAsync',args);
// }
// 当在store中的actions中使用返回Promise对象时这里就能使用async/await进行异步处理
// async incAsync(){
// // await拿到返回的异步结果然后处理
// await this.$store.dispatch('increaseAsync',args);
// }
// 引入对应map方法后
...mapMutations(['increase']),
...mapActions(['increaseAsync']),
inc(){
this.increase();
},
incAsyc(){
this.increaseAsync(args);
}
},
computed: {
// 因为mapState方法返回的是一个对象,所以需要解构出来,相当于
// {count: this.$store.state.count},这时count就变成了计算属性,可以直接使用
...mapState(['count']),
...mapGetters(['money'])
// 本质就是将状态声明为组件中的计算属性,一个组件需要获取多个状态时方便使用
...mapState({
count:state=>state.count+"元"
})
}
}
</script>
const store =new Store({
state:{
token: localStorage.getItem("token") || "",
cart: JSON.parse(localStorage.getItem("cart")) || [
},
mutation:{
},
actions:{
}
})
// 订阅store变化
store.subscribe((mutation, state) => {
switch (mutation.type) {
case "setToken":
localStorage.setItem("token", JSON.stringify(state.token));
break;
case "addCart":
localStorage.setItem("cart", JSON.stringify(state.cart));
break;
}
});
export default store;
vuex原理解析
// Vue.use(Vuex),这是vue安装插件的机制,需要Vuex对外暴露一个install方法,会把Vue传递给install这个函数
// 在vue.use的源码中 /src/core/global-api/use.js
// 其实就是把传递插件的install方法执行一下,存储在一个插件数组中, 传递Vue进去,我们可以利用这个机制,对Vue本身进行扩展
// mini-vuex
let Vue;
function install (_Vue) {
Vue = _Vue;
function vuexInit () {
var options = this.$options;
// store injection
if (options.store) {
this.$store = typeof options.store === 'function'
? options.store()
: options.store;
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store;
}
}
Vue.mixin({ beforeCreate: vuexInit });
}
const Store = function Store (options = {}) {
const {state = {}, mutations={}, getters={}} = options
const computed = {}
const store = this
store.getters = {};
for (let [key, fn] of Object.entries(getters)) {
computed[key] = function () { return fn(store.state, store.getters); };
Object.defineProperty(store.getters, key, {
get: function () { return store._vm[key]; },
});
}
this._vm = new Vue({
data: {
$$state: state
},
computed,
})
this._mutations = mutations
}
Store.prototype.commit = function(type, payload){
if(this._mutations[type]) {
this._mutations[type](this.state, payload)
}
}
Object.defineProperties(Store.prototype, {
state: {
get: function(){
return this._vm._data.$$state
}
}
});
export default {Store, install}