3.3.0 • Published 9 months ago

@haixing_hu/pinia-decorator v3.3.0

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
9 months ago

pinia-decorator

npm package License English Document CircleCI Coverage Status

pinia-decorator 是一个 JavaScript 库,它使用了 JavaScript 装饰器的第三阶段提案, 简化了将 Pinia 存储与 Vue 类风格组件 集成的过程。换句话说,它提供了类似于 vuex-classpinia-class 库的功能。

该库受 vuex-classpinia-class 的启发,但存在一些关键区别:

  1. 它是用纯 JavaScript 实现的,不需要 TypeScript 支持。
  2. 它支持 Vue 3
  3. 它支持使用 vue3-class-component 实现的 JavaScript 类风格 Vue 组件, 而 pinia-class 主要针对使用 vue-facing-decorator 实现的 TypeScript 类风格 Vue 组件。
  4. 它支持使用 @DefineStore 装饰器将一个类定义为 Pinia 存储。

目录

安装

你可以通过 npm 或 yarn 安装 pinia-decorator

npm install @haixing_hu/pinia-decorator

yarn add @haixing_hu/pinia-decorator

使用

pinia-decoratorVue 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(必需):使用 PiniadefineStore() 函数定义的待注入的 Pinia 存储对象。
  • stateName(可选):待注入的状态在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的状态的名称。

@WritableState

@WritableState 装饰器与 @State 类似,但它允许你将可写状态从 Pinia 存储注入到 Vue 类风格组件 中。这意味着你可以在组件内部既读取又修改 Pinia 存储的状态值。

@WritableState 装饰器的语法如下:

@WritableState(store: Object, stateName?: string)
  • store(必需):使用 PiniadefineStore() 函数定义的待注入的 Pinia 存储对象。
  • stateName(可选):待注入的状态在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的状态的名称。

@Getter

@Getter 装饰器用于将 getter 从 Pinia 存储注入到 Vue 类风格组件 中。 它允许你在组件内部调用 Pinia 存储的 getter 函数。

@Getter 装饰器的语法如下:

@Getter(store: Object, getterName?: string)
  • store(必需):使用 PiniadefineStore() 函数定义的待注入的 Pinia 存储对象。
  • getterName(可选):待注入的 getter 在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的 getter 的名称。

@Action

@Action 装饰器用于将 action 从 Pinia 存储注入到 Vue 类风格组件 中。 它允许你在组件内部调用存储的 action 函数。

@Action 装饰器的语法如下:

@Action(store: Object, actionName?: string)
  • store(必需):使用 PiniadefineStore() 函数定义的待注入的 Pinia 存储对象。
  • actionName(可选):待注入的 action 在 Pinia 存储中的名称。如果未提供, 装饰器将使用被装饰的字段名作为待注入的 action 的名称。

@Store

@Store 装饰器用于将整个 Pinia 存储注入到 Vue 类风格组件中。它允许你访问存储的所有状态、 getter 和 action。

@Store 装饰器的语法如下:

@Store(store: Object)
  • store(必需):使用 PiniadefineStore() 函数定义的待注入的 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 文件以获取更多详细信息。

3.3.0

9 months ago

3.2.0

9 months ago

3.1.0

9 months ago

3.0.1

10 months ago

3.0.0

10 months ago

2.3.0

10 months ago

2.2.0

10 months ago

2.1.0

10 months ago

1.2.2

1 year ago

2.0.0

10 months ago

1.2.0

2 years ago

1.2.1

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.1.0

2 years ago