refer to:/kaorun343/vue-property-decorator
How to make vue support Ts writing? We need to use itvue-property-decorator,This component depends entirely onvue-class-component
.
First install: npm i -D vue-property-decorator
Let's look at the code display on the page:
<template> <div> foo:{{foo}} defaultArg:{{defaultArg}} | {{countplus}} <button @click="delToCount($event)">Clickdel emit</button> <HellowWordComponent></HellowWordComponent> <button ref="aButton">ref</button> </div> </template> <script lang="ts"> import { Component, Vue, Prop, Emit, Ref } from 'vue-property-decorator'; import HellowWordComponent from '@/components/'; @Component({ components: { HellowWordComponent, }, beforeRouteLeave(to: any, from: any, next: any) { ('beforeRouteLeave'); next(); }, beforeRouteEnter(to: any, from: any, next: any) { ('beforeRouteLeave'); next(); }, }) export default class DemoComponent extends Vue { private foo = 'App Foo!'; private count: number = this.$; @Prop(Boolean) private defaultArg: string | undefined; @Emit('delemit') private delEmitClick(event: MouseEvent) {} @Ref('aButton') readonly ref!: HTMLButtonElement; // computed; get countplus () { return ; } created() {} mounted() {} beforeDestroy() {} public delToCount(event: MouseEvent) { (event); += 1; // countplus will accumulate } } </script> <style lang="less"> ... </style>
vue-proporty-decoratorIt has the following decorators and functions:
- @Component
- @Prop
- @PropSync
- @Model
- @Watch
- @Provide
- @Inject
- @ProvideReactive
- @InjectReactive
- @Emit
- @Ref
1.@Component(options:ComponentOptions = {})
@Component
The decorator can receive an object as a parameter and can be declared in the object.components ,filters,directives
Options for decorators are not provided, and can also be declaredcomputed,watch
wait
registerHooks:
In addition to putting beforeRouteLeave in Component as described above, you can also register globally, which is registerHooks
<script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; ([ 'beforeRouteLeave', 'beforeRouteEnter', ]); @Component export default class App extends Vue { beforeRouteLeave(to: any, from: any, next: any) { ('beforeRouteLeave'); next(); } beforeRouteEnter(to: any, from: any, next: any) { ('beforeRouteLeave'); next(); } } </script>
2.@Prop(options: (PropOptions | Constructor[] | Constructor) = {})
@Prop
The decorator receives a parameter, which can be written in three ways:
-
Constructor
,For exampleString,Number,Boolean
etc.prop
type; -
Constructor[]
, specifiedprop
Optional type; -
PropOptions
, the following options are available:type,default,required,validator
。
Note: The attribute's ts type needs to be added after itundefined
Type; or add! after the attribute name to indicateNon-null
andNon-undefined
assertion, otherwise the compiler will give an error message;
// Parent component:<template> <div class="Props"> <PropComponent :name="name" :age="age" :sex="sex"></PropComponent> </div> </template> <script lang="ts"> import {Component, Vue,} from 'vue-property-decorator'; import PropComponent from '@/components/'; @Component({ components: {PropComponent,}, }) export default class PropsPage extends Vue { private name = 'Zhang San'; private age = 1; private sex = 'nan'; } </script> // Subcomponents:<template> <div class="hello"> name: {{name}} | age: {{age}} | sex: {{sex}} </div> </template> <script lang="ts"> import {Component, Vue, Prop} from 'vue-property-decorator'; @Component export default class PropComponent extends Vue { @Prop(String) readonly name!: string | undefined; @Prop({ default: 30, type: Number }) private age!: number; @Prop([String, Boolean]) private sex!: string | boolean; } </script>
3,@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {})
@PropSync
Decorators and@prop
The usage is similar, the difference between the two is:
-
@PropSync
The decorator receives two parameters:
propName: string
Represents the attribute name passed by the parent component;
-
options: Constructor | Constructor[] | PropOptions
and@Prop
The first parameter is consistent;@PropSync
A new computed attribute will be generated.
Note that when using PropSync, you must use it in the parent component with .sync.
// Parent component<template> <div class="PropSync"> <h1>Parent component</h1> like:{{like}} <hr/> <PropSyncComponent :="like"></PropSyncComponent> </div> </template> <script lang='ts'> import { Vue, Component } from 'vue-property-decorator'; import PropSyncComponent from '@/components/'; @Component({components: { PropSyncComponent },}) export default class PropSyncPage extends Vue { private like = 'Like the parent component'; } </script> // Subcomponents<template> <div class="hello"> <h1>Subcomponents:</h1> <h2>syncedlike:{{ syncedlike }}</h2> <button @click="editLike()">Reviselike</button> </div> </template> <script lang="ts"> import { Component, Prop, Vue, PropSync,} from 'vue-property-decorator'; @Component export default class PropSyncComponent extends Vue { @PropSync('like', { type: String }) syncedlike!: string; // Used to implement two-way binding of components, children can change the value passed by the parent component editLike(): void { = 'Syncedlike after the modified subcomponent!'; // Two-way binding, changing the synchronization like will change the parent component's like } } </script>
4.@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {})
@Model
Decorators allow us to customize on a componentv-model
, receive two parameters:
-
event: string
Event name. -
options: Constructor | Constructor[] | PropOptions
and@Prop
The first parameter is consistent.
Note that if you don’t understand, you can check the vue official website document./v2/api/#model
// Parent component<template> <div class="Model"> <ModelComponent v-model="fooTs" value="some value"></ModelComponent> <div>Parent component app : {{fooTs}}</div> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import ModelComponent from '@/components/'; @Component({ components: {ModelComponent} }) export default class ModelPage extends Vue { private fooTs = 'App Foo!'; } </script> // Subcomponents<template> <div class="hello"> Subcomponents:<input type="text" :value="checked" @input="inputHandle($event)"/> </div> </template> <script lang="ts"> import {Component, Vue, Model,} from 'vue-property-decorator'; @Component export default class ModelComponent extends Vue { @Model('change', { type: String }) readonly checked!: string public inputHandle(that: any): void { this.$emit('change', ); // I will talk about @Emit later, here I will use this.$emit instead } } </script>
5,@Watch(path: string, options: WatchOptions = {})
-
@Watch
The decorator receives two parameters: -
path: string
The attribute name being listened to;options?: WatchOptions={} options
It can contain two properties:
immediate?:boolean
Whether to call the callback function immediately after listening begins;deep?:boolean
Whether to call the callback function when the attributes of the object being listened to are changed;
Happened inbeforeCreate
After the hook,created
Before the hook
<template> <div class="PropSync"> <h1>child:{{child}}</h1> <input type="text" v-model="child"/> </div> </template> <script lang="ts"> import { Vue, Watch, Component } from 'vue-property-decorator'; @Component export default class WatchPage extends Vue { private child = ''; @Watch('child') onChildChanged(newValue: string, oldValue: string) { (newValue); (oldValue); } } </script>
6,@Emit(event?: string)
-
@Emit
The decorator receives an optional parameter, which is$Emit
The first parameter of , acts as the event name. If this parameter is not provided,$Emit
The callback function name will becamelCase
Turn tokebab-case
, and use it as the event name; -
@Emit
The return value of the callback function will be used as the second parameter, if the return value is aPromise
Object,$emit
Will be herePromise
Objects are marked asresolved
Then trigger; -
@Emit
The parameters of the callback function will be placed after its return value and will be$emit
Use as a parameter.
// Parent component<template> <div class=""> ClickemitGet the name of the child component<br/> Name:{{}} <hr/> <EmitComponent sex='female' @add-to-count="returnPersons" @delemit="delemit"></EmitComponent> </div> </template> <script lang="ts"> import { Vue, Component } from 'vue-property-decorator'; import EmitComponent from '@/components/'; @Component({ components: { EmitComponent }, }) export default class EmitPage extends Vue { private emitData = { name: 'I don't have a name yet' }; returnPersons(data: any) { = data; } delemit(event: MouseEvent) { (); (event); } } </script> // Subcomponents<template> <div class="hello"> Subcomponents: <div v-if="person"> Name:{{}}<br/> age:{{}}<br/> gender:{{}}<br/> </div> <button @click="addToCount(person)">Clickemit</button> <button @click="delToCount($event)">Clickdel emit</button> </div> </template> <script lang="ts"> import { Component, Vue, Prop, Emit, } from 'vue-property-decorator'; type Person = {name: string; age: number; sex: string }; @Component export default class PropComponent extends Vue { private name: string | undefined; private age: number | undefined; private person: Person = { name: 'I am Zhang San of the child component', age: 1, sex: 'male' }; @Prop(String) readonly sex: string | undefined; @Emit('delemit') private delEmitClick(event: MouseEvent) {} @Emit() // If no alias is set here, the following function name is used by default addToCount(p: Person) { // If there are capital letters, you need to separate them with horizontal lines @add-to-count return ; // If you do not return here, the parameter p in brackets will be used by default; } delToCount(event: MouseEvent) { (event); } } </script>
7,@Ref(refKey?: string)
@Ref
The decorator receives an optional parameter to point to reference information to an element or child component. If this parameter is not provided, the attribute name after the decorator will be used as the parameter
<template> <div class="PropSync"> <button @click="getRef()" ref="aButton">Getref</button> <RefComponent name="names" ref="RefComponent"></RefComponent> </div> </template> <script lang="ts"> import { Vue, Component, Ref } from 'vue-property-decorator'; import RefComponent from '@/components/'; @Component({ components: { RefComponent }, }) export default class RefPage extends Vue { @Ref('RefComponent') readonly RefC!: RefComponent; @Ref('aButton') readonly ref!: HTMLButtonElement; getRef() { (); (); } } </script>
/Inject ProvideReactive/InjectReactive
@Provide(key?: string | symbol) / @Inject(options?: { from?: InjectKey, default?: any } | InjectKey)
decorator @ProvideReactive(key?: string | symbol)
/ @InjectReactive(options?: { from?: InjectKey, default?: any } | InjectKey)
decorator
Provide/inject decorator,
The key can be string orSymbol type,
Similarities: Data provided by Provide/ProvideReactive can be obtained by using Inject/InjectReactive in internal components.
Differences:
If provided (ProvideReactive
) value is modified by the parent component, and the child component can use itInjectReactive
Capture this modification.
// Outermost component<template> <div class=""> <H3>ProvideInjectPagepage</H3> <div> existProvideInjectPagepage使用Provide,ProvideReactiveDefine data,unnecessarypropsPassing data Then grandpa trapped his parents,Parents condoms son,Son condoms grandson,最后exist孙子组件里面获取ProvideInjectPage Information inside </div> <hr/> <provideGrandpa></provideGrandpa> <!--Grandpa Components--> </div> </template> <script lang="ts"> import { Vue, Component, Provide, ProvideReactive, } from 'vue-property-decorator'; import provideGrandpa from '@/components/'; @Component({ components: { provideGrandpa }, }) export default class ProvideInjectPage extends Vue { @Provide() foo = Symbol('fooaaa'); @ProvideReactive() fooReactive = 'fooReactive'; @ProvideReactive('1') fooReactiveKey1 = 'fooReactiveKey1'; @ProvideReactive('2') fooReactiveKey2 = 'fooReactiveKey2'; created() { = Symbol('fooaaa111'); = 'fooReactive111'; this.fooReactiveKey1 = 'fooReactiveKey111'; this.fooReactiveKey2 = 'fooReactiveKey222'; } } </script> // ...provideGrandpa calls parent component<template> <div class="hello"> <ProvideParentComponent></ProvideParentComponent> </div> </template> // ...ProvideParentComponent calls son component<template> <div class="hello"> <ProvideSonComponent></ProvideSonComponent> </div> </template> // ...ProvideSonComponent calls grandchild component<template> <div class="hello"> <ProvideGSonComponent></ProvideGSonComponent> </div> </template> // Grandson component <ProvideGSonComponent>, after multiple layers of reference, you can get the data of the outermost component provided by using Inject in the grandson component<template> <div class="hello"> <h3>The components of the grandson</h3> Grandpa Components里面的foo:{{}}<br/> Grandpa Components里面的fooReactive:{{fooReactive}}<br/> Grandpa Components里面的fooReactiveKey1:{{fooReactiveKey1}}<br/> Grandpa Components里面的fooReactiveKey2:{{fooReactiveKey2}} <span style="padding-left:30px;">=> fooReactiveKey2NothingkeySo it can't be obtained</span> </div> </template> <script lang="ts"> import { Component, Vue, Inject, InjectReactive, } from 'vue-property-decorator'; @Component export default class ProvideGSonComponent extends Vue { @Inject() readonly foo!: string; @InjectReactive() fooReactive!: string; @InjectReactive('1') fooReactiveKey1!: string; @InjectReactive() fooReactiveKey2!: string; } </script>
demo address:/slailcp/vue-cli3/tree/master/src/pc-project/views/manage
This is all about this article about understanding vue-property-decorator in one article. For more related vue-property-decorator content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!