为什么使用TypeScript开发vue2.x体验很差?__Vue.js
发布于 4 年前 作者 banyungong 2434 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

都这么写了,为什么还要用ts?

                                                                                                               ——来自我的日常吐槽

“为什么使用TypeScript开发vue2.x体验很差?”,这句话不仅是一句吐槽,也是一种疑惑。

吐槽的是:花费了更多的时间,使用TypeScript构建出的类型安全的代码,在书写Vue模板时竟然完全用不上。

疑惑的是:为什么React跟TypeScript结合的那么好,而Vue却一塌糊涂?

追根溯源——现在这种窘境是源于何处

自从Vue出现以来,社区就一直在寻找使用OO开发Vue的方法,并产出了许多优秀的库,比如vue-class-component。这个库非常关键,它不仅给予了我们以OO的方式开发Vue程序的能力,更为使用TypeScript开发Vue程序带来了可能。

我们知道Vue是一个object-based框架,而不是class-based。TypeScript作为一个编译时的检查工具,它的能力范围仅限于class/function的校验。因此,TypeScript和基于object的Vue的开发方式是不兼容且没有意义的。而vue-class-component提供了一个修饰器,它内部会把class的属性和方法转化为Vue options,这样我们就能用class去写Vue组件,使用TypeScript也因此变得有意义了。

实践中,我们还会结合使用vue-property-decorator这个库,它基于vue-class-component提供的自定义decorator能力,很好的提升了我们使用TypeScript开发Vue的体验。

因此,我们逐渐形成了Vue+TypeScript+vue-class-component+vue-property-decorator的技术栈体系,以OO的方式开发Vue程序,痛并快乐着。

痛点1——template校验

通常情况下,我们使用SFC(Single File Component)开发Vue程序。与React的“All in JS”不同,在这个过程中,视图和逻辑是分离的。我们的逻辑写在script标签,而视图写template模板中。视图层在这里不是ts代码,而是单纯的字符串。

另一方面,对于TypeScript来说,它只能处理ts或者tsx,对于字符串是无能为力的。除非,我们提供一个额外的工具,实时把模板字符串转化成ts或tsx代码,TypeScript才“有可能”去分析。

因此template的类型校验一直是TypeScript+Vue2.x开发中的主要痛点。

实际上Vetur就是这种工具,但是在Vue2.x时代,他们没有做这件事。但幸运的是,在即将到来的Vue3时代,Vetur已经做好准备了。https://github.com/vuejs/rfcs/issues/64

痛点2——jsx校验

为了更灵活的编写视图层代码,JSX是必不可少的。但是头疼的是,基于现有的技术栈,TypeScript对于vue的JSX支持并不友好,基本没有类型检查的能力。说到这里,又回到了最开始的疑惑:为什么React跟TypeScript结合的那么好,而Vue却一塌糊涂?实际上这个锅不在TypeScript,而在于我们自己和Vue本身。

TypeScript从1.6开始支持JSX,它对JSX的描述是:

JSX is an embeddable XML-like syntax. It is meant to be transformed into valid JavaScript, though the semantics of that transformation are implementation-specific. JSX rose to popularity with the React framework, but has since seen other implementations as well. TypeScript supports embedding, type checking, and compiling JSX directly to JavaScript.

虽然TypeScript对JSX的定义很大程度上参考了React的JSX,但是TypeScript提供了一系列的配置,这允许我们自定义JSX。因此,只要我们利用好这些配置,我们就有机会让TypeScript去检查Vue版本的JSX。

实践中,我们一般使用这样的配置来定义TypeScript的JSX:


然而,这个配置远不能让TypeScript很好的工作。因为这里面只定义了Element、ElementClass、IntrinsicElements这三个类型,而最关键的ElementAttributesProperty并没有给出定义,这也就导致TypeScript无法去检查用户自定义组件的props,TypeScript的类型检查形同虚设。

关于这些属性的含义需要详细阅读:https://www.typescriptlang.org/docs/handbook/jsx.html

对于React来说,官方已经提供了非常完善的JSX定义,同时还有着“TypeScript的JSX很大程度上参考了React的JSX”这样的天然优势,因此TypeScript对React的JSX的兼容性非常好。但是对于Vue2.x来说,不仅官方没有提供完善的JSX定义,在JSX格式上于React的JSX也有很大不同(比如Element的props/children属性)。因此TypeScript对于Vue2.x的JSX兼容性非常差。

但是从另一方面说,只要我们去完善这个JSX的配置,补充上ElementAttributesProperty等缺失定义,也许我们就能让TypeScript真正的跑在Vue2.x的程序中。关于这个问题,会在后续文章里详细分析,在这里先不展开了。

结论

TypeScript和Vue的兼容性:

版本

业务逻辑

template

render函数

Vue2.x

✅(需借助vue-class-component)

❌(没有工具链支持)

✅(需要自己配置好TypeScript的JSX定义,一般会借助vue-tsx-support这个库)

Vue3.x

✅(工具链支持)

✅(TypeScript的JSX定义内置)

参考

https://www.typescriptlang.org/docs/handbook/jsx.html

https://www.zhihu.com/question/310485097/answer/591869966

https://github.com/vuejs/vue-class-component

https://github.com/kaorun343/vue-property-decorator

https://github.com/wonderful-panda/vue-tsx-support

完。

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: XxjzZ 原文链接:https://juejin.im/post/6844904144881319949

回到顶部