vue-property-decorator

MuYan2022-04-22VueVue

为什么要使用 vue-property-decorator

vue-property-decorator 是在 vue-class-component 的基础上做了进一步的封装,在 TypeScript 官方文档 中,官方推荐了 vue-class-component,提供了 Vue,Component 等,而 vue-property-decorator 是社区出品,深度依赖于 vue-class-component,提供了更多操作符:@Component,@Prop,@Watch,@Emit 等等

安装

npm i -S vue-class-component
npm i -S vue-property-decorator

用法

这里有几个装饰器和一个函数(Mixin):

@Prop
@PropSync
@Model
@ModelSync
@Watch
@Provide
@Inject
@ProvideReactive
@InjectReactive
@Emit
@Ref
@VModel
@Component (由 vue-class-component 提供)
Mixins (mixins 函数 由 vue-class-component 提供)

@Component

  • @Component(options:ComponentOptions = {})

  • 即使没有组件也不能省略@Component,否则会报错。

  • @Component:注明此类为一个 vue 组件

  • export default class extends Vue: export 当前组件类是继承 vue 的

  • @Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives 等未提供装饰器的选项,也可以声明 computed,watch 等

import { Vue, Component } from "vue-property-decorator";

@Component({
  filters: {
    toFixed: (num: number, fix: number = 2) => {
      return num.toFixed(fix);
    },
  },
})
export default class MyComponent extends Vue {
  public list: number[] = [0, 1, 2, 3, 4];
  get evenList() {
    return this.list.filter((item: number) => item % 2 === 0);
  }
}

组件引用

import { Vue, Component } from "vue-property-decorator";
import TestComponent "@/TestComponent.vue";
@Component({
  components: {
    TestComponent
  }
})
export default class ComponentName extends Vue {}

@Prop

  • @Prop(options: (PropOptions | Constructor[] | Constructor) = {})

@Prop 装饰器接收一个参数,这个参数可以有三种写法:

  • Constructor,例如 String,Number,Boolean 等,指定 prop 的类型;
  • Constructor[],指定 prop 的可选类型;
  • PropOptions,可以使用以下选项:type,default,required,validator。

注:

  • 属性的 ts 类型后面需要加上 undefined 类型;或者在属性名后面加上!,表示非 null 和 非 undefined 的断言,否则编译器会给出错误提示;
  • 指定默认值必须使用上面例子中的写法,如果直接在属性名后面赋值,会重写这个属性,并且会报错。
import { Vue, Component, Prop } from "vue-property-decorator";

@Component
export default class ComponentName extends Vue {
  @Prop(String) public propA: string | undefined;
  @Prop([String, Number]) public propB!: string | number;
  @Prop({
    type: String,
    default: "abc",
  })
  public propC!: string;
}

@PropSync

  • @PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {})

@PropSync 装饰器与@prop 用法类似,二者的区别在于:

  • @PropSync 装饰器接收两个参数: propName: string 表示父组件传递过来的属性名; options: Constructor | Constructor[] | PropOptions 与@Prop 的第一个参数一致;
  • @PropSync 会生成一个新的计算属性。

注:

  • @PropSync 需要配合父组件的.sync 修饰符使用
import { Vue, Component, PropSync } from "vue-property-decorator";

@Component
export default class ComponentName extends Vue {
  @PropSync("propA", { type: String, default: "abc" })
  public syncedPropA!: string;
}
<template>
  <DEMO :like.sync="like" />
</template>

@Model

  • @Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {})

@Model 装饰器允许我们在一个组件上自定义 v-model,接收两个参数:

  • event: string 事件名。
  • options: Constructor | Constructor[] | PropOptions 与@Prop 的第一个参数一致。
import { Vue, Component, Model } from "vue-property-decorator";

@Component
export default class MyInput extends Vue {
  @Model("change", { type: String, default: "123" }) public value!: string;
}

@Watch

  • @Watch(path: string, options: WatchOptions = {})

@Watch 装饰器接收两个参数:

  • path: string 被侦听的属性名;
  • options?: WatchOptions={} options 可以包含两个属性 : immediate?:boolean 侦听开始之后是否立即调用该回调函数; deep?:boolean 被侦听的对象的属性被改变时,是否调用该回调函数;
import { Vue, Component, Watch } from "vue-property-decorator";

@Component
export default class MyInput extends Vue {
  @Watch("msg")
  public onMsgChanged(newValue: string, oldValue: string) {}

  @Watch("arr", { immediate: true, deep: true })
  public onArrChanged1(newValue: number[], oldValue: number[]) {}

  @Watch("arr")
  public onArrChanged2(newValue: number[], oldValue: number[]) {}
}

@Emit

  • @Emit 装饰器接收一个可选参数,该参数是$Emit的第一个参数,充当事件名。如果没有提供这个参数,$Emit 会将回调函数名的 camelCase 转为 kebab-case,并将其作为事件名;

  • @Emit 会将回调函数的返回值作为第二个参数,如果返回值是一个 Promise 对象,$emit 会在 Promise 对象被标记为 resolved 之后触发;

  • @Emit 的回调函数的参数,会放在其返回值之后,一起被$emit 当做参数使用。

  • 如果事件的名称未通过事件参数提供,则使用函数名称。 在这种情况下,camelCase 名称将转换为 kebab-case。

import { Vue, Component, Emit } from "vue-property-decorator";

@Component
export default class ComponentName extends Vue {
  count = 0;

  @Emit()
  addToCount(n: number) {
    this.count += n;
  }

  @Emit("reset")
  resetCount() {
    this.count = 0;
  }

  @Emit()
  returnValue() {
    return 10;
  }

  @Emit()
  promise() {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(20);
      }, 0);
    });
  }
}

@Ref

  • @Ref(refKey?: string)

  • @Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用信息。如果没有提供这个参数,会使用装饰器后面的属性名充当参数

import { Vue, Component, Ref } from "vue-property-decorator";

import AnotherComponent from "@/path/to/another-component.vue";

@Component
export default class YourComponent extends Vue {
  @Ref() readonly anotherComponent!: AnotherComponent;
  @Ref("aButton") readonly button!: HTMLButtonElement;
}

等同于

export default {
  computed() {
    anotherComponent: {
      cache: false,
      get() {
        return this.$refs.anotherComponent as AnotherComponent
      }
    },
    button: {
      cache: false,
      get() {
        return this.$refs.aButton as HTMLButtonElement
      }
    }
  }
}

Mixins 用法

  • 定义 mixins 文件
import { Vue, Component } from "vue-property-decorator";

@Component
export default class testMixins extends Vue {
  test: string = "测试数据";
}
  • 使用
import { Component, Vue } from "vue-property-decorator";
import outMixins from "./mixins";

@Component({
  mixins: [outMixins],
})
export default class ComponentName extends Vue {}

参考:vue-property-decoratoropen in new window

上次更新 2026/6/23 11:49:15
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8