Pinia 快速上手运用

相比于Vuex 4.X而言Pinia可以很好的区分相应的Hooks不必要像Vuex 一样先调用useStore获取我们的Store。

单独的Hooks可以很好的区分我们的模块和业务,不必像Vuex中module那样调用复杂。

同时去掉了Vuex Mutations属性,正常开发中其实这个属性非常鸡肋。

两者相比,明显Pinia更适合Vue3的setup,同时更好兼容TypeScript。


前言:

在使用Pinia前需要使用对应的vue app 安装。

import { createPinia } from 'pinia'// vue app创建流程
app.use(createPinia()); // 安装pinia

 

一、声明一个Store

  

 1 import {defineStore} from 'pinia';
 2   
 3 export const useUserInfo = defineStore('userInfo', {
 4      state: () => ({
 5        name: 'lisi',
 6        age: 18,
 7      }),
 8      getters: {
 9        userName: (state) => state.name,
10        getAuthCode(state) { // 此使用方式将失去本身缓存能力  单纯作函数使用
11           return (id) => [Code];
12        }
13      },
14      actions: {
15        setName(newName) {
16          this.name = newName;
17        }
18     }    
19 }); 

可以看到在我们声明的actions中可以直接调用this.xxx 即可调用到我们的state中声明的属性,相比vuex 4.x 需要调用 commit 还是比较友好的。

建议还是使用actions

同时我们想要清除掉当前的Store可以接收其返回值并调用$reset函数。

<script setup lang="ts">
import { useUserInfo } from './store';

const userInfoStore = useUserInfo();
// 重置状态
userInfoStore.$reset();
// 改变状态
userInfoStore.$patch({name: "张三"}); // 可以传入部分的state属性,会根据传入属性更新state,但是此种修改比较低能。
userInfoStore.$patch((state) => {
  state.name = 'wangwu';
}); // 方便修改和精确调整其接受函数回调提供修改state,因为其属性为响应式的所以可以直接修改。

// 替换整个state userInfoStore.$state = {sex: 1}; // 此方式就可以替换掉当前的store的state </script>

二、调用其他的Store

其实调用其他的store非常简单,可能你已经想到了!没错,就是导入我们声明的useUserInfo;

import {defineStore} from 'pinia';
import { useUserInfo } './store';

export const useUserAuthCode = defineStore('userAuthCodes', {
    state: () => {
      userCodes: [],
    },
    actions: {
      getUserAuthCodeById(state) {
        const userStore = useUserInfo(); // 获取useInfoStore,getters中也是如此使用
        // todo 异步请求
        this.userCodes = []; // 获取到的数据
      }
    }
});

 

三、订阅监听

  (1)State的监听 store.$subscribe(callback, options);

<script steup>
import { useUserInfo } from './store';

const userInfoStore = useUserInfo();

userInfoStore.$subscribe((mutation, state) => {
   // import { MutationType } from 'pinia'
  mutation.type // 'direct' | 'patch object' | 'patch function'
  // 与 userInfoStore.$id 相同
  mutation.storeId // 'cart'
  // 仅适用于 mutation.type === 'patch object'
  mutation.payload // 补丁对象传递给 to userInfoStore.$patch()

 // 做自己需要监听的事情
});
</script>

监听事件默认绑定到当前组件实例上,组件卸载会自动移除,想要保留其状态需要设置它的options = { detatched: true }。

其特点与watch非常类似,但是$subscribe只在 patches 之后触发一次。

 

  (2) 监听actions store.$onActions(callback, boolean);

import { useUserInfo } form './store';

const userInfoStore = useUserInfo();

const unUserInfoSubscribe = userInfoStore.$onAction(({
    name, // action 的名字,
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError, // 在这个 action 抛出异常的时候,执行这个函数
}) => {
    // 如果 action 成功并且完全运行后,after 将触发。
    // 它将等待任何返回的 promise

    // 如果 action 抛出或返回 Promise.reject ,onError 将触发

}, true); // 第二位参数标识当前组件卸载后保留状态

unUserInfoSubscribe(); // 卸载监听

监听事件默认绑定到当前组件实例上,组件卸载会自动移除。

 

四、非setup的使用

import { mapState, mapActions } from 'pinia'
import { useUserInfo } from '../store'

export default {
  computed: {
    // state | getters
    // 允许访问组件内的 this.userName
    // 与从 store.userName中读取相同
    ...mapState(useUserInfo , ['userName'])
    // 与上面相同,但将其注册为 this.name
    ...mapState(useUserInfo , {
      name: 'userName',
      // 您还可以编写一个访问 store 的函数
      userAge: store => store.userName,
    })
  },
  methods: {
    ...mapActions(useUserInfo, ['setName']),
    ...mapActions(useUserInfo, {
      setUserName: 'setName',
    }),
  },
};

两个mapXXX都需要两个参数,第一个是我们定义的Store函数,第二个参数可以是数组和对象,数组中声明对应的state或actions中存在key名称,对象则可以声明自定义的key:对应声明的Key。

mapState中对象类型options还可以声明函数,接收一个store可以任意访问state中的参数。大致与vuex 3.x版本差不多。

tips: Pinia肯定也是拥有组合式的写法,语法和我们自定义Hooks是一样的,还有嵌套的Store,它的书写方式参考Getters,Actions的共享状态。

 

posted @ 2023-03-17 14:09  键盘的旋律  阅读(145)  评论(0编辑  收藏  举报