都这么写了,为什么还要用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的描述是:
虽然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
完。
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: XxjzZ 原文链接:https://juejin.im/post/6844904144881319949