切换至深色主题
Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库,借鉴了 Flux、Redux 和 The Elm Architecture。
代码示例
import { createStore, Store } from 'vuex';
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
export const key: InjectionKey<Store<State>> = Symbol();
const store = createStore({
modules: {
a: moduleA,
}
})
export default store;- API接口
import {
version,
Store,
storeKey,
createStore,
useStore,
mapState,
mapMutations,
mapGetters,
mapActions,
createNamespacedHelpers,
createLogger
} from 'vuex';
export default {
setup () {
const store = useStore()
}
}- Store 实例属性
- Store 实例方法
State与mapState辅助函数
computed: {
...mapState([
'app',
'moduleA'
])
},Getter与mapGetters辅助函数
从 store 中的 state 中派生出一些状态。
getters: {
doneTodos (state) {
return state.todos.filter(todo => todo.done)
}
}
computed: {
...mapGetters([
'doneTodos'
])
}
// 通过属性访问
store.getters.doneTodosMutation与mapMutations辅助函数
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
mutations: {
increment (state, payload) {
state.count++
}
}
// 提交载荷(Payload)
store.commit('increment', {})- 订阅Mutation
const unsubscribe = store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
// 停止订阅
unsubscribe()Action与mapActions辅助函数
actions: {
increment ({ commit }) {
commit('increment')
},
async actionA ({ commit }, params) {
commit('gotData', await getData())
},
async actionB ({ commit }, params) {
return await getData();
},
}
methods: {
...mapActions(['increment'])
}
// 派发
store.dispatch('increment', {})
store.dispatch('actionA').then(() => {
// ...
})- 订阅Action
const unsubscribe = store.subscribeAction((action, state) => {
console.log(action.type)
console.log(action.payload)
})
// 停止订阅
unsubscribe()按需加载
Vuex状态管理,通过一次性注入业务逻辑,随着业务逻辑的增加,JS公共包体积就会膨胀变大,这严重影响了首次加载速度。
- 示例一,在main.js添加
Vue.use(function() {
Vue.mixin({
beforeCreate: function() {
// $options是组件选项,包含组件.vue文件的 `export default` 的属性
// 为了拿到在组件定义的是否按需加载的属性值 `isNeedVuex`
if(this.$options.isNeedVuex) {
// 需要设置.vue文件的name属性,跟单文件组件名字命名一样
let name = this.$options.name;
import("./store/modules/" + name).then((res) => {
console.log(res);
// res.default就是代表我们在store/modules文件夹下对应文件的export default对象
// registerModule是vuex自带的方法,请自行搜索
// 第一个参数是动态注入的模块名,第二个参数是模块导出对象
this.$store.registerModule(name, res.default);
});
}
}
});
});组合式函数
import { useStore } from 'vuex'
const store = useStore()缓存页面数据
//在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload",()=>{
sessionStorage.setItem("store", JSON.stringify(this.$store.state))
})内置Logger插件
Vuex 自带一个日志插件用于一般的调试。
import { createLogger } from 'vuex';
const logger = createLogger({});
const store = createStore({
plugins: [logger]
})Pinia 状态管理库
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态,
语法示例
- App.vue
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount("#app");- stores/index.ts
import { reactive } from "vue";
import { defineStore } from "pinia";
import type { SCROLL_ROUTE_TYPE } from "@/constants/router";
export const storeMenu = defineStore("menu", () => {
const menuList = reactive<SCROLL_ROUTE_TYPE[]>([]);
const pushRoute = (item: SCROLL_ROUTE_TYPE) => {
menuList.push(item);
};
const removeRoute = (index: number) => {
menuList.splice(index, 1);
};
const clearRoute = () => {
menuList.splice(0, menuList.length);
};
return { menuList, pushRoute, removeRoute, clearRoute };
});- 代码示例
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
actions: {
increment() {
this.count++
},
},
})
// 读取
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
counter.count++
counter.$patch({ count: counter.count + 1 })
counter.increment()
},
}