vue 初試 typescript

vue 裏使用 ts 需要另外裝兩個包

  "dependencies": {
    "vue-class-component": "^7.2.2",    //  這個是 寫 vue 的官方庫
    "vue-property-decorator": "^8.3.0",   //  這個對vue-class-component 做了一層封裝
    "vuex-class": "^0.3.2"   // 這個是爲了 vuex 的
  },

1、明確賦值斷言

<script lang="ts">
import { Stock } from '@/store/state'
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component({})
export default class SGird extends Vue {
  @Prop({
    type: Array,
    default: () => []
  })
  options: Stock[]
}
</script>

當代碼這樣寫的時候,編輯器會提示錯誤

就是說你沒有給這個只進行初始化,但是事實上,在上面的 @prop 裝時器中已經進行初始化了

所以需要使用

@Prop({
  type: Array,
  default: () => []
})
options!: Stock[]

在冒號前面加上   !   明確賦值斷言,告訴 編輯器,這個已經被賦值了

2、類型斷言

在使用 computed 的時候,這個是一個很常見的需求,返回一個布爾值

  get showPopper(): boolean {
    return (this.showList && this.inputV && this.options.length > 0)
  }

但是這樣同樣會報錯,這個時候就需要進行類型斷言了,就是強行將這個返回值的類型指向  布爾值

  get showPopper(): boolean {
    return (this.showList && this.inputV && this.options.length > 0) as boolean
  }

3、監聽的時候,需要第一時間執行

在vue裏,原本加一個 immediate 就行,但是現在使用了 Watch 的裝飾器之後,寫法就變了

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

@Watch('value', { immediate: true })
  handleValueChange(n: number | string): void {
    if (n !== this.inputV) {
      this.inputV = n
    }
  }

4、使用 debounce

以前的代碼直接使用 debounce 包裝一下自己的函數,這個函數就是防抖的了,但是現在換一種寫法

import { Bind, Debounce } from 'lodash-decorators'  // 導入 lodash包
....

  @Bind()
  @Debounce(300)
  handleInput(val: string): void {
    if (val) {
      this.$store.dispatch('getStockList', {
        payload: { nameOrCode: val }
      })
    } else {
      this.$store.commit('SET_STOCK_LIST', [])
    }
  }

5、event 事件

在 vue @input 之類的事件中,會傳遞一個 event 屬性,當時 一直 以爲是 Vue 的內部屬性,直到去看了文檔

原話是 原生的 DOM 事件,這樣的話,反而就簡單了,直接使用 Event 作爲 類型

6、最後講一下 vuex 的使用

store/state.ts 文件

export interface Option {
  label: string
  value: string | number
  [propName: string]: string | number
}

export interface State {
  seasonList: Array<Option>
}

export const state: State = {
  seasonList: [],
}

store/index.ts文件

import Vue from 'vue'
import Vuex from 'vuex'
import { state, State, Option } from './state'
import api from '@/api/api.js'

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  mutations: {
    SET_SEASON_LIST(state: State, list: Array<Option>) {
      state.seasonList = list
    },
  },
  actions: {
    async getReportList({ commit }) {
      const {
        data: { code, data }
      } = await api.search.reportList({})
      if (code === 200) {
        const list = data.map((d: ReportList) => ({
          label: d.report,
          value: d.date
        }))
        commit('SET_SEASON_LIST', list)
      }
    },
  },
  modules: {}
})

Home.vue文件

<script lang="ts">
import { State } from 'vuex-class'
import { Option } from '@/store/state'
import { Bind, Debounce } from 'lodash-decorators'

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

@Component({
  components: {
  }
})
export default class Home extends Vue {
  created() {
    this.$store.dispatch('getReportList')
  }

  @State private seasonList!: Option[]

}
</script>

7、使用 vuex 的模塊化

同上面的代碼

store/state.ts 文件

export interface Option {
  label: string
  value: string | number
  [propName: string]: string | number
}

export interface ReportList {
  date: string
  report: string
}

/**
* 增加的這個參數,就是爲了 給 actions 傳參的
*/
export interface Payload {
  payload: any
  callback?: (data?: any) => void
}

export interface State {
  seasonList: Array<Option>
}

export const state: State = {
  seasonList: [],
}

store/index.ts文件

import Vue from 'vue'
import Vuex from 'vuex'
import search from './modules/search'

Vue.use(Vuex)

export default new Vuex.Store({
  mutations: {},
  actions: {},
  modules: {
    search
  }
})

store/modules/search.ts文件

import { state, State, Option, Payload } from '../state'
import { ActionContext } from 'vuex'
import api from '@/api/api.js'

const search = {
  namespaced: true,
  state: state,
  mutations: {
    SET_SEASON_LIST(state: State, list: Array<Option>) {
      state.seasonList = list
    },
  },
  actions: {
    async getReportList(
      // 這個類型就是 整個參數的類型,要注意的是
      // 傳進去的兩個泛型一個 一個是當前節點的state,一個是 根節點的 state, 
      // 這裏爲了方便,就是同一個了      ActionContext<State, RootState>
      { commit }: ActionContext<State, State>,   
      // 這裏就是用了自定義的 參數類型
      { payload, callback }: Payload
    ) {
      const {
        data: { code, data }
      } = await api.search.reportList(payload)
      if (code === 200) {
        commit('SET_SEASON_LIST', data)
        callback && callback(data)
      }
    }
  }
}

export default search

  這裏是 vuex 裏面關於 ActionContext 的定義

關於調用:

Home.vue文件

<script lang="ts">
import { State } from 'vuex-class'
import { Option } from '@/store/state'
import { Bind, Debounce } from 'lodash-decorators'

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

@Component({
  components: {
  }
})
export default class Home extends Vue {
  created() {
    this.$store.dispatch('search/getReportList')
  }

  // 在 state 裏面就 實現了 模塊化的提取
  // 在這個時候 private seasonList!: Option[] 這裏的 
  // seasonList 名字也不是固定的,甚至可以叫做 list 等等
  @State(state => state.search.seasonList) private seasonList!: Option[]

}
</script>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章