Vue-property-decorator VUE property decorator

vue-class-component + vue-property-decorator

Differences and connections: produced by the Vue-property-decorator community; Vue-class-component official product; Vue-class-component provides vue, Component, and so on;

Vue-property-decorator relies heavily on vue-class-component to extend more operators: @prop, @propsync, @Model, @modelsync, @watch, @provide, @Inject, @ProvidereActive, @Injectreactive, @emit, @ref, @ VModel, @ Component

Referenced in vUE

import { Vue, Component, Prop, PropSync, Model, ModelSync, Watch, Inject, Provide, ProvideReactive, InjectReactive, Emit, Ref, VModel } from 'vue-property-decorator'; @Component export default class YourComponent extends Vue { name: string = 'Simon Zhang'; // computed get MyName(): string { return `My name is ${this.name}`; } // methods sayHello(): void { alert(`Hello ${this.name}`); } mounted() { this.sayHello(); }}Copy the code

@Prop

One-way data flow All prop forms a one-way downlink binding between their parent prop: updates from the parent prop flow down to the child, but not the other way around.

@Prop(options: (PropOptions | Constructor[] | Constructor) = {})
Copy the code

The @prop decorator accepts a parameter that can be written in one of three ways:

1. PropOptions: Contains the following options: Type, required, default, validator

/ / define type Prop < T > = {T} () : | {new (... args: any[]): T & object } | { new(... args: string[]): Function } type PropType<T> = Prop<T> | Prop<T>[] type PropValidator<T> = PropOptions<T> | PropType<T> interface PropOptions<T = any> { type? : PropType<T>; required? : boolean; default? : T | null | undefined | (() => T | null | undefined); validator? (value: T): boolean; }Copy the code
// PropOptions example {type: Boolean, // Data type passed from parent component to child component required: false, // Whether default is mandatory: False // Default: ()=>({}) // Custom validator: value => ['success', 'warning', 'danger'].includes(value) }Copy the code
@Component export default class YourComponent extends Vue { @Prop({default: 'default value'}) readonly propB! : string; @prop ({type: Boolean, // Data type passed from parent component to child component required: false, // Mandatory or not Default: false // Default, if Object is passed, default: ()=>({}) collapsed! : boolean; }Copy the code

Constructor[], specifying the optional type of prop;

@Component
export default class YourComponent extends Vue {
  @Prop([String, Boolean]) readonly propC: string | boolean | undefined;
}
Copy the code

Constructor (e.g. String, Number, Boolean, Array, Object, Date, Function, Symbol, or custom Function types) specifying the type of prop

@Component
export default class YourComponent extends Vue {
  @Prop(Number) readonly propA: number | undefined;
}
Copy the code

Complete sample

@Component export default class YourComponent extends Vue { @Prop(Number) readonly propA: number | undefined; @Prop({default: 'default value'}) readonly propB! : string; @Prop([String, Boolean]) readonly propC: string | boolean | undefined; @prop ({type: Boolean, // Data type passed from parent component to child component required: false, // Mandatory or not Default: false // Default, if Object is passed, default: ()=>({}) collapsed! : boolean; // <==> // props: { // propA: { // type: Number // }, // propB: { // default: 'default value' // }, // propC: { // type: [String, Boolean] // }, // collapsed: { // type: Boolean, // required: false, // default: false // } // } }Copy the code

@PropSync

@propSync@prop Works like creating a computed getter and setter behind the scenes, except that it takes the propName as an argument to the decorator. This way, you can interact with the property as if it were a regular data property, while making it as simple as.sync attaching modifiers to the parent component

Note that @propsync is used in conjunction with.sync in the parent component

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

@propsync and @prop are used similarly. The difference is that:

The @propSync decorator takes two arguments: propName: type string, which represents the property name passed by the parent component; Options: PropOptions | Constructor [] | Constructor and @ Prop in the first parameter is consistent; @propSync generates a new calculated property

Complete sample

@Component export default class YourComponent extends Vue { @PropSync('name', {type: String}) syncedName! : string; // <==> // props: { // name: { // type: String // } // }, // computed: { // syncedName: { // get() { // return this.name // }, // set(value) { // this.$emit('update:name', value) // } // } // } }Copy the code

@Model

V-model for custom components

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `<input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)">`
});
Copy the code

Customize Prop and Event for two-way data binding

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

The @Model decorator allows you to customize a V-Model on a component that takes two parameters: event: string, which represents the event name; Options: PropOptions | Constructor [] | Constructor are consistent with the first parameter of the @ Prop;

Complete sample

@Component export default class YourComponent extends Vue { @Model('change', {type: Boolean}) readonly checked! : boolean; / / < = = > / / model: {/ / custom components of v - model / / prop: 'checked', / / the event: 'change' / /}, / / props: {/ / checked: {/ / type: Boolean // Prop validation //} //Copy the code

@ModelSync

@ModelSync(propName: string, event? : string, options: (PropOptions | Constructor[] | Constructor) = {})Copy the code

The @modelSync decorator accepts three arguments: propName: type string, which represents the type name; Event: indicates the name of an event. Options: PropOptions | Constructor [] | Constructor are consistent with the first parameter of the @ Prop;

Complete sample

@Component export default class YourComponent extends Vue { @ModelSync('checked', 'change', {type: Boolean}) readonly checkedValue! : boolean; // <==> // model: { // prop: 'checked', // event: 'change' // }, // props: { // checked: { // type: Boolean // } // }, // computed: { // checkedValue: { // get() { // return this.checked // }, // set(value) { // this.$emit('change', value) // } // } // } }Copy the code

@Watch

@Watch(path: string, options: WatchOptions = {})
Copy the code

The @watch decorator takes two arguments: path: string, the name of the property to be listened on; options? : WatchOptions = {} contains two properties:

  1. immediate? : booleanWhether the callback function is called immediately after the listener starts;
  2. deep? : booleanIndicates whether to monitor in depth

Complete sample

interface Person {} @Component export default class YourComponent extends Vue { @Watch('child') onChildChanged(val: string, oldVal: string) {} @Watch('person', {immediate: true, deep: true}) onPersonChanged1(val: Person, oldVal: Person) {} @Watch('person') onPersonChanged2(val: Person, oldVal: Person) {} // <==> // watch: { // child: [ // { // handler: 'onChildChanged', // immediate: false, // deep: false // } // ], // person: [ // { // handler: 'onPersonChanged1', // immediate: true, // the child component props needs to execute the function when it gets the default value from the parent component for the first time, so it needs to set the immediate to true // deep: }, {// handler: 'onPersonChanged2', // immediate: false, // deep: false // } // ] // }, // methods: { // onChildChanged(val, oldVal) {}, // onPersonChanged1(val, oldVal) {}, // onPersonChanged2(val, oldVal) {} // } }Copy the code

@Provide

Provide and Inject bindings are not responsive and can be used for deeply nested components where the deep child component only needs part of the parent component.

@Provide(key? : string | symbol)Copy the code

Complete sample

@Component export default class YourComponent extends Vue {// -> parent @provide () foo = 'foo'; @Provide('bar') baz = 'bar'; // <==> // data() { // return { // foo: 'foo', // baz: 'bar' // } // }, // provide() { // return { // foo: this.foo, // bar: this.baz // } // } }Copy the code

@Inject

@Inject(options? : { from? : InjectKey, default? : any } | InjectKey)Copy the code

Complete sample

const symbol = Symbol('baz'); @Component export default class YourComponent extends Vue {// -> child @inject () readonly foo! : string; @Inject('bar') readonly bar! : string; @Inject({from: 'optional', default: 'default'}) readonly optional! : string; @Inject(symbol) readonly baz! : string; // <==> // inject: { // foo: 'foo', // bar: 'bar', // optional: { from: 'optional', default: 'default' }, // baz: symbol // } }Copy the code

@ProvideReactive

A reactive version of @provide @providereactive.

@ProvideReactive(key? : string | symbol)Copy the code

Complete sample

Const key = Symbol() @Component export default class YourComponent extends Vue {// -> parent @providereActive () one = 'value' @ProvideReactive(key) two = 'value' }Copy the code

@InjectReactive

Reactive version of Inject @injectreactive. If the parent component modifies the supplied value, the child component can capture the change

@InjectReactive(options? : { from? : InjectKey, default? : any } | InjectKey)Copy the code

Complete sample

Const key = Symbol() @Component export default class YourComponent extends Vue {// -> child @injectreactive () one! : string @InjectReactive(key) two! : string }Copy the code

@Emit

@Emit(event? : string)Copy the code

The @emit decorator accepts an optional argument as the event name; If this parameter is not provided, $emit will change the callback function’s camelCase to kebab-case (dash name) as the event name;

@emit will take the return value of the callback as the second argument. If the return value is a Promise object, $Emit will fire the Promise object as Resolved.

The arguments to the @emit callback will be used by $Emit after the return value.

Complete sample

@Component export default class YourComponent extends Vue { count: number = 0; @Emit() addToCount(n: number) { this.count += n; } @Emit('reset') resetCount() { this.count = 0; } @Emit() returnValue() { return 10; } @Emit() onInputChange(e: any) { return e.target.value; } @emit () promise() {// Functions decorated by @emit $Emit with their return values and their original arguments. If the return value is a Promise, it will be resolved before it is issued. return new Promise((resolve) => { setTimeout(() => { resolve(20); }, 0); }); } // <==> // data() { // return { // count: 0 // } // }, // methods: { // addToCount(n) { // this.count += n // this.$emit('add-to-count', n) // }, // resetCount() { // this.count = 0 // this.$emit('reset') // }, // returnValue() { // this.$emit('return-value', 10) // }, // onInputChange(e) { // this.$emit('on-input-change', e.target.value, e) // }, // promise() { // const promise = new Promise((resolve) => { // setTimeout(() => { // resolve(20) // }, 0) // }) // // promise.then((value) => { // this.$emit('promise', value) // }) // } // } }Copy the code

@Ref

@Ref(refKey? : string)Copy the code
// add as HTMLDivElement :(Object is possibly 'null'. Let docEl = document.documentElement as HTMLDivElementCopy the code

Complete sample

import AnotherComponent from '@/path/to/another-component.vue' @Component export default class YourComponent extends Vue  { @Ref() readonly anotherComponent! : AnotherComponent @Ref('aButton') readonly button! : HTMLButtonElement; // <==> // computed() { // anotherComponent: { // cache: False, // When the cache is enabled, // return this.$refs.anotherComponent as anotherComponent //} // button: {// cache: false, // get() { // return this.$refs.aButton as HTMLButtonElement // } // } // } }Copy the code

@VModel

@VModel(propsArgs? : PropOptions)Copy the code

Complete sample

@Component export default class YourComponent extends Vue { @VModel({type: String}) names! : string; // <==> // props: { // value: { // type: String // } // }, // computed: { // names: { // get() { // return this.value // }, // set(value) { // this.$emit('input', value) // } // } // } }Copy the code

@Component

Complete sample

@Component
export default class YourComponent extends Vue {
    
}
Copy the code