Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
适合多个组件没有关系的时候使用,可以共享数据
基本使用
mutation-types.js
export const ADD = 'ADD'
export const REDUCE = 'REDUCE'
store.js
import Vue from "vue"
import Vuex from "vuex"
import {ADD,REDUCE} from './mutation-types';
Vue.use(Vuex)
//创建状态管理对象
let store = new Vuex.Store({
#状态
//定义共享变量
state:{
count:0,
todo: [
{ id: 1, text: '睡觉', done: true },
{ id: 2, text: '吃饭', done: false },
{ id: 3, text: '打豆豆', done: true },
{ id: 4, text: '敲代码', done: false }
]
},
#变更状态,同步函数
//修改共享数据
mutations:{
increament:function(state,{num = 0}){
state.count += num
},
[ADD](state) {
state.count++
},
[REDUCE](state) {
state.count--
}
},
#派生状态
//派生属性
getters:{
getTodoById: (state) => {
return (id) => {
return state.todo.find(item => item.id === id)
}
}
level:function(state){
if(state.conut < 5){
return "青铜"
}else if(state.count < 10){
return "白银"
}else{
return "黄金"
}
}
}
#异步操作
//通过调用mutations,间接对状态属性产生影响,而不是直接变更状态
//action可以包含任意异步操作
actions:{
increamentAction:function(context){
context.commit("increament",1)
}
},
}),
export default store
页面调用
methods:{
test:function(){
//提交参数= 提交负荷 提交给mutations
this.$store.commit({
type:"increament",
num:3
})
//调用action中的方法
this.$store.dispatch("increamentAction")
}
}
//html中调用
{{$store.state.count}}
{{$store.getters.level}}
<p>{{getTodoById(2).text}}</p>
<button @click="add">增加按钮</button>
<button @click="reduce">减少按钮</button>
#映射方式
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
computed:{
...mapState(['count'])
...mapGetters(['level','getTodoById'])
}
methods:{
...mapMutations(["increament"]),
...mapMutations({
add:'ADD',
reduce:'REDUCE'
})
...mapActions(["increamentAction"])
onFun(){
this.increament()
this.increamentAction()
}
}
模块化使用
index.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
import moduleA from "./modules/moduleA"
import getters from "./getters"
let store = new Vuex.Store({
getters:getters,
modules:{
counting:moduleA
}
})
export default store
moduleA.js
export default {
//定义共享变量
state:{
count:1
},
//修改共享数据
mutations:{
increament:function(state,step){
state.count += step
}
},
//通过调用mutations,间接对状态属性产生影响
actions:{
increamentAction:function(context){
context.commit("increament",1)
}
}
}
getters.js
export default{
level:function(state){
if(state.counting.conut < 5){
return "青铜"
}else if(state.counting.count < 10){
return "白银"
}else{
return "黄金"
}
}
}
页面调用
{{$store.state.counting.count}}
{{$store.getters.level}}
vuex的实现原理
class KStore{
constructor(options){
this.state = options.state;
this.mutations = options.mutations;
this.actions = options.actions;
//借用vue本身的数据相应式机制
this.vm = new Vue({
data:{
state:this.state
}
})
}
commit(type,payload){
const mutation = this.mutations[type];
mutation(this.state,payload)
}
dispatch(type,payload){
const action = this.actions[type];
const ctx = {
commit:this.commit.bind(this),
state:this.state,
dispatch:this.dispatch.bind(this)
}
return action(ctx,payload)
}
}
vuex实例
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
Vue.use(Vuex);
const state = {
num:5
}
export default new Vuex.Store({
state,
getters,
actions,
mutations
})
mutations.js
import {GET_HOT_SHOPS} from './mutation-types.js'
[GET_HOT_SHOPS](state,list){
state.hotShops = state.hotShops.concat(list);
},
mutations-types.js
export const GET_HOT_SHOPS = 'GET_HOT_SHOPS'
actions.js
import axios from 'axios'
import * as types from './mutation-types.js'
export default {
getHotShops({commit,state}){
state.busy = true;
commit(types.IS_SHOW_LOADING_TIPS,true);
axios.get('/mock/home/hot_shop.json').then((response)=>{
commit(types.IS_SHOW_LOADING_TIPS,false);
let result = response.data.list.slice(state.num-5,state.num);
if(result.length !== 0){
commit(types.GET_HOT_SHOPS,result);
state.busy = false;
state.num+=5;
}else{
commit(types.IS_SHOW_LOADED_TIPS,true);
}
})
},
}
getters.js
export default{
hotShops: state=>state.hotShops,
}
保存刷新后没有数据
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from "./mutations"
import getters from './getters'
import actions from './actions'
//import state from './state'
Vue.use(Vuex)
export default new Vuex.Store({
state: sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : {
iscollapse: false,
IsFactory: '',
companys: []
},
mutations,
getters,
actions,
})
APP.vue
<script>
export default {
data() {
return {};
},
mounted() {
window.addEventListener("unload", this.saveState);
},
methods: {
saveState() {
sessionStorage.setItem("state", JSON.stringify(this.$store.state));
},
},
};