当前位置: 首页 > news >正文

vue3中pinia详解

基础概念:

Pinia 是 Vue.js 的轻量级状态管理库,允许跨组件/页面共享状态,被视为 Vuex 的替代品。

简单运用:

安装:

npm install pinia
# 或
yarn add pinia

入口文件(main.js):

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const pinia = createPinia()
const app = createApp(App)app.use(pinia)
app.mount('#app')

Store:

  • store文件名为counter.js ,文件命名要尽量简单而且知文达意。
  • Store 使用 defineStore() 定义,它需要一个id(唯一性),作为第一个参数传递,是为了方便使用浏览器插件vue devtools。
  • 将返回的函数命名为 useCounterStore ,这种 use... 的命名方式是前端程序员之间的通俗约定。
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {
//counter就是这个Store的idstate: () => ({ count: 0 }),getters: {double: (state) => state.count * 2,},actions: {increment() {this.count++},},
})

组件中使用:

import { useCounterStore } from '@/stores/counter'const counter = useCounterStore()// 直接访问 state
count: computed(() => counter.count),
console.log(counter.count)//  0
// 访问 getter
doubleCount: computed(() => counter.doubleCount)
console.log(counter.doubleCount)//  0

三个核心:

Pinia 的核心单元,包含状态(state)、getters 和 actions,他们可以简单理解为vue2中的data,computed,methods。

state:

state 是存储应用数据的地方

定义 state:

import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({count: 0,name: 'John Doe',items: [],isActive: true})
})

访问state:

import { useCounterStore } from '@/stores/counter'const store = useCounterStore()// 直接访问
console.log(store.count)//  0
  • store 被实例化后,可以直接访问 store 上的state、getters 和 actions 
  •  store 是 reactive 对象,所以在使用 getters 中的属性时,不用在getter 之后写.value。
  •  对 store 进行解构时,直接解构是会失去响应性的,需要使用 storeToRefs 来保持响应性
import { storeToRefs } from 'pinia'const counter = useCounterStore()
const { count, double } = storeToRefs(counter)

修改 state :

直接修改:
store.count++
store.name = 'Jane Doe'
使用 $patch 方法批量修改:
store.$patch({count: store.count + 1,name: 'Jane Doe'
})// 或者使用函数形式
store.$patch((state) => {state.items.push({ name: 'item' })state.isActive = false
})
使用 $state 替换整个 state:
store.$state = { count: 999, name: 'Paimon' }
重置 state 为初始值:
store.$reset()
订阅(监听) State 变化:
import { useStore } from './store'const store = useStore()// 订阅状态变化
const userSubscribe = store.$subscribe((mutation, state) => {// mutation 包含变更信息console.log('变更类型:', mutation.type)console.log('变更的 store id:', mutation.storeId)console.log('变更的 payload:', mutation.payload)// state 是变更后的完整状态console.log('新状态:', state)
})// 取消订阅
unsubscribe()

$subscribe 回调函数接收两个参数:

mutation 对象包含:

  • type: 变更类型 ('direct' | 'patch object' | 'patch function')
  • storeId: 发生变更的 store id
  • payload: 传递给 $patch 的 payload(如果是直接修改则不存在)

state: 变更后的完整 store 状态

$subscribe 还接受一个可选的 options 对象作为第二个参数:

store.$subscribe((mutation, state) => {// 回调逻辑
}, {detached: true, // 当组件卸载时保持订阅(默认为 false)deep: true,     // 深度监听(默认为 false)flush: 'post'   // 回调触发时机:'pre' | 'post' | 'sync'(默认为 'post')
})

与 watch 的区别:

  • $subscribe 会响应所有状态变更(包括 $patch 和直接修改)
  • $subscribe 提供变更的元信息(mutation 对象)
  • watch 更适合监听特定状态属性的变化

getters:

Getters 用于从 store 中派生出状态的计算属性,类似于 Vue 中的计算属性或 Vuex 中的 getters。

定义 getters:

import { defineStore } from 'pinia'export const useStore = defineStore('main', {state: () => ({count: 0}),getters: {doubleCount: (state) => state.count * 2,// 可以访问其他 gettersdoubleCountPlusOne() {return this.doubleCount + 1 // this 指向 store 实例}}
})

使用 getters:

import { useStore } from '@/stores/main'const store = useStore()// 直接访问
let doubleCount = store.doubleCount,
// 或者作为计算属性
let doubleCountPlusOne = computed(() => store.doubleCountPlusOne)

特点:

  • 类型推断:Pinia 会自动推断 getters 的类型
  • this 访问:可以通过 this 访问整个 store 实例
  • 传递参数:可以通过返回函数来接受参数
getters: {getUserById: (state) => {return (userId) => state.users.find((user) => user.id === userId)}
}
// 使用
store.getUserById(123)
  • 访问其他 store:可以在 getter 中访问其他 store
import { useOtherStore } from './other-store'getters: {combinedValue() {const otherStore = useOtherStore()return this.count + otherStore.value}
}

与 Vuex 的区别:

  • Pinia 的 getters 没有缓存的概念(Vuex 有缓存)
  • Pinia 的 getters 只是计算属性,没有像 Vuex 那样的 mapGetters 辅助函数
  • 在 Pinia 中,可以直接通过 store 实例访问 getters,不需要像 Vuex 那样通过 getters 对象

actions:

actions 是用来定义可以修改状态(state)的方法的地方。它可以包含业务逻辑,并且可以是异步的。

定义 actions:

import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({count: 0}),actions: {increment() {this.count++},decrement() {this.count--}}
})

使用 actions:

const store = useCounterStore()
store.increment() // 调用 action

异步 actions:

actions: {async fetchUserData(userId) {// 拿取用户数据try {const response = await fetch(`/api/users/${userId}`)this.user = await response.json()} catch (error) {console.error('Failed to fetch user:', error)}}
}

访问其他 actions:

actions: {async login(userCredentials) {// 用户认证const user = await this.authenticate(userCredentials)this.setUser(user)// this 指向 store 实例},async authenticate(credentials) {// 认证逻辑},setUser(user) {this.user = user}
}

访问其他 Store:

actions: {async checkout() {const cartStore = useCartStore()const userStore = useUserStore()// 使用其他 store 的数据和方法if (!userStore.isLoggedIn) {await userStore.login()}await api.post('/checkout', {items: cartStore.items,userId: userStore.user.id})cartStore.clear()}
}

传递参数:

actions: {addTodo(text) {this.todos.push({ text, done: false })}
}

与 Getters 交互:

actions: {completeAll() {// 使用 getterthis.allTodos.forEach(todo => {todo.done = true})}
},
getters: {allTodos() {return this.todos}
}

Pinia 状态持久化:

Pinia 默认情况下状态不会持久化,页面刷新后状态会丢失。

官方推荐的持久化插件 pinia-plugin-persistedstate。

安装:

npm install pinia-plugin-persistedstate
# 或
yarn add pinia-plugin-persistedstate

基本使用:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

store 中启用:

import { defineStore } from 'pinia'export const useStore = defineStore('storeId', {state: () => ({someState: 'hello pinia',}),persist: true, // 启用持久化
})

配置选项:

persist: {key: 'my-custom-key', // 存储的键名idstorage: localStorage, // 默认是 sessionStoragepaths: ['user', 'settings'], // 只持久化部分状态beforeRestore: (ctx) => { /* 恢复前 */ },afterRestore: (ctx) => { /* 恢复后 */ },
}

http://www.dtcms.com/a/298644.html

相关文章:

  • 关于“前导零”的问题记录,也就是(0.1)和.1这种数据处理问题
  • streamyfin(世博会)android 编译
  • 0人工沟通,它如何用AI撬动海外B端9400亿采购市场?
  • Round-Robin仲裁器
  • <HMI><威纶通><触摸屏>基于威纶通MT8106iQ触摸屏,实现自定义登录窗口(优化)
  • 内核驱动相关知识点
  • 【Agent】Common Ground 团队协作模型:Partner、Principal 与 Associate
  • 数据结构自学Day14 -- 归并排序
  • 正则表达式 \b:单词边界
  • 模拟flink处理无限数据流
  • WAIC2025预告|英码深元AI一体机将亮相华为昇腾展区,以灵活部署的能力赋能行业智能化转型
  • 学习:JS[6]环境对象+回调函数+事件流+事件委托+其他事件+元素尺寸位置
  • ReVQ (Quantize-then-Rectify,量化后修正)
  • 笛卡尔积规避:JOIN条件完整性检查要点
  • FreeRTOS—互斥信号量
  • Sweet Home 3D:一款免费的室内装修辅助设计软件
  • 【集合】JDK1.8 HashMap 底层数据结构深度解析
  • 第二章: 解密“潜在空间”:AI是如何“看见”并“记住”世界的?
  • 深入解析C语言三路快速排序算法
  • 动态规划:从入门到精通
  • 多品种小批量如何实现柔性排产?
  • 无感交互,创意飞扬:AI摄像头动捕赋能中小学AI人工智能实训室
  • Python Requests-HTML库详解:从入门到实战
  • 环境变量-进程概念(7)
  • 对自定义域和 GitHub 页面进行故障排除(Windows)
  • 批改作业小工具(一)-read report
  • InfluxDB Line Protocol 协议深度剖析(一)
  • 07 51单片机之定时器
  • 10BASE-T1S核心机制——PLCA参数详解
  • 关于AI编程的分析报告