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>