1. 程式人生 > 其它 >TS語言學習(三)

TS語言學習(三)

ts在Vue專案中的基礎用法

vue-property-decorator

vue-property-decoratorvue-class-component的基礎上增加了更多與Vue相關的裝飾器,使Vue元件更好的跟TS結合使用。這兩者都是離不開裝飾器的,(decorator)裝飾器已在ES提案中。Decorator是裝飾器模式的實踐。裝飾器模式呢,它是繼承關係的一個替代方案。動態地給物件新增額外的職責。在不改變介面的前提下,增強類的效能。

vue-property-decorator是這個Vue專案檔案中完全依賴的庫,它是Vue官方推薦的並且依賴於vue-class-component

,先介紹下它在專案中的常見用法。

  • @Component
  • @Emit
  • @Provice @Inject
  • @Prop
  • @Watch
  • @Model
  • @Minxins

@Component 類裝飾器

首先,Vue頁面中的script部分要加一個lang=ts,這樣安裝好typescript正能引用

複製程式碼
<script lang="ts">
    import {Vue, Component} from 'vue-property-decorator';
    import BaseHeader from '@/components/BaseHeader'; 
    
    //公共頭部元件
    @Component({
        components: {
            BaseHeader
        }
    })
    export default class extends Vue {
        private stateA:boolean = true
        private stateB:string = ''
        private stateC:number = 0
        private stateD:any = {}
        stateE:any[] = []
    }
</script>

等同於

複製程式碼
<script>
    import Vue from 'vue';
    import BaseHeader from '@/components/BaseHeader'; //公共頭部元件

    export default {
        components: {
            BaseHeader
        },
        
        data(){
            return {
                stateA: true,
                stateB: '',
                stateC: 0,
                stateD: {},
                stateE: []
            }    
        }
    }
</script>

vue-property-decorator在專案中的應用最主要是起一個裝飾器的作用,差異化的話看對比就非常直觀了

data變數的定義比較多元化,這裡區別有加private,不加就是public,當變數標記為private時,它就不能在宣告它的類的外部訪問。

@Component裝飾器屬性名必須得寫上

@Prop

父子元件之間的屬性傳值

複製程式碼
export default class extends Vue {
    @Prop({ default: 0 }) private propA!: number
    @Prop({ default: () => [10, 20, 30, 50] }) private propB!: number[]
    @Prop({ default: 'total, sizes, prev, pager, next, jumper' }) private propC!: string
    @Prop({ default: true }) private propD!: boolean,
    @prop([String, Boolean]) propE: string | boolean;
}    

等同於

複製程式碼
export default {
  props: {
    propA: {
        type: Number
    },
    propB: {
        type: Array,
        default: [10, 20, 30, 50]
    },
    propC: {
        type: String,
        default: 'total, sizes, prev, pager, next, jumper'
    },
    propD: {
        type: String,
        default: 'total, sizes, prev, pager, next, jumper'
    },
    propE: {
        type: [String, Boolean]
    }
  }
}

這裡有兩個常用修飾符!``?!和可選引數?是相對的, !表示強制解析(也就是告訴typescript編譯器,我這裡一定有值),

你寫?的時候再呼叫,typescript會提示可能為undefined

@Emit

複製程式碼
Component
export default class YourComponent extends Vue {
  count = 0

  @Emit('reset')
  resetCount() {
    this.count = 0
  }

  @Emit()
  returnValue() {
    return 10
  }

  @Emit()
  onInputChange(e) {
    return e.target.value
  }
}

等同於

複製程式碼
export default {
  data() {
    return {
      count: 0
    }
  },
  
  methods: {
    resetCount() {
      this.count = 0
      this.$emit('reset')
    },
    
    returnValue() {
      this.$emit('return-value', 10)
    },
    
    onInputChange(e) {
      this.$emit('on-input-change', e.target.value, e)
    }
  }
}

@Emit裝飾器的函式會在執行之後觸發等同於其函式名(駝峰式會轉為橫槓式寫法)的事件, 並將其函式傳遞給$emit

@Emit觸發事件有兩種寫法

  • @Emit()不傳引數,那麼它觸發的事件名就是它所修飾的函式名.
  • @Emit(name: string),裡面傳遞一個字串,該字串為要觸發的事件名


@Watch 觀察屬性裝飾器

@Watch裝飾器主要用於替代Vue屬性中的watch屬性,監聽依賴的變數值變化而做一系列的操作

複製程式碼
@Component
export default class YourComponent extends Vue {
  @Watch('child')
  onChildChanged(val: string, oldVal: string) {}

  @Watch('person', { immediate: true, deep: true })
  onPersonChanged(val: Person, oldVal: Person) {}
}

等同於

複製程式碼
export default {
  watch: {
    child(val, oldVal) {},
    person: {
        handler(val, oldVal) {},
        immediate: true,
        deep: true
    }
  }
}

watch 是一個物件,物件就有鍵,有值。

  • 第一個handler:其值是一個回撥函式。即監聽到變化時應該執行的函式。
  • 第二個是deep:其值是true或false;確認是否深入監聽。deep的意思就是深入觀察,監聽器會一層層的往下遍歷,給物件的所有屬性都加上這個監聽器(受現代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到物件屬性的新增或刪除)
  • 第三個是immediate:其值是true或false;immediate:true代表如果在 wacth 裡聲明瞭之後,就會立即先去執行裡面的handler方法,如果為 false就跟我們以前的效果一樣,不會在繫結的時候就執行

@Watch使用非常簡單,接受第一個引數為要監聽的屬性名, 第二個屬性為可選物件。@Watch所裝飾的函式即監聽到屬性變化之後應該執行的函式。

@Watch裝飾的函式的函式名並非如上onStateChanged嚴格命名,它是多元化的,你可以隨心所欲的命名,當然,能按照規範化的命名會使你的程式碼閱讀性更好。

複製程式碼
// myMixin.ts

@Component
export default class MyMixin extends Vue {
  mixinValue:string = 'Hello World!!!'
}

// 引用mixins
import MyMixin from './myMixin.js'

@Component
export default class extends mixins(MyMixin) {
  created () {
    console.log(this.mixinValue) // -> Hello World!!!
  }
}

 

Minxins

然後我又偷學到了另外一種mixins寫法,記錄一下

先改造一下myMixin.ts,定義vue/type/vue模組,實現Vue介面

複製程式碼
// myMixin.ts
import { Vue, Component } from 'vue-property-decorator';


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

@Component
export default class myMixins extends Vue {
    mixinValue: string = 'Hello World!!!'
}
 

引用

複製程式碼
import { Vue, Component, Prop } from 'vue-property-decorator';
import MyMixin from './myMixin.js'

@Component({
    mixins: [MyMixin]
})
export default class extends Vue{
    created(){
        console.log(mixinValue) // => Hello World!!!
    }
}

兩種方式不同在於定義mixins時如果沒有定義vue/type/vue模組, 那麼在混入的時候就要繼承該mixins;

如果定義vue/type/vue模組,在混入時可以在@Componentmixins直接混入。

@Provide @Inject

@Provide 宣告一個值 , 在其他地方用 @Inject 接收,在實戰專案中用得不多,一般用於不依賴於任何第三方狀態管理庫(如vuex)的元件編寫


@Ref(refKey?: string)

@Ref裝飾器接收一個可選引數,用來指向元素或子元件的引用資訊。如果沒有提供這個引數,會使用裝飾器後面的屬性名充當引數

複製程式碼
import { Vue, Component, Ref } from 'vue-property-decorator'
import { Form } from 'element-ui'

@Componentexport default class MyComponent extends Vue {
  @Ref() readonly loginForm!: Form
  @Ref('changePasswordForm') readonly passwordForm!: Form

  public handleLogin() {
    this.loginForm.validate(valide => {
      if (valide) {
        // login...
      } else {
        // error tips
      }
    })
  }
}

等同於

複製程式碼
export default {
  computed: {
    loginForm: {
      cache: false,
      get() {
        return this.$refs.loginForm
      }
    },
    passwordForm: {
      cache: false,
      get() {
        return this.$refs.changePasswordForm
      }
    }
  }
}

 

使用時切記要引入修飾器

複製程式碼
import {
    Vue,
    Component,
    Prop,
    Component,
    Emit,
    Provice,
    Inject,
    Watch,
    Model,
    Minxins,
} from 'vue-property-decorator'

 

鉤子函式

以下的public、private在引入tslint後是必寫的,否則會有警告,如果沒有引的話是可以不寫的