@haixing_hu/pinia-decorator v3.3.0
pinia-decorator
pinia-decorator 是一个 JavaScript 库,它使用了 JavaScript 装饰器的第三阶段提案, 简化了将 Pinia 存储与 Vue 类风格组件 集成的过程。换句话说,它提供了类似于 vuex-class 和 pinia-class 库的功能。
该库受 vuex-class 和 pinia-class 的启发,但存在一些关键区别:
- 它是用纯 JavaScript 实现的,不需要 TypeScript 支持。
- 它支持 Vue 3。
- 它支持使用 vue3-class-component 实现的 JavaScript 类风格 Vue 组件, 而 pinia-class 主要针对使用 vue-facing-decorator 实现的 TypeScript 类风格 Vue 组件。
- 它支持使用
@DefineStore
装饰器将一个类定义为 Pinia 存储。
目录
安装
你可以通过 npm 或 yarn 安装 pinia-decorator:
npm install @haixing_hu/pinia-decorator
或
yarn add @haixing_hu/pinia-decorator
使用
pinia-decorator 为 Vue 3 类风格组件 提供了以下装饰器:
@State
:用于将只读状态从 Pinia 存储注入到组件中。@WritableState
:用于将可写状态从 Pinia 存储注入到组件中。@Getter
:用于将 getter 从 Pinia 存储注入到组件中。@Action
:用于将 action 从 Pinia 存储注入到组件中。@Store
:用于将整个 Pinia 存储注入到组件中。@DefineStore
:用于将一个类定义为 Pinia 存储。
@State
@State
装饰器用于将只读状态从 Pinia 存储注入到 Vue 类风格组件 中。
它允许你在组件内部访问和使用 Pinia 存储的状态。
@State
装饰器的语法如下:
@State(store: Object, stateName?: string)
store
(必需):使用Pinia
的defineStore()
函数定义的待注入的 Pinia 存储对象。stateName
(可选):待注入的状态在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的状态的名称。
@WritableState
@WritableState
装饰器与 @State
类似,但它允许你将可写状态从 Pinia 存储注入到
Vue 类风格组件 中。这意味着你可以在组件内部既读取又修改 Pinia 存储的状态值。
@WritableState
装饰器的语法如下:
@WritableState(store: Object, stateName?: string)
store
(必需):使用Pinia
的defineStore()
函数定义的待注入的 Pinia 存储对象。stateName
(可选):待注入的状态在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的状态的名称。
@Getter
@Getter
装饰器用于将 getter 从 Pinia 存储注入到 Vue 类风格组件 中。
它允许你在组件内部调用 Pinia 存储的 getter 函数。
@Getter
装饰器的语法如下:
@Getter(store: Object, getterName?: string)
store
(必需):使用Pinia
的defineStore()
函数定义的待注入的 Pinia 存储对象。getterName
(可选):待注入的 getter 在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的 getter 的名称。
@Action
@Action
装饰器用于将 action 从 Pinia 存储注入到 Vue 类风格组件 中。
它允许你在组件内部调用存储的 action 函数。
@Action
装饰器的语法如下:
@Action(store: Object, actionName?: string)
store
(必需):使用Pinia
的defineStore()
函数定义的待注入的 Pinia 存储对象。actionName
(可选):待注入的 action 在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的 action 的名称。
@Store
@Store
装饰器用于将整个 Pinia 存储注入到 Vue 类风格组件中。它允许你访问存储的所有状态、
getter 和 action。
@Store
装饰器的语法如下:
@Store(store: Object)
store
(必需):使用Pinia
的defineStore()
函数定义的待注入的 Pinia 存储对象的创建函数。
toStore()
toStore()
函数用于将一个类定义为 Pinia 存储。它允许你定义一个类,该类的实例将作为 Pinia 存储的实例。
toStore()
函数的语法如下:
toStore(storeId: string, Class: function)
storeId
(必需):Pinia 存储的ID。Class
(必需):待定义为 Pinia 存储的类。
@RawField
@RawField
装饰器用于将一个类的字段标记为原始字段,这样该类被转换为 Pinia store 后,该
字段表示的状态不会被转换为响应式状态。
示例
以下是如何在 Vue 组件中使用这些装饰器的简单示例:
import { Component, toVue } from '@haixing_hu/vue3-class-component';
import { State, WritableState, Getter, Action, Store } from '@haixing_hu/pinia-decorator';
import { useMyStore } from './my-pinia-store-module';
@Component
export class MyComponent extends Vue {
@State(useMyStore)
myValue;
@State(useMyStore, 'message')
myMessage;
@Getter(useMyStore)
myGetter
@Getter(useMyStore, 'count')
myCountGetter
@Action(useMyStore)
fetchData;
@Action(useMyStore, 'sayMessage')
mySayMessage;
@Store(useMyStore)
store;
someOtherMessage = 'Hello World!';
callSayMessage() {
console.log('MyComponent.callSayMessage');
this.mySayMessage(this.myMessage);
}
}
export default toVue(MyComponent);
下面是一个使用 toStore()
函数的示例,注意该函数支持类的继承:
import { toStore, RawField } from '@haixing_hu/pinia-decorators';
import { Logger } from '@haixing_hu/logging';
import dayjs from 'dayjs';
class BaseUserStore {
id = '';
username = '';
password = '';
nickname = '';
token = {
value: 'token-value',
expired: 1000,
};
get age() {
throw new Error('This getter will be overridden by subclass');
}
setNickname(nickname) {
this.nickname = nickname;
}
login() {
throw new Error('This function will be overridden by subclass');
}
}
class UserStore extends BaseUserStore { // support class inheritance
avatar = '';
birthday = '';
@RawField
logger = Logger.getLogger('store.user'); // this field is marked as raw field
get age() { // override the super class getter
return dayjs().diff(this.birthday, 'year');
}
setAvatar(avatar) {
this.avatar = avatar;
}
updatePassword(password) {
this.password = newPassword;
return api.updatePassword(this.username, newPassword);
}
login() { // override the super class method
this.logger.info('Logging in as:', this.username);
return api.login(this.username, this.password);
}
}
export default toStore('user', UserStore);
以上例子定义了一个名为 user
的 Pinia 存储,它等价于以下代码:
import { defineStore } from 'pinia';
import { markRaw } from 'vue';
const useUserStore = defineStore('user', {
state: () => ({
id: '',
username: '',
password: '',
nickname: '',
token: {
value: 'token-value',
expired: 1000,
},
avatar: '',
birthday: '',
logger: markRaw(Logger.getLogger('store.user')),
}),
getters: {
age: (state) => dayjs().diff(state.birthday, 'year'),
},
actions: {
setNickname(nickname) {
this.nickname = nickname;
},
setAvatar(avatar) {
this.avatar = avatar;
},
updatePassword(newPassword) {
this.password = newPassword;
return api.updatePassword(this.username, newPassword);
},
login() {
this.logger.info('Logging in as:', this.username);
return api.login(this.username, this.password);
},
},
});
export default useUserStore;
我们可以按如下方式在 Vue 组件中使用 UserStore
:
<template>
<div>
<div>Username: {{ username }}</div>
<div>Nickname: {{ nickname }}</div>
<div>Age: {{ age }}</div>
<div>Avatar: <img :src="avatar" /></div>
<button @click="setNickname('new-nickname')">Set Nickname</button>
<button @click="avatar = 'new-avatar.png'">Set Avatar</button>
<button @click="updatePassword('new-password')">Change Password</button>
<button @click="login()">Login</button>
</div>
</template>
<script>
import { Component, toVue } from '@haixing_hu/vue3-class-component';
import { State, Getter, Action } from '@haixing_hu/pinia-decorators';
import UserStore from 'src/stores/user';
@Component
class UserPage {
@State(UserStore)
username;
@State(UserStore)
nickname;
@WritableState(UserStore)
avatar;
@Getter(UserStore)
age;
@Action(UserStore)
setNickname;
@Action(UserStore)
updatePassword;
@Action(UserStore)
login;
}
export default toVue(UserPage);
</script>
有关更多详细信息,请查看以下演示项目:
贡献
如果你发现任何问题或有改进建议,请随时在 GitHub 仓库 中提出问题或提交请求。
我们欢迎你的贡献和反馈!
许可证
pinia-decorator
遵循 Apache 2.0 许可证分发。
请查看 LICENSE 文件以获取更多详细信息。
10 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
1 year ago
11 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago