Vuex使用小结

218 阅读1分钟

安装

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中已有数据,我什么都不做");
      }

    },
}