Plugins
-
plugin是一个函数, 其接收一个context作为参数, 其返回值将会被添加到store上.context参数pinia:createPinia()返回的Pinia实例app:createApp()返回的appstore: 被插件作用的storeoptions: 定义defineStore时传入第三个参数
- 返回值
- 返回对象, 其中的属性将被添加到
store. 或者返回void
- 返回对象, 其中的属性将被添加到
- 📕只有
pinia实例被传给app之后创建的store才会被plugin作用.
-
plugin的简单使用-
创建
src/store/plugin/test.ts-
import { PiniaPluginContext } from 'pinia' export default function (context: PiniaPluginContext) { console.log('context.pinia', context.pinia); console.log('context.app', context.app); console.log('context.store', context.store); console.log('context.options', context.options); return { secret: 'don\'t tell anyone!' } }
-
-
main.js-
import { createPinia } from 'pinia' import myPiniaPlugin from './store/plugin/test' const app = createApp(App); const pinia = createPinia(); app.use(pinia); pinia.use(myPiniaPlugin);
-
-
看下面的截图, 只有
user和counter两个store被插件作用了, 而且每个store上都有plugin返回的参数. -

-

-
当然可以通过
store.[属性]的方式直接使用-
<h2>By Plugin: {{ user.secret }}</h2> 
-
-
📕返回的参数每个
store各自一份, 并不共享. 即如果你修改了store A的secret,store B的secret不会被影响.
-
-
给
store添加参数- 可以直接通过
store.[属性]的方式给store添加参数, 但是官网建议尽量使用返回值的方式来从而被开发者工具跟踪-
📕这种方式同样每个
store都有自己的数据, 互不影响. -
📕这种方式其实就是给
store添加新的state -
export default function (context: PiniaPluginContext) { context.store.hello = 'world'; return { secret: 'don\'t tell anyone!' } } -
这样的方式开发者工具并不会侦测到属性的添加, 只有在控制台打印
store时才可以看到 -

-
如果一定要在开发者工具中看到这个属性, 请保证
仅在开发环境下使用_customProperties. 因为生产环境下会被移除-
context.store.hello = 'world'; if (process.env.NODE_ENV === 'development') { context.store._customProperties.add('hello'); } 
-
-
- 可以直接通过
-
给
store添加响应式参数- 📕另外, 如果定义属性时使用响应式数据, 那么每个
store都会有自己的属性; - 由于
store本身是reactive, 其会自动解包内部的ref或者reactive, 因此在访问器内部响应式数据时不需要使用.value -
context.store.good = ref('bye'); console.log('no unwrapping', context.store.good); - 在组件中使用
-
<h2>By Plugin Reactive: {{ user.good }}</h2> -
function updateRefGood() { user.good = 'hahaha' console.log('after changing user good ', count.good) }
-

- 📕另外, 如果定义属性时使用响应式数据, 那么每个
- 但是响应式数据定义在插件之外, 那么所有的
store共享一个属性.- 同样的套路, 现在
plugin中定义数据 -
const bad = ref('sad') export default function (context: PiniaPluginContext) { context.store.hello = 'world'; // each store has its own good context.store.good = ref('bye'); console.log('no unwrapping', context.store.good); // all store share the same bad context.store.bad = bad; return { secret: 'don\'t tell anyone!' } } - 在组件中
-
<h2>By Plugin nonReactive: {{ user.bad }}</h2> <button @click="updateRefBad">updateRefBad</button> -
function updateRefBad() { user.bad = 'happy'; console.log('after changing user bad ', count.bad) } 
-
- 同样的套路, 现在
- 给
store添加新的state- 如果想给
store添加新的state property可以通过下面两种方式- 直接通过
store.[属性名] - 通过
store.$state这样才能在开发者工具中使用, 并且在SSR过程中被序列化.
- 直接通过
- 下面看第二种
-
export default function({ store } : PiniaPluginContext) { if (!Object.prototype.hasOwnProperty(store.$state, 'hasError')) { const hasError = ref(false); store.$state.hasError = hasError; } store.hasError = toRef(store.$state, 'hasError'); } 1️⃣首先, 为了正确处理SSR, 需要确保不覆盖任何已存在的值. 因此先判断是否存在hasError2️⃣如果不存在, 那么使用ref定义. 这样每个store都会有自己独立的hasError3️⃣其次, 如果已经存在hasError, 我们需要将hasError从state转移到store, 这样既可以通过store.hasError访问, 也可以通过store.$state.hasError访问.
-
- 📕这种情况下, 最后不要在
return时返回hasError了. 因为返回值会被展示在开发者工具中的state部分, 又定义又返回就会展示两次了. - 📕在
plugin中的增加state或修改state, 都不触发任何的订阅, 因为这时store并不活跃
- 如果想给
- 添加外部属性
- 如果要添加外部属性, 添加来自其他库的类的实例, 添加其他非响应式的数据, 我们应该使用
markRaw包装一下再传递给pinia. -
context.store.language = markRaw({ locale: 'zh-CN', });
- 如果要添加外部属性, 添加来自其他库的类的实例, 添加其他非响应式的数据, 我们应该使用
- 调用
$onAction和$subscribe-
context.store.$subscribe((mutation, state) => { // ... }); context.store.$onAction(() => { // ... });
-
本文详细介绍了如何使用Pinia插件为Vue应用的状态管理添加额外的功能。包括如何定义和使用插件,以及如何通过插件向store添加各种类型的属性。
908

被折叠的 条评论
为什么被折叠?



