Pinia 基本用法

500 阅读2分钟

Pinia 基本用法

官网: pinia.vuejs.org/

相对于以前的 vuex,pinia 具有以下优势

  • 更简单的写法,代码更清晰简洁,支持 composition apioptions api 语法
  • 更完善的 typescript 支持,无需创建自定义复杂的包装类型来支持 TypeScript,所有内容都是类型化的,并且 API 的设计方式尽可能利用 TS 类型推断
  • 非常轻量,只有 1kb 的大小

使用 pinia

yarn add pinia
or
npm install pinia

main.ts 中挂载 pinia

import { createPinia } from 'pinia'
import { createApp } from 'vue' import App from './app.vue'
createApp(App).use(createPinia()).mount('#app')

定义 store

store 的定义是通过 defineStore 这个函数,它需要一个唯一的名称,该名称可以作为第一个参数传递,也可以用 id 熟悉传递。

import { defineStore } from "pinia";
import { smartState } from "./types";
export const smartStore = defineStore({
  id: "smartStore",
  state: (): smartState => ({
    net_status: false,
    net_type: "wifi",
    net_link: true,
    net_icon: "icon-network_icon-3",
  }),
  actions: {
    setNetStatus(status: boolean, type: string, link: boolean) {
      this.net_status = status;
    },
  },
  getters: {
    getNetStatus(): string {
      return `net_status=${this.net_status}--net_type=${this.net_type}--net_link=${this.net_link}`;
    },
  },
});
// or
import { defineStore } from "pinia";
import { globaleMenuState } from "./types";
import { watchTvDefault } from "./config/watchTv/index";
export const globaleMenuStore = defineStore("globalMenu", {
  state: (): globaleMenuState => ({
    display: false,
    data: {
      watchTV: {
        icon: "icon-icon_watch-TV iconfont",
        langClassNameTitle: "_watchTV",
        subTree: watchTvDefault,
      },
    },
  }),
});

使用 store

import { smartStore } from "../../store/source/index";
import { storeToRefs } from "pinia";
export default defineComponent({
  name: "Home",
  setup() {
    const store = smartStore();
    console.log(store);
    // state中定义的值
    console.log(store.net_status);
    // getters
    console.log(store.getNetStatus);
    // actions
    setTimeout(() => {
      store.setNetStatus(true, "wifi", true);
    }, 2000);
    // storeToRefs
    const { net_status } = storeToRefs(store);
    const net_status_computed = computed(() => store.net_status);
    return {
      store,
      net_status,
    };
  },
});

上述代码中,useMainStore 实例化后的,我们就可以在 store 上访问 state、getters、actions 等(pinia 中没有 mutations),该 store 是一个 reactive 对象,所以不需要 “.value”,也不能对其进行解构使用,否则失去响应性(类似 props),如果需要对其进行解构使用可以使用 storeToRefs 方法或者配合 computed 方法实现。

$reset

可以通过调用 store 上$reset 的方法将状态重置为初始状态

const store = smartStore();
store.$reset();
$path

$patch 可以同时修改多个值,可以直接传入修改的对象,或者一个函数

const store = smartStore();
store.$path({
  net_status: false,
  net_link: false,
});
store.$path((state) => {
  state.net_status = false;
  state.net_link = false;
});
$subscribe 监听 state 变化

该方法的第一个参数接受一个回调函数,该函数可以在 state 变化时触发

const store = smartStore();
const subscribe = store.$subscribe((mutation, state) => {
  console.log(mutation);
  console.log(state);
});

该回调函数的两个参数其中 state 是 mainStore 实例,而 mutation 打印如下

mutation 对象主要包含三个属性

  • events : 是这次 state 改变的具体数据,包括改变前的值和改变后的值等等数据

  • storeId :是当前 store 的 id

  • type:表示这次变化是通过什么产生的,主要有三个分别是

    • “direct” :通过 action 变化的
    • ”patch object“ :通过 $patch 传递对象的方式改变的
    • “patch function” :通过 $patch 传递函数的方式改变的

取消订阅

可以通过调用 store.subscribe返回的值(即上方示例的subscribe变量)可以停止订阅,也可不取消订阅,当组件被卸载时,它们将被自动取消。如果要在组件卸载后保留它们,需要再subscribe返回的值(即上方示例的 subscribe 变量)可以停止订阅,也可不取消订阅,当组件被卸载时,它们将被自动取消。如果要在组件卸载后保留它们,需要再subscribe 中传第二个参数{ detached: true },detached 默认为 false。

const subscribe = store.$subscribe(
  (mutation, state) => {
    console.log(mutation);
    console.log(state);
  },
  { detached: true }
);

getter

getters 属性的值是一个函数,当该函数是箭头函数时返回参数 state,当 getters 的值是普通函数时,可以通过 this 访问整个 store 实例。

getters: {
    getNetStatus1:(state):string=>
      `net_status=${state.net_status}--net_type=${state.net_type}-- net_link=${state.net_link}`
    ,
    getNetStatus():string {
      return `net_status=${this.net_status}--net_type=${this.net_type}`
}
访问 getters
const store = smartStore();
// getters
console.log(store.getNetStatus1);
console.log(store.getNetStatus);

action

action 支持同步或异步,action 定义的函数可以是普通函数从而可以通过 this 访问整个 store 实例,同时该函数可以传入任意参数并返回任何数据。

actions: {
    // 同步
    setNetStatus(status:boolean,type:string,link:boolean) {
      this.net_status = status;
    },
    // 异步
    async getRpcNetworkStatus(){
        rpc_api.NetworkStatus().then((res)=>{
            this.net_status = res.status;
        })
    }
}

调用 action

const store = smartStore();
store.setNetStatus(true, "wifi", true);
监听订阅 action

通过 store.$onAction(),可以监听 action 的动作及结果等

该函数可以接收一个回调函数作为参数,回调函数的参数中有五个属性,具体如下

const onAction = store.$onAction(
  ({
    name, // action 函数的名称
    store, // store 实例,这里是 store
    args, // action 函数参数数组
    after, // 钩子函数,在action函数执行完成返回或者resolves后执行
    onError, // 钩子函数,在action函数报错或者rejects后执行
  }) => {
    console.log(`action 函数的名称===${name}`);
    console.log(`store 实例`, store);
    console.log(`action 函数参数数组`, args);
    after((result) => {
      console.log("$onAction after函数", result);
    });
    onError((error) => {
      console.log("错误捕获", error);
    });
  }
);
取消订阅

onAction默认在所在组件卸载时会被自动删除,可以通过传递第二个参数true,默认为false,组件卸载时,订阅依然有效,也可通过调用store.onAction 默认在所在组件卸载时会被自动删除,可以通过传递第二个参数 true,默认为false,组件卸载时,订阅依然有效,也可通过调用 store.onAction 返回的值来手动停止订阅。

const onAction = store.$onAction(caballback,true);
onAction();

pinia 插件

可以通过 pinia.use()方法,添加新属性、添加新选项、添加新方法等。

import { createPinia } from "pinia";
const pinia = createPinia();
pinia.use(() => ({
  env: "dev",
}));