Vue3 + TypeScript 实践总结

为什么 TypeScript

Vue2.x 对 TypeScript 的支持是硬伤,而 TypeScript 对于大型项目更加友好,团队协作时强类型总比约定更严谨。所以,一些大型工程在技术选型时,抛弃 Vue 而选择 React。尤其是在 React16.8+ 函数式组件有状态以后。

为什么会出现 setup

首先,Vue 只是 MVC 中的 View 层,需要将 Model、Controller 分离开才能最大化地降低耦合、增加复用。即Vue 单文件组件应该只是处理视图层的业务逻辑及渲染即可,而 Controller 的业务逻辑不应该在单文件组件中,因此诞生了 Vuex,而 Vuex 更多是一个全局状态管理,在处理一些业务逻辑、数据交互、组件通信上,使用 Vuex 来管理显得太重了。因而在 View 与 Controller 的业务逻辑处理上,有了一个真空地带,导致我们在 methods 中耦合了大量的业务逻辑,随着版本不断迭代,一旦体量变大,公共方法的抽离、代码维护的成本指数倍增长,组件已变得不可复用,难以阅读,能做的只能继续往上面堆;

其次,一些需要响应式的公共属性、方法,我们通常引入 mixin 来隔离,但是 mixin 不太好管理,容易污染。

不难发现,业务逻辑耦合度变高后,最终导致 Vue 单文件组件的作为 View 层,页面 UI 哪怕相似度极高,也可能无法复用。

高内聚、低耦合,对于 Vue 来说,即需要能够分离业务逻辑关注点、易管理、响应式的API,setup 为了这而产生。

Vue 实践

Props 自身的 type 属性无法描述更复杂的数据结构,TS 会报错

Vue 提供了类型别名 PropType,用于定义接收的更复杂的 props 属性结构。

import { PropType, defineComponent, RendererElement } from 'vue';

interface ITabItem {
text: string,
id: string | number,
active?: boolean
}

const XComponent = defineComponent({
props: {
tabList: {
type: Array as PropType>,
default: () => []
}
},
setup() {
return (): RendererElement => (

{
props.tabList.map(tab => {
return

{tab.text}


})
}

)
}
})

单文件 vue 组件与 tsx 函数组件间的 slot 使用

单文件 vue 组件互相之间的 slot 使用,可阅读官方文档 单文件插槽

jsx/tsx 组件互相之间的 slot 使用,可以阅读文档 jsx/tsx 插槽

单文件同 jsx、tsx 组件之间的 slot 使用,示例如下:

// vue 单文件中引入 tsx 函数式组件 XInput