Pinia的使用(以vue3+ts+vite为例)

news2024/11/17 3:49:01

文章目录

    • Pinia
      • 1. 安装
      • 2. 引入vue3
      • 3. 初始化store仓库
      • 4. 修改state
      • 5. 解构store
      • 6. store中的方法和计算属性(actions、getters)
      • 7. API
        • 7.1 $reset
        • 7.2 $subscribe 和 $onAction
      • 8. 插件
        • 案例:持久化插件

Pinia

Pinia官方文档

Pinia GitHub地址

1. 安装

yarn add pinia
# 或者使用 npm
npm install pinia

2. 引入vue3

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const store = createPinia()
const app = createApp(App)

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

3. 初始化store仓库

在这里插入图片描述

定义一个名称枚举(store-name.ts)

export enum Names {
  TEST = 'test',
  USER = 'user'
}

定义store

import { defineStore, storeToRefs } from 'pinia'
import { Names } from './store-name'

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
// defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。

// options API
export const useTestStore = defineStore(Names.TEST, {
  state: () => ({ name: '多多', count: 1 }),
  getters: {  // computed 修饰的一些值
    double: (state) => state.count * 2,
  },
  actions: {  // methods 同步异步 提交state
    increment() {
      this.count++
    },
  }
})

interface User {
  name: string
  age: number
}

// setup
export const useUserStore = defineStore(Names.USER, () => {
  // setup中:ref等于state  computed等于getters methods等于actions
  const name = ref('图图')
  const age = ref(18)
  const userMsg = computed(() => {
    return `我叫${name.value},我${age.value}岁了`
  })
  const setUser = (user: User) => {
    name.value = user.name
    age.value = user.age
  }

  return { name, age, userMsg, setUser }
})

使用store

<template>
  <div>USER:{{ user.name }} --- {{ user.age }} --- {{ user.userMsg }}</div>
</template>

<script setup lang="ts">
import { useUserStore } from '@/store'

const user = useUserStore()

</script>

4. 修改state

修改state的几种方法:

  1. 直接修改: user.name = '改变了'
  2. $patch(): user.$patch({name: 'patch对象改变'})
  3. $patch((state)=>{}): 好处是可以写修改逻辑, user.$patch((state)=>{ state.name = 'patch工厂函数' })
  4. $state: 不常用,需要修改全部值,不然ts类型报错, user.$state = {name: 'state改变', age: 18}
  5. action: 使用store内的方法 user.setUser({ name: '多多', age: 20 })
interface User {
  name: string
  age: number
}

export const useUserStore = defineStore(Names.USER, () => { // setup
  const name = ref('图图')
  const age = ref(18)
  
  const setUser = (user: User) => {
    !!user.name && (name.value = user.name)
    !!user.age && (age.value = user.age)
  }

  return { name, age, userMsg, setUser }
})

5. 解构store

pinia中,state相当于reactive不能直接解构,会失去响应性,pinia提供了 storeToRefs() 使其解构响应性不丢失

import { storeToRefs } from 'pinia';

const user = useUserStore()
const { name, age } = storeToRefs(user)

6. store中的方法和计算属性(actions、getters)

同步异步方法都可以,也可以进行互相调用

interface User {
  name?: string
  age?: number
}

const asyncData = () => {
  return new Promise<User>((resolve, reject) => {
    setTimeout(()=>{
      resolve({name: '异步', age: 20})
    },2000)
  })
}

export const useUserStore = defineStore(Names.USER, () => { // setup
  // setup中:ref等于state  computed等于getters methods等于actions
  const name = ref('图图')
  const age = ref(18)

  const ageMsg = computed<string>(()=>{
    return `${age.value}岁了`
  })

  const userMsg = computed<string>(() => {
    return `我叫${name.value}${ageMsg.value}`
  })

  // 同步
  const setUser = (user: User) => {
    !!user.name && (name.value = user.name)
    !!user.age && (age.value = user.age)
  }
  
  // 异步
  const asyncSetUser = async () => {
    const res = await asyncData()
    setUser(res)
  }


  return { name, age, userMsg, setUser, asyncSetUser }
})

7. API

7.1 $reset

重置state初始值,注意只在options API有用,setup函数模式报错

const test = useTestStore()
...
test.$reset()

7.2 $subscribe 和 $onAction

  1. $subscribestate 改变时会调用此函数
const user = useUserStore()

...
user.$subscribe((args, state) => {
  console.log('args, state :>> ', args, state)
},{
  detached: true, // 组件销毁也会监听
  // 与watch类似
  deep: true,
  flush: 'post'
})

在这里插入图片描述

  1. $onAction:调用方法时会调用此函数
// 第二个参数为true时,组件销毁也会监听
// 第二个参数为true时,组件销毁也会监听
// args.after 可以清除一些副作用函数
// args 方法传递的参数
user.$onAction((args) => {
  args.after(() => {
    console.log('after')
  })
  console.log('args :>> ', args)
}, true)

在这里插入图片描述

8. 插件

插件详情

由于有了底层 API 的支持,Pinia store 现在完全支持扩展。以下是你可以扩展的内容:

  • store 添加新的属性
  • 定义 store 时增加新的选项
  • store 增加新的方法
  • 包装现有的方法
  • 改变甚至取消 action
  • 实现副作用,如本地存储
  • 仅应用插件于特定 store

插件是通过 pinia.use() 添加到 pinia 实例的。

import { createPinia } from 'pinia'
import { PiniaPluginContext } from 'pinia'

// 在安装此插件后创建的每个 store 中都会添加一个名为 `secret` 的属性。
// 插件可以保存在不同的文件中
// Pinia 插件是一个函数,可以选择性地返回要添加到 store 的属性。它接收一个可选参数,即 context。
function SecretPiniaPlugin(context: PiniaPluginContext) {
  context.pinia // 用 `createPinia()` 创建的 pinia。 
  context.app // 用 `createApp()` 创建的当前应用(仅 Vue 3)。
  context.store // 该插件想扩展的 store
  context.options // 定义传给 `defineStore()` 的 store 的可选对象。
  // ...
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
// 将该插件交给 Pinia
pinia.use(SecretPiniaPlugin)

// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

案例:持久化插件

mian.ts

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import persistPlugins from '@/store/plugins/persist'
import { Names } from '@/store/store-name'

const app = createApp()
const store = createPinia()

store.use(persistPlugins({
  key: 'wgh',
  include: [Names.USER],	// 默认为空,全部持久化
  storage: sessionStorage  // 默认 localStorage
}))

...
app.mount('#app')

persist.ts

import { PiniaPluginContext } from "pinia";

type Options = {
  key?: string
  storage?: Storage
  include?: string[]
}

// 默认key
const __defaultKey__ = 'wdd'

// 存储数据
const setStorage = (key: string, value: any, storage: Storage): void => {
  storage.setItem(key, JSON.stringify(value))
}

// 获取数据
const getStorage = (key: string, storage: Storage) => {
  const result = storage.getItem(key) ? JSON.parse(storage.getItem(key) as string) : {}
  return result
}

// setup 单个state是ref,所以不能直接使用toRaw
export function toRaws<T extends object>(object: T) {
  const ret: any = Array.isArray(object) ? new Array(object.length) : {}
  for (const key in object) {
    ret[key] = toRaw(object[key])
  }
  return ret
}

// 利用函数柯里化接收用户传参
const persistPlugins = (options: Options) => {
  return (context: PiniaPluginContext) => {
    const { store } = context
    const storage = options?.storage || localStorage
    console.log('storage :>> ', storage);
    const data = getStorage(`${options?.key ?? __defaultKey__}-${store.$id}`, storage)
    store.$subscribe((args, state) => {
      if (!options?.include?.length || options.include?.includes(args.storeId)) {
        setStorage(`${options?.key ?? __defaultKey__}-${store.$id}`, toRaws(store.$state), storage)
      }
    })
    return { 
      ...data
    }
  }
}

export default persistPlugins

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode vscode-pandoc插件将中文Markdown转换为好看的pdf文档(使用eisvogel模板)

Markdown的使用经常需要转变其他格式&#xff0c;在VSCode里有个很好用的插件&#xff1a;vscode-pandoc&#xff0c;先进行下载。 打开设置&#xff08;左下角的小齿轮&#xff09; 输入pandoc 在HTML Opt String中粘贴入&#xff1a; -s -t html5可将Markdown转换输出HTML。…

STL-----map的常见使用

1&#xff0c;MAP的说明Map是STL的一个关联容器&#xff0c;它提供一对一&#xff08;其中第一个可以称为关键字&#xff0c;每个关键字只能在map中出现一次&#xff0c;第二个可能称为该关键字的值&#xff09;的数据 处理能力&#xff0c;由于这个特性&#xff0c;它完成有可…

3.1.8 多态

文章目录1.概念2.特点3.入门案例练习4 多态的好处5 多态的使用6 练习&#xff1a;多态成员使用测试7 拓展7.1 综合案例7.2 多态为了统一调用标准7.3 静态变量和实例变量的区别7.4 向上转型和向下转型1.概念 多态是面向对象程序设计&#xff08;OOP&#xff09;的一个重要特征&…

【数据结构初阶】第三篇——单链表

链表的概念及其结构 初始化链表 打印单链表 增加结点 头插 尾插 在给定位置之前插入 在给定位置之后插入 删除结点 头删 尾删 删除给定位置的结点 查找数据 修改数据 链表的概念及其结构 基本概念 链表是一种物理存储结构上非连续&#xff0c;非顺序的存储结构&a…

盘点保护隐私安全的浏览器,密码锁屏这个功能,真香

在互联网时代&#xff0c;大家都比较关心自己的隐私安全。一些互联网公司和在线客服会跟踪用户的在线活动&#xff0c;收集用户的个人信息&#xff0c;有时候甚至因为个人的不良习惯导致信息泄露&#xff0c;因此选择隐私和安全性好的浏览器尤其重要。下面给大家介绍隐私安全做…

大数据技术架构(组件)11——Hive:日期函数

1.4.5、日期函数1.4.5.1、from_unixtimeselect from_unixtime(1638602968),from_unixtime(1638602968,yyyy-MM-dd HH:mm:SS),from_unixtime(1638602968,yyyy-MM-dd);1.4.5.2、unix_timestampselect unix_timestamp();1.4.5.3、to_dateselect to_date(2021-12-04 2021-12-04 15:…

【授权与认证】OAuth 2.0 和 OIDC 的异同点

开发者谈 | OAuth 2.0 和 OIDC 协议的关系&#xff1f;&#xff08;内含必看案例&#xff09; 【Web 安全】CSRF 攻击详解 OAuth 2.0 OAuth 2.0 的一个简单解释OAuth 2.0 的四种方式什么是Oauth2.0&#xff0c;Oauth2.0的四种授权模式 简单说&#xff0c;OAuth 就是一种授权…

【前端】Vue项目:旅游App-(16)home+hooks:窗口滚动到底部动态加载新数据、抽取到hook

文章目录目标过程与代码监听窗口的滚动窗口上事件监听的移除封装到一个hook回调函数法&#xff08;不推荐&#xff09;返回值法&#xff08;推荐&#xff09;效果总代码修改或添加的文件hooks的useScrollhome-content参考本项目博客总结&#xff1a;【前端】Vue项目&#xff1a…

git 使用tag

文章目录概述示例创建标签 tag查看tag删除本地标签推送标签git 根据tag创建分支回退到tag参考概述 常常为发布上线某个版本打上一个标签&#xff0c;表示这是什么版本&#xff0c;这样后续找起来就很方便。 如果没有标签只能通过commit历史去查找&#xff0c;而且commit版本显…

每日学术速递1.30

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 更多Ai资讯&#xff1a; 今天带来的arXiv上最新发表的3篇文本图像的生成论文。 Subjects: cs.LG、cs.Cv、cs.AI、cs.CL 1.StyleGAN-T: Unlocking the Power of GANs for Fast Large-Scale Text-to-Im…

Spire.Doc for Java v11.1.1 Patch

Spire.Doc for Java是一个专业的 Word API&#xff0c;它使 Java 应用程序能够在不依赖 Microsoft Word 的情况下创建、转换、操作和打印 Word文档。 通过使用这个多功能库&#xff0c;开发人员能够毫不费力地处理大量任务&#xff0c;例如插入图像、超链接、 数字签名、书签和…

Mybatis-plus(下)

一&#xff0c;乐观锁可参考官方文档&#xff1a;https://baomidou.com/pages/0d93c0/场景&#xff1a;当两个工作人员同时去处理一条投诉工单的时候当两个人一起点开了投诉工单详情 并一起编辑处理 随后同时反馈给用户时 此时就会出现矛盾 当系统正常 没有bug的时候 是会出现两…

SpringCloud_Sleuth分布式链路请求跟踪

目录一、概述1.为什么会出现这个技术&#xff1f;需要解决哪些问题&#xff1f;2.是什么3.解决二、搭建链路监控步骤1.zipkin2.服务提供者3.服务消费者&#xff08;调用方&#xff09;4.依次启动eureka7001/8001/805.打开浏览器访问&#xff1a; http://localhost:9411一、概述…

网络流量监控对DMS系统排错分析案例

背景 DMS系统是某汽车集团的经销商在线系统&#xff0c;是汽车集团的重要业务系统。本次分析重点针对DMS系统性能进行分析&#xff0c;以供安全取证、性能分析、网络质量监测以及深层网络分析。 该汽车总部已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和…

Qt扫盲-QDebug理论总结

QDebug理论使用总结一、概述二、使用1. 基础使用2. 格式化选项3.将自定义类型写入流一、概述 每当开发人员需要将调试或跟踪信息写入设备、文件、字符串或控制台时&#xff0c;都会使用QDebug。这个就可以方便我们调试&#xff0c;基本上Qt所有的内容都能通过调试打印出来&…

14.重载运算与类型转换

文章目录重载运算与类型转换14.1基本概念直接调用一个重载的运算符函数某些运算符不应该被重载使用与内置类型一致的含义赋值和复合赋值运算符选择作为成员或者非成员14.2输入和输出运算符14.2.1重载输出运算符<<输出运算符尽量减少格式化操作输入输出运算符必须是非成员…

智能家居之主机---计划筹备

智能家居之主机---计划筹备前言绪言前期构思硬件平台结构平台前言 绪言 感觉有一年多没发过文章了&#xff0c;这一年多太忙了&#xff0c;来到新的公司后要学的太多了&#xff0c;代码风格&#xff0c;架构&#xff0c;操作系统&#xff0c;各种通讯协议&#xff0c;伺服驱动…

解决问题的方法论

概述 解决问题的能力是职场中最重要的能力之一&#xff0c;如何逻辑清晰、效率满满的解决问题&#xff0c;可参考以下4个步骤。 一、准确的界定问题 找出真正的问题。 准确的界定问题&#xff0c;避免被表面现象所迷惑。 《麦肯锡工具》中&#xff0c;给出一个标准的步骤&am…

【数据手册】LM1117L3芯片的使用

1.特征 可调或固定输出1A输出电流低损耗&#xff0c;在1A输出电流时最大电压为1.3V0.04%的线路调节0.2%负载调节100%热极限燃烧快速瞬态响应 2.描述 LM1117系列正可调和固定调节器设计提供1A高电流效率。所有内部电路设计为低至1.3V输入输出差。片内微调将参考电压调整为1% 3…

【微服务】RabbitMQSpringAMQP消息队列

&#x1f6a9;本文已收录至专栏&#xff1a;微服务探索之旅 &#x1f44d;希望您能有所收获 一.初识MQ (1) 引入 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;可以立即得到响应&#xff0c;但是你却不能跟多个人同时通话。 异…