裝飾器vue-property-decorator


接觸到了新的vue項目,使用vue+ts+vue-property-decotator來進行項目的簡化,一時間語法沒有看懂,所以花時間學習這個裝飾器的包。

1.裝飾器 @Component(options:Component = {})

默認接受一個對象作為參數,在這個對象中聲明components、 filters、 directives等未提供裝飾符的選項,也可以聲明computed、watch等

import { Component, Vue } from 'vue-property-decorator'
import Gap from './Gap.vue'

@Component({
    components: {
        Gap,
    }
})
export default class CorrectQuestionResult extends Vue{
    get trueAnswerText () {
        const trueAnswer = this.trueAnswer.ecAnswers![0]
        return this.formatAnswerDesc(trueAnswer.operation!, trueAnswer.source!, trueAnswer.target!)
    }
}

在@component中聲明了引入的組件,組件的寫法也發生了改變,export default class '組件name' extends Vue, 在vue中data、computed的形式也發生改變

<script lang="ts">
    import {Vue, Component} from 'vue-property-decorator';

    @Component({})
    export default class "組件名" extends Vue{
        ValA: string = "hello world";
        ValB: number = 1;
        get val() {
             return this.ValB + 1;
            }
    }
</script>    

等同於

<script>
    export default {
       data() {
           return {
              ValA: string = "hello world";
              ValB: number = 1;
         }
       },
      computed: {
          val() {
              return this.ValB + 1;
           }
      }
    }
</script>

2.@Prop(options: (PropOptions | construct[] | construct))

 @Prop接受一個參數,可以有三種寫法

    Constructor,例如String,Number, Boolean等,指定prop的類型

    Constructor[],指定prop的類型

    PropOptions,可以使用以下選項:type,default,required,validator

import { Vue, Component, Prop } from 'vue-property-decorator'

@Componentexport default class MyComponent extends Vue {
  @Prop(String) public propA: string | undefined
  @Prop([String, Number]) public propB!: string | number
  @Prop({
    type: String,
    default: 'abc'
  })
  public propC!: string
}

warning:

    屬性的ts類型后面需要加上undefined類型;或者在屬性名后面加上!,表示非null 和 非undefined

的斷言,否則編譯器會給出錯誤提示

    指定默認值必須使用上面例子中的寫法,如果直接在屬性名后面賦值,會重寫這個屬性,並且會報錯。

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

  裝飾自定義Model,自定義v-model,接收兩個參數:1.event 2. prop; 和vue官方的參數一致,只是裝飾器寫法稍有不同。

import { Vue, Component, Model } from 'vue-property-decorator'

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

需要在父組件中配合

<input
    type="text"
    v-model="value"  // 真的
    :value="value" // 假的
    @change="$emit('change', $event.target.value)" // 假的
  />

 

4.@Watch (path: string, options:watchOptions = {}), 接收兩個參數 path: 被監聽的屬性名, 監聽的條件:{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[]) {}
}

 5.@Emit裝飾器

    1.接收一個可選參數,該參數是$emit的第一個參數(事件名),如果沒有提供這個參數,$emit會將回調函數的cameCase轉為kebab-case,作為事件名

    2.會將回調函數的返回值作為第二個參數,如果返回值是一個promise對象,$emit會在promise狀態改為resolve之后觸發。

    3.emit回調函數的參數,將會放在其返回值之后,一起被$emit當作參數使用。

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

@Component
export default class MyComponent extends Vue {
  count = 0
  @Emit()
  public addToCount(n: number) {
    this.count += n
  }
  @Emit('reset')
  public resetCount() {
    this.count = 0
  }
  @Emit()
  public returnValue() {
    return 10
  }
  @Emit()
  public onInputChange(e) {
    return e.target.value
  }
  @Emit()
  public promise() {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(20)
      }, 0)
    })
  }
}

等同於

export default {
  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)
      })
    }
  }
}

6.Mixins在vue中有兩種配合typescript的混合方法,一種需要定義接口、一種不需要定義vue/type/vue模塊

//定義要混合的類 mixins.ts
import Vue from 'vue';
import  Component  from 'vue-class-component';

@Component  // 一定要用Component修飾
export default class myMixins extends Vue {
    value: string = "Hello"
}
// 引入
import  Component  {mixins}  from 'vue-class-component';
import myMixins from 'mixins.ts';

@Component
export class myComponent extends mixins(myMixins) {
                          // 直接extends myMinxins 也可以正常運行
      created(){
          console.log(this.value) // => Hello
    }
}

第二種方式,需要定義vue/type/vue模塊,1.改造混入的ts文件定義 vue/type/vue接口

// mixins.ts
import { Vue, Component } from 'vue-property-decorator';


declare module 'vue/types/vue' {
    interface Vue {
        value: string;
    }
}

@Component
export default class myMixins extends Vue {
    value: string = 'Hello'
}
import { Vue, Component, Prop } from 'vue-property-decorator';
import myMixins from '@static/js/mixins';

@Component({
    mixins: [myMixins]
})
export default class myComponent extends Vue{
    created(){
        console.log(this.value) // => Hello
    }
}

兩種方法的不同是定義vue/type/vue模塊,在混入的時候就要繼承該mixins,,如果是定了該模塊,直接在@Component中混入即可

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM