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>