前言

Vue的最新官网文档中,细心的小伙伴会发现Vuex已经被Pinia给代替啦,于是我翻出我之前项目将Vuex也换成了Pinia进行了对比学习。

Pinia的基本使用

安装Pinia数据持久化(数据持久化实现): npm i pinia-plugin-persistedstate

安装Pinia: npm i pinia

Vuex和Pinia的挂载

Vuex的挂载:
import { createApp } from 'vue'
import store from './store/vuexIndex'
createApp(App).use(store).mount('#app')

Pinia的挂载:
import { createApp } from 'vue'
//挂载pinia
import { createPinia } from 'pinia'
const pinia = createPinia()
//pinia持久化
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
pinia.use(piniaPluginPersistedstate)

createApp(App).use(pinia).mount('#app')

创建Sotre

Vuex:
import { createStore } from 'vuex'
import { getPlayList } from '../api/index'
/* 配合vuex进行持久化数据*/
import persistedState from 'vuex-persistedstate'
const store = createStore({
    state() {
        return {
            //整个音乐列表的数据存储
            musicObj: {},
            //底部随机音乐的 存储
            bottomMusic: {},
            //存储是否点击歌曲
            acitve: truecount:0
        }
    },
    mutations:
    {
        //保存发现好歌单信息
        saveMusic(state, obj) {
            state.musicObj = obj
        },
        //通过acion异步获取底部歌单播放详情
        getMusic(state, obj) {
            state.bottomMusic = obj
        },
        ......
    },
    getters: {
         handleCount()
        {
          state.count++
      }
   },
    actions: {
        //拿到列表中的默认播放歌单
        async getMusicList(context) {
            let res = await getPlayList(1)
            context.commit('getMusic', res.data.playlist.tracks)

        }
    },
    plugins: [persistedState(/* { storage: window.sessionStorage } */)]
})

export default store

Pinia:
import { defineStore } from 'pinia'
import { getPlayList } from '../api/index'
export const mainStore = defineStore('main', {
    state: () => {
        return {
            //整个音乐列表的数据存储
            musicObj: {},
            //底部随机音乐的 存储
            bottomMusic: {},
            //存储是否点击歌曲
            acitve: true
        }
    },
    getters: {
         handleCount()
        {
          this.count++
      }
   },
    actions: {
        //拿到列表中的默认播放歌单
        async getMusicList(context) {
            let res = await getPlayList(1)         
        }
    },
    //开启数据持久化存粗
    persist: true
})

使用Store

import { onBeforeMount} from "vue";

//Vuex引入:
import { useStore } from "vuex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
<script>
export default {
  setup() {
    //创建VuexStore
    const storeVuex = useStore();
    //创建PiniaStore
    const storePinia = mainStore();
    
    function handleIcon(index) {
      isListen = !isListen;
      indexNumber.value = index;
      //通过点击传递指定列表数据 
      
      //在Vuex获取musicObj数据
      emitter.emit("event", storeVuex.state.musicObj[index]);
      //在Pinia获取musicObj数据
      emitter.emit("event", storePinia.musicObj[index]);
    }

  }
<script>

Vuex结构Store:mapState,Pinia结构Store:storeToRefs

import { onMounted } from "vue";
//Vuex引入:
import { mapState } from "../../store/piniaIndex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
import { storeToRefs } from "pinia";
<script>
export default {
  setup() {
    //storeVuex
    const storeVuex = mapState(["bottomMusic", "acitve"]);
  
    //PiniaStore
    const storePinia = mainStore();
    const { bottomMusic, acitve } = storeToRefs(storePinia);
    
    let musicAhtuor = ref("");
    let isActive = ref(acitve);
    onMounted(async () => {
      musicAhtuor.value = bottomMusic.ar[0].name;
    });
    return(
    ...storeVuex
    )

  }
<script>

简单数据修改

import { onMounted } from "vue";
//Vuex引入:
import { useStore } from "vuex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
<script>
export default {
  setup() {
    //storeVuex
    const storeVuex = useStore()
  
    //PiniaStore
    const storePinia = mainStore();
    
    let isActive = ref(true);
    //获取事件总线传递过来的数据
    emitter.on("event", (e) => {
      ......
    for (let i = 0; i < 2; i++) {
        //Vuex
        ID[0] === ID[1]? store.commit("getIsActive", true): store.commit("getIsActive",false);
        //Pinia
        ID[0] === ID[1] ? (storePinia.acitve = true) : (storePinia.acitve = false);
      }
      if (ID.length === 2) {
        ID = [];
      }
    });

  }
<script>

多条数据修改

import { onBeforeMount } from "vue";
//Vuex引入:
import { useStore } from "vuex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
<script>
export default {
  setup() {
    //storeVuex
    const storeVuex = useStore()
  
    //PiniaStore
    const storePinia = mainStore();
    
    let state = reactive({ playData: {} });
    onBeforeMount(async () => {
       ......
       //Vuex需要用到
       
      //Pinia
      //$patch+对象
      storePinia.$patch({
        musicObj: state.playData.tracks,
        count:count+2
      });
      //$patch+函数
      storePinia.$patch((stateP) => {
        stateP.musicObj = state.playData.tracks;
        count:stateP.count+2
      });
  }
<script>

通过action修改

//Vuex引入:
import { useStore } from "vuex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
<script>
export default {
  setup() {
    //storeVuex
    const storeVuex = useStore()
    storeVuex.dispatch("getMusicList");
  
    //PiniaStore
    const storePinia = mainStore();
    storePinia.getMusicList();
  }
<script>

Getter的使用

VuexPinia中的 getterVue中的计算属性几乎一样,在获取state值之前做一些逻辑处理,getter中的值有缓存特性,如果值没有改变,多次使用也只会调用一次.

//Vuex引入:
import { useStore } from "vuex";
//Pinia引入:
import { mainStore } from "../../store/piniaIndex";
<script>
export default {
  setup() {
    //storeVuex
    const storeVuex = useStore()
    storeVuex.getters.handleCount();
  
    //PiniaStore
    const storePinia = mainStore();
    storePinia.handleCount();
  }
<script>

总结

  • PiniaVue2/3的兼容性更好,支持TypeScript
  • PninaVuex的替代版,符合Vue3组合式API,让代码扁平化
  • Pnina抛弃传统的mutation,只有stategetteraction,简化状态管理
  • 代码简洁明了

作者:FeyeW 链接:https://juejin.cn/post/7149553176227053605 来源:稀土掘金