likes
comments
collection
share

pinia(2.0.34) 最新使用指南与持久化缓存

作者站长头像
站长
· 阅读数 14

一、特点

  1. 完整的 ts 支持

  2. 三大核心:state(存储的值),getters(计算属性),actions也可支持同步(改变值的方法,支持同步和异步)

  3. 与vuex相比,去除了mutations(actions也可支持同步)和modules(只有store之间的互相引用)

二、安装

yarn add pinia

三、使用

1. 创建 pinia 实例

新建 store/index.ts(src目录下新建store文件夹,并创建index.ts文件)

import { createPinia } from 'pinia';

const store = createPinia();

export default store;

2. 在 main.js 中引用

import { createApp } from 'vue';
import App from './App.vue';
import store from './store';

const app = createApp(App);

app.use(store);
app.mount('#app');

3. 创建 store

新建store/user.ts

import { defineStore } from 'pinia';

// defineStore 第一个参数是id,必需且值唯一
export const useUserStore = defineStore('user', {
  //state返回一个函数,防止作用域污染
  state: () => {
    return {
      userInfo: {
        name: 'zhangsan',
        age: 23,
      },
      token: 'S1',
    };
  },
  getters: {
    newName: (state) => state.userInfo.name + 'vip',
  },
  actions: {
    //更新整个对象
    updateUserInfo(userInfo: { name: string; age: number }) {
      this.userInfo = userInfo;
    },
    //更新对象中某个属性
    updateAge(age: number) {
      this.userInfo.age = age;
    },
    //更新基础数据类型
    updateToken(token: string) {
      this.token = token;
    },
  },
});

4. 使用 store

store 是一个用 reactive 包装的对象,直接解构读取state会失去响应式,因此需要storeToRefs,它将为每一个响应式属性创建引用;需通过 .value 读取解构出来的值

<template>
  <div>
    <div>姓名:{{ userInfo.name }} 年龄:{{ userInfo.age }}</div>
    <div>token:{{ token }}</div>
    <div>getter值:{{ newName }}</div>
    <button @click="handleUser">更新用户</button>
    <button @click="handleAge">更新年龄</button>
    <button @click="handleToken">更新token</button>
  </div>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useUserStore } from '@/store/user'; //路径别名,引入store

const userStore = useUserStore();

//storeToRefs 会跳过所有的 action 属性
const { userInfo, token, newName } = storeToRefs(userStore);

//action 属性直接解构
const { updateUserInfo, updateAge, updateToken } = userStore;

const handleUser = () => {
  updateUserInfo({ name: 'lisi', age: 24 });
};

const handleAge = () => {
  //userInfo是一个ref响应式引用,需通过.value取值
  updateAge(userInfo.value.age + 1);
};

const handleToken = () => {
  updateToken('23234');
};
</script>

5. 异步 actions

除了上面展示的同步action,action也可以是异步的

新建store/list.ts

import { defineStore } from 'pinia';

const getData = () => {
  return new Promise<number>((resolve) => {
    setTimeout(() => {
      resolve(Math.random() * 100);
    }, 200);
  });
};

export const useListStore = defineStore('list', {
  state: () => {
    return {
      list: [] as number[],
    };
  },
  actions: {
    async updateList() {
      try {
        const data = await getData();
        this.list.push(data);
      } catch {
        /* empty */
      }
    },
  },
});

6. store 的相互引用

每个store可看做一个hook。相互引用即调用不同hook

新建store/userSex.ts

import { defineStore } from 'pinia';
import { useUserStore } from './user';

enum Sex {
  man = '男人',
  woman = '女人',
}

export const userSexStore = defineStore('user2', {
  state: () => {
    return {
      sex: Sex.man,
    };
  },
  actions: {
    updateSex() {
      const userStore = useUserStore();  // 引用其他store
      if (userStore.userInfo.name !== 'zhangsan') this.sex = Sex.woman;
    },
  },
});

7. 路由钩子中使用store

使用store的前提是保证pinia已被注册

import { useUserStore } from '@/store/user';

router.beforeEach((to, from) => {
  // 这样做是可行的,因为路由器是在其被安装之后开始导航的,
  // 而此时 Pinia 也已经被安装。
  const userStore = useUserStore();
  if (!userStore.token && to.path !== "/login") {
    return "/login";
  }
});

四、数据持久化

1. 安装插件

yarn add pinia-plugin-persistedstate

2. 引用插件

修改 store/index.ts

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

const store = createPinia();

store.use(piniaPluginPersistedstate); // 使用持久化插件

export default store;

3. 在store模块中启用持久化

在user.ts中启用:添加persist配置项

import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
  state: () => ({
    ...
  }),
  getters: { ... },
  actions: { ... },
    
  // 开始数据持久化
  persist: true,
})

当更新state值时,会默认存储到localStorage中

4. 修改key与存储位置

默认存储到localStorage的key值就是store模块id值。可以修改key值和存储位置

  //将persist: true,改为
  persist: {
    key: 'storekey', // 修改存储的键名,默认为当前 Store 的 id
    storage: window.sessionStorage, // 存储位置修改为 sessionStorage
  },

5. 自定义要持久化的字段

默认会将store中的所有字段都缓存,可以通过paths点符号路径数组指定要缓存的字段

persist: {
    paths: ['userInfo.name'], //存储userInfo的name
  },

欢迎关注:之后文章会首发在云在前端公众号,未经许可禁止转载!