vue-property-decorator的使用解讀
最近接觸了一個新項目,是基于 Webpack 搭建的 Vue2+TypeScript 項目,里面用的語法有些新奇,經(jīng)查閱資料,發(fā)現(xiàn)用的是 vue-property-decorator ,下面是整理的筆記。
裝飾器是什么
1、裝飾器(Decorator)是一種與類(class)相關的語法,用來注釋或修改類和類方法,許多面向?qū)ο蟮恼Z言都有這項功能。
2、裝飾器是一種函數(shù),寫成@ + 函數(shù)名。它可 以放在類和類方法的定義前面。
為什么要使用 vue-property-decorator
vue-class-component 是官方推出的vue對 typescript 支持的裝飾器(庫),可以將 Vue 中的組件用類的方式編寫。vue-property-decoretor 即vue屬性裝飾器,這個庫完全依賴于 vue-class-component 。在 vue 中使用 typescript,通過裝飾器來簡化書寫。
如何使用 vue-property-decorator
基本用法
<template>
<div class="text">測試</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component
export default class Test extends Vue {
}
</script>
<style lang="less" scoped>
.text{color:red}
</style>- lang="ts": 表示腳本當前語言是TypeScript;
- @Component: 表示這個類是一個 vue 組件,@Component不能省略,否則會報錯;
- Test: 表示組件名
- export default class Login extends Vue: 表示當前組件類是繼承vue的
定義變量
data中的數(shù)據(jù)由原來的data()方法改成直接在對象中定義,data內(nèi)的屬性直接作為實例屬性書寫,默認都是public公有屬性,當變量標記為private時,它就不能在聲明它的類的外部訪問。
<template>
<div class="text">{{uName}}--{{age}}</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component
export default class Test extends Vue {
uName='張三'
private age=18
}
</script>
<style lang="less" scoped>
.text{color:red}
</style>生命周期鉤子函數(shù)
<template>
<div class="text">{{uName}}--{{age}}</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component
export default class Test extends Vue {
uName:string = '張三'
private age:number = 18
private created():void {
console.log(`Hello,${this.uName}`);
}
}
</script>
<style lang="less" scoped>
.text{
color:red
}
</style>方法
<template>
<button @click="sum">{{count}}</button>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
@Component
export default class Test extends Vue {
count:number=1
private sum(){
this.count++
}
}
</script>
<style lang="less" scoped>
.text{
color:red
}
</style>@Component 類裝飾器
@Component({})可以聲明components、filter、directives等未提供裝飾器的vue選項,也可以聲明computed、watch、路由守衛(wèi)函數(shù)(beforeRouteEnter、beforeRouteLeave)等。
簡單的說,就是框架負責為類額外添加一些成員和功能,而開發(fā)者負責通過 注解 的方式 將數(shù)據(jù)傳給框架,框架收到 注解 傳入的數(shù)據(jù)后,可以用在類上。
<template>
<div>
<button @click="sum">{{count}}</button>
<ComponentA/>
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import ComponentA from '@/component/ComponentA.vue'
@Component({
watch:{
count(n){
console.log(n);
}
},
components:{
ComponentA
}
})
export default class Test extends Vue {
count:number=1
private sum(){
this.count++
}
}
</script>
<style lang="less" scoped>
.text{
color:red
}
</style>@Prop
父子組件之間的屬性傳值,子組件接收父組件傳參
@Prop接受一個參數(shù)可以是類型變量或者對象或者數(shù)組.@Prop接受的類型比如Number是JavaScript的類型,之后定義的屬性類型則是TypeScript的類型
//父組件 Test.vue
<template>
<div>
<button @click="sum">{{count}}</button>
<ComponentA :propA="propA" :propB="propB" :propC="propC"/>
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import ComponentA from '@/component/ComponentA.vue'
@Component({
watch:{
count(n){
console.log(n);
}
},
components:{
ComponentA
}
})
export default class Test extends Vue {
count:number=1
private propA:number=1
private propB:boolean=true
private propC:string='你好呀'
private sum(){
this.count++
}
}
</script>
<style lang="less" scoped>
.text{
color:red
}
</style>//子組件 ComponentA.vue
<template>
<div>
<div>{{str}}</div>
<div>下面是父組件傳來的值</div>
<div>{{propA}}</div>
<div>{{propB}}</div>
<div>{{propC}}</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue{
str:string='我是子組件'
@Prop(Number) propA:number|undefined
@Prop([String,Boolean]) propB!:string|boolean
@Prop({
default:'default value'
}) propC!:string
}
</script>
<!--下面是不用裝飾器的寫法-->
<!--<script>
export default {
props: {
propNum: {
type: Number
},
propStr: {
default: 'default value'
},
propArr: {
type: [String, Boolean]
}
},
data(){
return {
str:'我是子組件'
}
},
}
</script>-->需要注意的是:屬性的ts類型后面需要加上undefined類型;或者在屬性名后面加上!,表示非null 和 非undefined 的斷言,否則編譯器會給出錯誤提示。
@PropSync()
與 Prop 的區(qū)別是子組件可以對 props 進行更改, 并同步給父組件。
子組件 ComponentA:
<template>
<div>
<p>{{count}}</p>
<button @click="innerCount += 1">increment</button>
</div>
</template>
<script lang="ts">
import { Vue, Component, PropSync } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue {
@PropSync('count') private innerCount!: number // 注意@PropSync 里的參數(shù)不能與定義的實例屬性同名, 因為 props 是只讀的.
}
</script>父組件:注意父組件里綁定 props 時需要加修飾符 .sync
<template>
<ComponentA :count.sync="count"/>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import ComponentA from '@/component/ComponentA.vue'
@Component({
components:{
ComponentA
}
})
export default class Test extends Vue {
private count: number = 1
}
</script>@Emit
定義emit事件,參數(shù)字符串表示分發(fā)的事件名,如果沒有,則使用方法名作為分發(fā)事件名,會自動轉(zhuǎn)連字符寫法;
@Emit會將回調(diào)函數(shù)的返回值作為第二個參數(shù),如果返回值為一個Promise對象,emit會在Promise-resolved后觸發(fā);
//父組件 Test.vue
<template>
<div>
<ComponentA @edit-promise="editHandle" @sum="editHandle" @editHandleEmit="editHandle" @returnValue="editHandle" />
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import ComponentA from "@/component/ComponentA.vue";
@Component({
components: {
ComponentA
},
})
export default class Test extends Vue {
editHandle(count: any) {
console.log(count,'====');
}
}
</script>//子組件 ComponentA.vue
<template>
<div>
<button @click="editHandle(1)">Click</button>
<button @click="returnValue(2)">returnValue</button>
<button @click="sum">sum</button>
<button @click="editPromise">promise</button>
</div>
</template>
<script lang="ts">
import { Vue, Component, Emit } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue {
count: number = 0;
//@Emit(name: string),里面?zhèn)鬟f一個字符串,該字符串為要觸發(fā)的事件名
@Emit("editHandleEmit")
private editHandle(n:number) {
this.count+=n
}
@Emit("returnValue")
private returnValue(n:number) {
return this.count+=n
}
//@Emit()不傳參數(shù),那么它觸發(fā)的事件名就是它所修飾的函數(shù)名
@Emit()
sum() {
return this.count
}
//這里@Emit()沒有傳參數(shù)名,editPromise 又是駝峰命名,所以,父組件用的時候要用中劃線拼接形式 edit-promise
@Emit()
editPromise() {
return new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
</script>@Watch 觀察屬性裝飾器
@Watch使用非常簡單,接受第一個參數(shù)為要監(jiān)聽的屬性名 第二個屬性為可選對象
{immediate?: boolean, deep?: boolean}第一個表示監(jiān)聽開始后是否立即調(diào)用回調(diào)函數(shù),第二個表示監(jiān)聽的屬性變化時是否調(diào)用回調(diào)函數(shù)
<template>
<div>
<button @click="sum">sum</button>
</div>
</template>
<script lang="ts">
import { Vue, Component, Watch } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue {
count: number = 0;
sum() {
this.count++
}
@Watch('count')
countChange1(newVal:number, oldVal:number){
console.log(newVal, oldVal);
}
//immediate:其值是true或false;immediate:true代表如果在 wacth 里聲明了之后,就會立即先去執(zhí)行里面的handler方法,如果為 false就跟我們以前的效果一樣,不會在綁定的時候就執(zhí)行
@Watch('count', { immediate: true })
countChange2(newVal:number, oldVal:number){
console.log(newVal, oldVal);
}
//deep:其值是true或false;確認是否深入監(jiān)聽。deep的意思就是深入觀察,監(jiān)聽器會一層層的往下遍歷,給對象的所有屬性都加上這個監(jiān)聽器(受現(xiàn)代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除)
@Watch('count', { deep: true })
countChange3(newVal:number, oldVal:number){
console.log(newVal, oldVal);
}
}
</script>計算屬性
對于Vue中的計算屬性,我們只需要將該計算屬性名定義為一個函數(shù),,在函數(shù)前加上get關鍵字即可,原本Vue中的computed里的每個計算屬性都變成了在前綴添加get的函數(shù)。
<template>
<div>
<button @click="sum">sum</button>
<div>{{computedMsg}}</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Watch } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue {
count: number = 0;
sum() {
this.count++
}
get computedMsg(){
return this.count;
}
set computedMsg(count: number){
}
}
</script>@Provide 和@Inject
- @Provide()、@Inject()提供了父子組件、多層嵌套組件以及兄弟組件數(shù)據(jù)傳遞的方法。
- @Provide():父組件中通過Provide傳遞數(shù)據(jù);
- @Inject():子組件中通過Inject獲取數(shù)據(jù);
<template>
<div>
<div>{{desc}}</div>
<ComponentA/>
</div>
</template>
<script lang="ts">
import { Vue, Component, Provide } from "vue-property-decorator";
import ComponentA from "@/component/ComponentA.vue";
@Component({
components: {
ComponentA
},
})
export default class Test extends Vue {
desc:string="我是父組件"
//父組件中通過Provide傳遞數(shù)據(jù),str1、provideStr2是定義的要傳遞的變量
//如果@Provide()沒有傳參,則要傳給子組件的變量就是@Provide()后面定義的變量名
@Provide() str1:string = '你好呀!';
//如果@Provide()有傳參,則要傳給子組件的變量就是@Provide()中傳入的參數(shù)的變量名
@Provide('provideStr2') private str2:boolean = true;
}
</script><template>
<div>
<div>{{str}}</div>
<div>{{str1}}</div>
<div>{{str3}}</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Inject } from "vue-property-decorator";
@Component
export default class ComponentA extends Vue {
str:string="我是子組件"
//子組件中通過Inject獲取數(shù)據(jù)
// str1后面加 “!”表示,str1一定有值
// @Inject()不傳參表示接受的變量名和傳遞的變量名一樣
@Inject() private str1!: string;
// 如不確定provideStr2是否一定有值,可以加上 “|undefined”,這樣就不用加 “!”
// @Inject()傳參表示接受的變量名和傳遞的變量名不一樣,@Inject()后面定義的變量為接收數(shù)據(jù)的變量
@Inject('provideStr2') str3: boolean|undefined;
}
</script>總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue3二次封裝element-ui中的table組件的過程詳解
這篇文章主要給大家介紹了vue3二次封裝element-ui中的table組件的過程,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友跟著小編一起來學習吧2024-01-01
vue-cli-service serve報錯error:0308010C:digital enve
這篇文章主要介紹了vue-cli-service serve報錯error:0308010C:digital envelope routines::unsupported的解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06

