前言
在Vue的最新官网文档中,细心的小伙伴会发现Vuex已经被Pinia给代替啦,于是我翻出我之前项目将Vuex也换成了Pinia进行了对比学习。
Pinia的基本使用
安装Pinia: npm i pinia
安装Pinia数据持久化(数据持久化实现): npm i pinia-plugin-persistedstate
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: true,
count: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的使用
Vuex和Pinia中的 getter 和 Vue中的计算属性几乎一样,在获取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>
总结
-
Pinia对Vue2/3的兼容性更好,支持TypeScript -
Pnina是Vuex的替代版,符合Vue3组合式API,让代码扁平化 -
Pnina抛弃传统的mutation,只有state,getter和action,简化状态管理 -
代码简洁明了