vue-property-decorator的使用解讀
最近接觸了一個(gè)新項(xiàng)目,是基于 Webpack 搭建的 Vue2+TypeScript 項(xiàng)目,里面用的語(yǔ)法有些新奇,經(jīng)查閱資料,發(fā)現(xiàn)用的是 vue-property-decorator ,下面是整理的筆記。
裝飾器是什么
1、裝飾器(Decorator)是一種與類(class)相關(guān)的語(yǔ)法,用來注釋或修改類和類方法,許多面向?qū)ο蟮恼Z(yǔ)言都有這項(xiàng)功能。
2、裝飾器是一種函數(shù),寫成@ + 函數(shù)名。它可 以放在類和類方法的定義前面。
為什么要使用 vue-property-decorator
vue-class-component 是官方推出的vue對(duì) typescript 支持的裝飾器(庫(kù)),可以將 Vue 中的組件用類的方式編寫。vue-property-decoretor 即vue屬性裝飾器,這個(gè)庫(kù)完全依賴于 vue-class-component 。在 vue 中使用 typescript,通過裝飾器來簡(jiǎn)化書寫。
如何使用 vue-property-decorator
基本用法
<template>
<div class="text">測(cè)試</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": 表示腳本當(dāng)前語(yǔ)言是TypeScript;
- @Component: 表示這個(gè)類是一個(gè) vue 組件,@Component不能省略,否則會(huì)報(bào)錯(cuò);
- Test: 表示組件名
- export default class Login extends Vue: 表示當(dāng)前組件類是繼承vue的
定義變量
data中的數(shù)據(jù)由原來的data()方法改成直接在對(duì)象中定義,data內(nèi)的屬性直接作為實(shí)例屬性書寫,默認(rèn)都是public公有屬性,當(dāng)變量標(biāo)記為private時(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='張三'
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選項(xiàng),也可以聲明computed、watch、路由守衛(wèi)函數(shù)(beforeRouteEnter、beforeRouteLeave)等。
簡(jiǎn)單的說,就是框架負(fù)責(zé)為類額外添加一些成員和功能,而開發(fā)者負(fù)責(zé)通過 注解 的方式 將數(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接受一個(gè)參數(shù)可以是類型變量或者對(duì)象或者數(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 的斷言,否則編譯器會(huì)給出錯(cuò)誤提示。
@PropSync()
與 Prop 的區(qū)別是子組件可以對(duì) props 進(jìn)行更改, 并同步給父組件。
子組件 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ù)不能與定義的實(shí)例屬性同名, 因?yàn)?props 是只讀的.
}
</script>父組件:注意父組件里綁定 props 時(shí)需要加修飾符 .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ā)事件名,會(huì)自動(dòng)轉(zhuǎn)連字符寫法;
@Emit會(huì)將回調(diào)函數(shù)的返回值作為第二個(gè)參數(shù),如果返回值為一個(gè)Promise對(duì)象,emit會(huì)在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一個(gè)字符串,該字符串為要觸發(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 又是駝峰命名,所以,父組件用的時(shí)候要用中劃線拼接形式 edit-promise
@Emit()
editPromise() {
return new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
</script>@Watch 觀察屬性裝飾器
@Watch使用非常簡(jiǎn)單,接受第一個(gè)參數(shù)為要監(jiān)聽的屬性名 第二個(gè)屬性為可選對(duì)象
{immediate?: boolean, deep?: boolean}第一個(gè)表示監(jiān)聽開始后是否立即調(diào)用回調(diào)函數(shù),第二個(gè)表示監(jiān)聽的屬性變化時(shí)是否調(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 里聲明了之后,就會(huì)立即先去執(zhí)行里面的handler方法,如果為 false就跟我們以前的效果一樣,不會(huì)在綁定的時(shí)候就執(zhí)行
@Watch('count', { immediate: true })
countChange2(newVal:number, oldVal:number){
console.log(newVal, oldVal);
}
//deep:其值是true或false;確認(rèn)是否深入監(jiān)聽。deep的意思就是深入觀察,監(jiān)聽器會(huì)一層層的往下遍歷,給對(duì)象的所有屬性都加上這個(gè)監(jiān)聽器(受現(xiàn)代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測(cè)到對(duì)象屬性的添加或刪除)
@Watch('count', { deep: true })
countChange3(newVal:number, oldVal:number){
console.log(newVal, oldVal);
}
}
</script>計(jì)算屬性
對(duì)于Vue中的計(jì)算屬性,我們只需要將該計(jì)算屬性名定義為一個(gè)函數(shù),,在函數(shù)前加上get關(guān)鍵字即可,原本Vue中的computed里的每個(gè)計(jì)算屬性都變成了在前綴添加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>總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解如何使用Vue-PDF在應(yīng)用中嵌入PDF文檔
在現(xiàn)代Web應(yīng)用中,PDF文檔的使用非常普遍,因?yàn)樗梢栽诟鞣N設(shè)備和操作系統(tǒng)上保持一致的外觀和格式,本文我們就來探討一下如何在Vue.js應(yīng)用中使用vue-pdf庫(kù)嵌入PDF文檔吧2023-08-08
VUE-PDF實(shí)現(xiàn)pdf在線預(yù)覽問題
這篇文章主要介紹了VUE-PDF實(shí)現(xiàn)pdf在線預(yù)覽問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue.JS項(xiàng)目中5個(gè)經(jīng)典Vuex插件
在本文中,將向你展示5個(gè)特性,你可以通過 Vuex 插件輕松地添加到下一個(gè)項(xiàng)目中。一起來學(xué)習(xí)下。2017-11-11
vue3二次封裝element-ui中的table組件的過程詳解
這篇文章主要給大家介紹了vue3二次封裝element-ui中的table組件的過程,文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友跟著小編一起來學(xué)習(xí)吧2024-01-01
vue-cli-service serve報(bào)錯(cuò)error:0308010C:digital enve
這篇文章主要介紹了vue-cli-service serve報(bào)錯(cuò)error:0308010C:digital envelope routines::unsupported的解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06

