vue3

pinia

# 0. 安装

 npm install pinia --save
 // or
 npm i pinia -S

# 1. 介绍 3 种使用方式

import { defineStore } from 'pinia';

// options API模式
export const usePersonStore = defineStore('person', {
  state: () => {
    return {
      name: '人类'
    };
  },
  actions: {
    updateName(newName) {
      this.name = newName;
    }
  },
  getters: {
    // getters基本与Vue的计算属性一致
    getFullName() {
      return 'Full' + this.name;
    }
  }
});

// 对象形式
export const useTeacherStore = defineStore({
  id: 'teacher',
  state: () => {
    return {
      name: '老师'
    };
  },
  actions: {
    updateName(newName) {
      this.name = newName;
    }
  },
  getters: {
    getFullName() {
      return 'Full' + this.name;
    }
  }
});

// setup模式
import { computed, ref } from 'vue';
export const useStudentStore = defineStore('student', () => {
  const name = ref('学生');

  function updateName(newName) {
    name.value = newName;
  }

  const getFullName = computed(() => 'Full' + name.value);

  return { name, updateName, getFullName };
});

# 2. 数据持久化 pinia-plugin-persist

2.1 pinia-plugin-persist 最新版本为 1.0.0 ;配套的 pinia 版本为>=2.0.0 && < 3.0.0


npm i pinia-plugin-persist -S
// 在 src/store/index.js 中引入 pinia-plugin-persist 插件:
import { createPinia } from 'pinia';
import piniaPluginPersist from 'pinia-plugin-persist';

const pinia = createPinia();
pinia.use(piniaPluginPersist);

export default pinia;
// 在对应的 src/store/info.js 中开启缓存:
import { defineStore } from 'pinia';
import { useOtherStore } from './other';

export const useInfoStore = defineStore('info', {
  state: () => {
    return {
      name: '橙某人',
      age: 18
    };
  },
  getters: {
    getHobby() {
      return this.name;
      // return useOtherStore().hobby;
    }
  },
  persist: {
    enabled: true, // 开启缓存
    strategies: [
      {
        key: 'infoStore', // 修改缓存的key
        storage: localStorage, // 指定localStorage作为缓存
        paths: ['name'] // 只缓存name
      }
    ]
  }
});

2.2. 使用

<script setup>
import { storeToRefs } from 'pinia';
import useFormInfoStore from '@/store/formInfo';
import { readonly } from 'vue';
const formInfoStore = useFormInfoStore();

// 解构出state
const { age, name } = storeToRefs(formInfoStore);

// 1. **因为直接修改state中的属性;不建议这么做,很难知道在哪改了数据**
formInfoStore.age++; // 19
// 解决方案:
const readonlyStore = readonly(formInfoStore);
readonlyStore.age++; // 这样就会报错,提示不能修改只读的对象

// 2 .$reset 重置状态,将状态重置成为初始值
formInfoStore.$reset();
console.log(formInfoStore.age); // 18

// 3.$patch 支持对state对象的部分批量修改
formInfoStore.$patch({
  name: 'hello Vue',
  age: 198
});

// 4.$state 通过将其 $state 属性设置为新对象来替换 Store 的整个状态
formInfoStore.$state = {
  name: 'hello Vue3',
  age: 100,
  gender: '男'
};

// 4.$subscribe 订阅store中的状态变化
formInfoStore.$subscribe(
  (mutation, state) => {
    // 监听回调处理
  },
  {
    detached: true // 💡如果在组件的setup中进行订阅,当组件被卸载时,订阅会被删除,通过detached:true可以让订阅保留
  }
);
</script>

# 3. 数据持久化 pinia-plugin-persistedstate

3.1 src/store/index.js

import { createPinia } from 'pinia';
import piniaPluginPersist from 'pinia-plugin-persistedstate';

const pinia = createPinia();
pinia.use(piniaPluginPersist);

export default pinia;

3.2 src/store/info.js

import { defineStore } from 'pinia'
interface UserState {
  readonly name: string
  id: number | null
}

export const useStore = defineStore('user', {
  state: () => ({
    name: 'zhangsan',
    id: null,
  }),
  getters: {
    getName(): string {
      return this.name
    },
  },
  actions: {
    setName(newName: string) {
      // this.name = newName
      ;(this as { name: string }).name = newName
    },
  },
  persist: {
    storage: localStorage,
    pick: ['name'],
  },
})

3.3 使用

import { useStore } from '@/store/modules/user.ts'
import { storeToRefs } from 'pinia'
const _useStore = useStore()
const readonlyStore = readonly(_useStore)

readonlyStore.name = '王五'  // 不能修改只读的对象,警告报错且不会更新数据

readonlyStore.setName('李11')

# 4. $onAction() 可以使用 store.$onAction() 订阅 action 及其结果。传递给它的回调在 action 之前执行。 after 处理 Promise 并允许您在 action 完成后执行函数,onError 允许您在处理中抛出错误。

const unsubscribe = formInfoStore.$onAction(
  ({
    name, // action 的名字
    store, // store 实例
    args, // 调用这个 action 的参数
    after, // 在这个 action 执行完毕之后,执行这个函数
    onError // 在这个 action 抛出异常的时候,执行这个函数
  }) => {
    // 记录开始的时间变量
    const startTime = Date.now();
    // 这将在 `store` 上的操作执行之前触发
    console.log(`Start "${name}" with params [${args.join(', ')}].`);

    // 如果 action 成功并且完全运行后,after 将触发。
    // 它将等待任何返回的 promise
    after(result => {
      console.log(
        `Finished "${name}" after ${
          Date.now() - startTime
        }ms.\nResult: ${result}.`
      );
    });

    // 如果 action 抛出或返回 Promise.reject ,onError 将触发
    onError(error => {
      console.warn(
        `Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
      );
    });
  }
);

// 手动移除订阅
unsubscribe();
上次更新: