安装
npm install vuex@next --save
import store from "./store";
// 全局使用store插件
// 将$store透传全局所有组件
app.use(store)
store结构
src/store/index.js
const store = {
/* 一手数据状态 */
state(){
return {
nums:[]
}
},
/* 基于一手数据换算而来的二手数据 */
getters:{
odds(state){
return state.nums.filter(n=>n%2===1)
},
},
/* 组件通过派发action异步地编辑数据 */
action:{
async fetchNums({ commit, state }, page){
// 异步从后台获取数据
const list = await backEndApi(url,{page})
//提交mutation同步更新state数据
commit("setNums",list)
}
},
/* 提交mutation以同步更新state */
mutations:{
setNums(state, payload){
state.nums = payload
}
},
}
Vue2中使用
import { mapState,mapGetters,mapActions } from "vuex"
export default {
/* 从vuex中订阅数据 */
computed:{
/* 订阅state */
//如果不需要更改state中的数据名字
...mapState([
//将state.nums映射为组件内的同名计算属性this.nums
"nums"
]),
//如果需要更改state中的数据名字
...mapState({
//将state.nums映射为组件内的别名计算属性this.myNums
myNums:"nums"
//当state.nums为一个引用数据类型时,代表使用闭包将组件内的myNums2与外界隔离开来
myNums2:state=>state.nums
}),
/* 订阅getters 不想改名字就数组伺候 否则对象伺候 */
...mapGetters(["odds"]),
...mapGetters({myOdds:"odds"}),
},
methods:{
/* 映射store中action为组件内的方法 不想改名字就数组伺候 否则对象伺候 */
// 组件内形成一个同名方法 fetchNums(page)
...mapActions(["fetchNums"]),
...mapActions({myFetchNums:"fetchNums"}),
},
}
// 在组件内正常地使用计算属性
// 相当于读取store.state.nums(具有响应式)
this.myNums
// 相当于读取store.getters.odds(具有响应式)
this.myOdds
//在组件内正常地使用方法
// 相当于派发action去更新nums this.$store.dispatch('fetchNums',5)
this.myFetchNums(5)
Vue3中使用
<script setup>
//拿到store对象
import { useStore } from "vuex"
const store = useStore()
// 读取store中的数据
store.state.nums
store.getters.odds
// 派发action
store.dispatch('fetchNums',5)
// 在组件以计算属性的形式订阅store中的数据
const myNums = computed(()=>store.state.nums)
const myOdds = computed(()=>store.getters.odds)
</script>
模块化
定义子模块
import { getCities } from "../../api/locationApi";
export default {
/* 子模块的命名空间 */
namespaced: true,
/* 子模块有自己的state */
state() {
return {
cities: [],
};
},
/* 子模块有自己的actions */
actions: {
async fetchCities({ commit, state }) {
const cities = await getCities();
commit("setCities", cities);
},
},
/* 子模块有自己的mutations */
mutations: {
setCities(state, cities) {
state.cities = cities;
},
},
};
在中央仓库中引用子模块
import cityModule from "./modules/city";
const store = {
...
/* 子模块 */
modules: {
news: newsModule,
city: cityModule,
},
...
}
外界访问子模块内容
// 访问子模块中的state(比较特殊)
store.state.city.cities
// 访问子模块中的getters
// store.getters['city/someGetter']
computed:{
...mapGetters([
'city/someGetter', // -> this['city/someGetter']
'city/someOtherGetter', // -> this['city/someOtherGetter']
])
}
// 派发模块中的action
store.dispatch('city/fetchCities')
更多模块内容请参考 官方文档
数据持久化
安装插件
npm i vuex-persistedstate
配置插件
import createPersistedState from "vuex-persistedstate";
const store = {
...
/* 插件 */
plugins: [
// 配置持久化插件(把数据存在localStorage)
createPersistedState(),
],
}
- 插件配置成功之后 Vuex的数据将直接存储在locatStorage中,而非内存中;
- 使用了持久化插件后,vue-devtool将无法继续检测到数据变化
- 没有使用持久化时,刷新页面会导出vuex存储在内存里的数据被清空
- 使用了持久化后,数据永久存储在localStorage中,可以作为全局【数据缓存器】使用
使用本地数据缓存
actions:{
// this.$store.dispatch('fetchPlayings',1)
async fetchPlayings({ commit, state }, page) {
// 本地数据量不满足条件时联网获取数据
if (state.playings.length < 40) {
console.log("联网获取playings数据", page);
const films = await getPlayings(page);
commit("addPlayings", films);
}
// 否则直接使用本地数据缓存
else {
console.log("本地缓存localStorage中已有数据,我什么都不做");
}
},
}