经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue3探索——pinia高阶使用
来源:cnblogs  作者:前端cry  时间:2023/9/18 9:04:30  对本文有异议

以下是一些 Pinia 的其他高阶功能:

  1. storeToRefs():响应式解构仓库,保证解构出来的数据是响应式的数据。
  2. 状态持久化:Pinia 并没有内置的状态持久化功能,但你可以使用第三方库或自定义插件来实现状态的持久化。例如,你可以使用 localStorage 或 sessionStorage 来将状态保存在客户端。
  3. 插件系统:Pinia 允许你编写自定义插件,以扩展和定制状态管理功能。你可以创建插件来处理持久化、日志记录、错误处理等任务,以适应你的特定需求。

响应式解构storeToRefs()

背景

在组件中访问仓库state,getters,actions时,总要在变量名前面带上仓库实例名,像下面这样,每个变量都这么写就会显得很代码很累赘。而直接解构的话,数据会丢失响应式。

  1. import store from '@/store/senior.ts';
  2. const userStore = store();
  3. // 访问state中的money,需要敲上'userStore.'
  4. console.log(userStore.money);
  5. // 直接解构,会丢失响应式
  6. const { age } = userStore;

使用

在组件中使用storeToRefs可以保证解构出来的数据是响应式的数据。

  1. import { storeToRefs } from 'pinia';
  2. // ......
  3. const { age } = storeToRefs(userStore);
  4. console.log(age.value); // 别忘了 .value 这个小尾巴~

状态持久化插件pinia-plugin-persist

pinia本身不提供持久化存储状态,这里我们使用插件pinia-plugin-persist 进行持久化存储。

npm: pinia-plugin-persist

Pinia Plugin Persist

1-安装

  • yarn
  1. yarn add pinia-plugin-persist
  • npm
  1. npm install pinia-plugin-persist
  • pnpm
  1. pnpm add pinia-plugin-persist

2-配置

src/store/index.ts中进行pinia的配置

  1. import { createPinia } from 'pinia';
  2. // 1-引入包
  3. import piniaPersist from 'pinia-plugin-persist';
  4. const pinia = createPinia();
  5. // 2-使用pinia-plugin-persist插件
  6. pinia.use(piniaPersist);
  7. export default pinia;

src/main.ts

  1. // ......
  2. import { createApp } from 'vue';
  3. import App from './App.vue';
  4. // 1-引入pinia配置文件
  5. import pinia from '@/store/index.ts';
  6. const app = createApp(App);
  7. // 2-使用pinia配置文件
  8. app.use(pinia);
  9. app.mount('#app');

打开项目下的ts配置文件tsconfig.json

  1. {
  2. "compilerOptions": {
  3. "types": [
  4. "pinia-plugin-persist"
  5. ]
  6. },
  7. }

3-使用

组合式API写法

在仓库中的defineStore() 第三个参数进行配置。

src/store/senior.ts

  1. export const store = defineStore(
  2. 'senior',
  3. () => {
  4. const age = ref(18);
  5. const money = ref(100);
  6. return {
  7. age,
  8. money
  9. }
  10. },
  11. {
  12. persist: {
  13. enabled: true, // 启用持久化存储
  14. // 存储策略,可以配置多个存储策略,一条策略对应一个存储
  15. strategies: [
  16. {
  17. key: 'local_age', // 存储的key名
  18. storage: localStorage, // 存储方式
  19. paths: ['money'] // 指定state字段进行存储
  20. },
  21. {
  22. key: 'session_age',
  23. storage: sessionStorage
  24. }
  25. ]
  26. }
  27. }
  28. );

persist参数说明:

  • enabled:(true) 开启持久化存储。
  • strategies:(Array) 配置存储策略,一条策略对应一个存储。
    • key:(String) 存储的key名。
    • storage:(Storage) 存储方式,默认值是sessionStorage,可以是localStorage,也可以自定义存储方式。
    • paths:(Array<string>) 指定某些state字段进行存储。若不配置,默认对整个state进行存储。

选项式API写法

src/store/senior.ts

  1. export const store = defineStore('senior', {
  2. state() {
  3. return {
  4. age: 18,
  5. money: 100,
  6. }
  7. },
  8. persist: {
  9. enabled: true,
  10. strategies: [
  11. {
  12. key: 'local_age',
  13. storage: localStorage,
  14. paths: ['money']
  15. },
  16. {
  17. key: 'session_age',
  18. storage: sessionStorage
  19. }
  20. ]
  21. }
  22. })

4-自定义存储方式(cookie)

以下示例是对官方示例,进行优化的版本。

  • yarn
  1. yarn add js-cookie
  • npm
  1. npm install js-cookie
  • pnpm
  1. pnpm add js-cookie

(2)定义仓库

src/store/senior.ts

  1. import { defineStore } from "pinia";
  2. import { ref } from 'vue';
  3. import Cookies from 'js-cookie';
  4. // 1-定义存储方式cookiesStorage
  5. const cookiesStorage: Storage = {
  6. setItem(key, state) {
  7. // 判断是值,还是整个仓库
  8. const isKey = Object.keys(JSON.parse(state)).includes(key);
  9. if (isKey) {
  10. // 值
  11. return Cookies.set(key, JSON.stringify(JSON.parse(state)[key]), { expires: 3 });
  12. }
  13. else {
  14. // 仓库state
  15. return Cookies.set(key, state, { expires: 3 });
  16. }
  17. },
  18. getItem(key) {
  19. // 判断键值是否存在
  20. let value = Cookies.get(key);
  21. // 这里应该需要判断是整个仓库state、还是值
  22. // 但目前没有发现较好的判断方法,所以persist必须配置paths
  23. /*
  24. // 如果是整个仓库state
  25. return value;
  26. */
  27. return value ?
  28. // 存在,返回对应的值(parse处理,保证和原类型一致)
  29. JSON.stringify({ [key]: JSON.parse(value) })
  30. :
  31. // 不存在,不做parse处理,防undefined报错
  32. JSON.stringify({ [key]: value });
  33. }
  34. }
  35. export const store = defineStore('senior', () => {
  36. const age = ref(123456);
  37. return {
  38. age,
  39. }
  40. }, {
  41. persist: {
  42. enabled: true,
  43. strategies: [
  44. {
  45. storage: cookiesStorage, // 2-使用cookiesStorage存储方式
  46. key: 'age',
  47. paths: ['age'] // 3-必须配置paths指定state字段,否则数据会错乱
  48. },
  49. ]
  50. }
  51. });

!!!注意:目前,根据官方文档的示例以及笔者的实践,使用cookie进行持久化存储,persist.strategies必须要配置paths 属性,即无法默认存储整个state,否则数据会出现错乱(文章中就不演示了,有兴趣的小伙伴儿可自行尝试)。

插件系统

介绍

Pinia 插件是一个函数,函数接收一个参数context(上下文对象),可以获取pinia实例、app应用等。

  1. export functionmyPiniaPlugin(context) {
  2. context.pinia // 使用 `createPinia()` 创建的 pinia
  3. context.app // 使用 `createApp()` 创建的当前应用程序(仅限 Vue 3)
  4. context.store // 插件正在扩充的 store
  5. context.options // 定义存储的选项对象传递给`defineStore()`
  6. // ...
  7. };

然后使用 pinia.use() 将此函数传递给 pinia

  1. pinia.use(myPiniaPlugin);

插件仅适用于在 将pinia传递给应用程序后创建的 store,否则将不会被应用。

功能

pinia官网描述pinia插件的功能:

  • 向 Store 添加新属性
  • 定义 Store 时添加新选项
  • 为 Store 添加新方法
  • 包装现有方法
  • 更改甚至取消操作
  • 实现本地存储等副作用
  • 适用于特定 Store
  • ……

向 Store 添加新属性

自定义插件函数返回(return)一个对象,对象中就是需要增加的属性。

src/store/index.ts中,配置pinia插件。

  1. import { createPinia } from 'pinia';
  2. import { ref } from 'vue';
  3. const pinia = createPinia();
  4. // 1-定义插件:向store增加属性
  5. const expandStore = () => {
  6. // 2-这里把需要增加的属性return出去即可
  7. return {
  8. hello: ref(123) // 在所有store上添加'hello'状态
  9. };
  10. }
  11. // 3-使用插件
  12. pinia.use(expandStore);
  13. export default pinia;

读取 Store 配置项

可以通过插件函数context.options 来获取每个store的额外配置,以便根据每个仓库的功能进行区别开发。

1-定义 Store 时添加新选项

  • 在组合式API中,defineStore() 的第三个参数就是仓库的配置项。
  • 在选项式API中,直接在defineStore() 的第二个参数(一个对象)中添加属性作为配置项。

src/store/senior.ts

组合式API

  1. import { defineStore } from "pinia";
  2. export const store = defineStore('senior',
  3. () => {
  4. return {}
  5. },
  6. {
  7. haha: {
  8. option1: '123'
  9. }
  10. }
  11. );

选项式API

  1. import { defineStore } from "pinia";
  2. export const store = defineStore('senior',
  3. {
  4. state: () => ({}),
  5. getters: {},
  6. actions: {},
  7. haha: {
  8. option1: '123'
  9. }
  10. }
  11. );

2-插件中获取每个store的选项

src/store/index.ts

  1. // 这里使用解构赋值,把options从context中解构出来
  2. const expandStore = ({ options }) => {
  3. console.log('options', options);
  4. }
  5. pinia.use(expandStore);

监听仓库变化$subscribe()$onAction()

在插件中使用 store.$subscribe()和 store.$onAction(),可以监听仓库的变化。

  1. pinia.use(({ store }) => {
  2. store.$subscribe(() => {
  3. // 在存储变化的时候执行
  4. })
  5. store.$onAction(() => {
  6. // 在 action 的时候执行
  7. })
  8. })

包装或重写现有方法

重写$reset方法

可以参考上一篇博文,重写了$reset方法:vue3探索——5分钟快速上手大菠萝pinia

  1. import { createPinia } from 'pinia';
  2. const pinia = createPinia();
  3. // 1-使用pinia自定义插件
  4. pinia.use(({ store }) => {
  5. // 2-获取最开始的State
  6. const initialState = JSON.parse(JSON.stringify(store.$state));
  7. // 3-重写$reset()方法
  8. store.$reset = () => {
  9. // 4-利用$patch()批量变更state,达到重置state的目的
  10. store.$patch(initialState);
  11. }
  12. });
  13. export default pinia;

暂时没有更多辣~

原文链接:https://www.cnblogs.com/cry0-0/p/17707386.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号