vue3-pinia

119 阅读1分钟
  • 可替代vuex的插件

例子

import { defineStore } from 'pinia';
import { store } from '@/store';
/**
 * 各种需共享的临时数据
 */
 
const recovery = {
  device: { tab: 'device', orderId: '', status: '' },
  log: { tab: 'log', orderId: '', assetId: '' },
};

const orderPhy = {
  delivery: { tab: 'delivery', orderId: '' },
};

type User = {
  name: string;
  age: number;
};

const result: User = {
  name: 'menffy2',
  age: 999,
};

const Login = (): Promise<User> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        name: 'menffy3',
        age: 999,
      });
    }, 2000);
  });
};

export const shareValueStore = defineStore('shareValue', {
  state: () => ({
    recovery,
    orderPhy,
    current: 1,
    name: 'menffy',
    user: <User>{},
  }),
  
  // computed修饰一些值
  getters: {
    recoveryDeviceData: (state) => {
      return state.recovery.device;
    },
    recoveryDeviceLogData: (state) => {
      return state.recovery.log;
    },
    orderPhyDeliveryData: (state) => {
      return state.orderPhy.delivery;
    },
    newVal(): string {
      return `$-${this.name}-${this.getUserAge}`;
    },
    getUserAge(): number {
      return this.user.age;
    },
  },
  // methods 可以做同步或异步操作,提交state
  actions: {
    // 同步
    setRecovery(choice, data) {
      if (choice === 'device') {
        this.recovery.device = data;
      } else {
        this.recovery.log = data;
      }
    },
    
    setOrderPhy(data) {
      this.orderPhy.delivery = data;
    },
    
    setCurrent(num: number) {
      this.current = num;
    },
    
    setUser() {
      this.user = result;
    },
    // 异步
    async setAsyncUser() {
      this.user = await Login();
      this.setName('menffy4');
    },
    
    setName(name: string) {
      this.name = name;
    },
  },
});

// 可以不要的
export function getShareValueStore() {
  return shareValueStore(store);
}

使用

<template>
    <div>
        <div>pinina</div>
        <div>直接读取store</div>
        <div>{{ share.current }}</div>
        <div>{{ share.name }}</div>
        <div>{{ share.user }}</div>
        <div>getter: {{ share.newVal }}</div>
        <div>解构读取store</div>
        <div>{{ current }}</div>
        <div>{{ name }}</div>
        <t-button @click="onChange">change</t-button>
        <t-button @click="reset">reset</t-button>
    </div>
</template>

<script setup lang="ts">
import { useShareValueStore } from '@/store';
import { storeToRefs } from 'pinia';

const share = shareValueStore();

// store解构
const { current, name } = storeToRefs(share);

const onChange = () => {
    console.log("五种方式修改state,具体逻辑可参见下方");
};

</script>

五种方式修改state

1、直接修改
const onChange = () => {
  share.current++;
  share.name = '123';
};
2、$patch批量修改
const onChange = () => {
  console.log('onChange');
  share.$patch({
    current: 123,
    name: '123',
  });
};
3、$patch批量修改
  • 工厂函数形式,可以在内部实现逻辑
const onChange = () => {
  share.$patch((state) => {
    state.current = 3;
    state.name = 'no3';
  });
};
4、$state
  • 弊端:必须修改整个对象,即state里定义的所有对象都必须修改,比较少用
const onChange = () => {
  share.$state = {
    current: 4,
    name: 'no4',
  };
};
5、defineStore里定义action动作
const onChange = () => {
  // 同步
  share.setCurrent(5);
  // 异步
  // share.setAsyncUser();
};

pinia解构store

  • 在pinia里是不可以直接解构的,会使其失去响应性
  • 使用官方提供api解构即可,原理与toRefs类似
import { useShareValueStore } from '@/store';
import { storeToRefs } from 'pinia';

const share = useShareValueStore();

const { current, name } = storeToRefs(share);

const onChange = () => {
    // 直接对store的变量做修改,同时影响解构的值和store里的值
    // share.current++;
    
    // 对解构出来的变量做修改,同时影响解构的值和store里的值
    current.value++;
};

image.png

实例的其他API

$reset 重置
// 修改值
const onChange = () => {
    share.setUser();
};

// 重置为初始值
const reset = () => {
  share.$reset();
};
$subscribe 订阅
// 修改值
const onChange = () => {
    share.setUser();
};

// 订阅
// 任何一个值有变化都会被捕捉到,类似watch
share.$subscribe((args, state) => {
  console.log('args====>', args);
  console.log('state====>', state);
},
// 参数和watch类似
{
  detached: true, // true表示,当前组件就算被销毁了,也要继续监听
  deep: true,  // 递归监听
  flush: 'post',
},
);

订阅输出: image.png

$onAction 监听
// 修改值
const onChange = () => {
    // 参数也会被捕获到
    share.setName('otherName');
};

// 一调用action里的方法就会被监听到
share.$onAction((args) => {
  args.after(() => {
    console.log('after,清除副作用,"args-action"之后才会执行');
  });
  console.log('args-action====>', args);
}, true);  // 这里的true表示,当前组件就算被销毁了,也要继续监听

image.png