详解在Vue中使用TypeScript的一些思考(实践)
Vue.extend or vue-class-component使用 TypeScript 写 Vue 组件时,有两种推荐形式:
两种形式输出结果一致,同是创建一个 Vue 子类,但在书写组件选项如 props,mixin 时,有些不同。特别是当你使用 Prop由于组件实例的作用域是孤立的,当从父组件传递数据到子组件时,我们通常使用 Prop 选项。同时,为了确保 Prop 的类型安全,我们会给 Prop 添加指定类型验证,形式如下: ({ message: 'test' })
}
}
}
我们定义了一个 someProp,它的类型是 Object。 使用 JavaScript 时,这并没有什么不对的地方,但当你使用 TypeScript 时,这有点不足,我们并不能得到有关于 someProp 更多有用的信息(比如它含有某些属性),甚至在 TypeScript 看来,这将会是一个 any 类型: 这意味着我们可以使用 someProp 上的任意属性(存在或者是不存在的)都可以通过编译。为了防止此种情况的发生,我们将会给 Prop 添加类型注释。 Vue.extend()使用 interface User {
name: string,age: number } export default Vue.extend({ 当组件内访问 testProps 时,便能得到相关提示: 然而,你必须以函数返回值的形式断言,并不能直接断言: 它会给出错误警告,User 接口并没有实现原生 Object 构造函数所执行的方法: Type 'ObjectConstructor' cannot be converted to type 'User'. Property 'id' is missing in type 'ObjectConstructor'. 实际上,我们可从 Prop type declaration : = { (): T } | { new (...args: any[]): T & object }
export type PropValidator export interface PropOptions<T=any> { 可知 Prop type 可以以两种不同方式出现:
当我们指定 type 类型为 String/Number/Boolean/Array/Object/Date/Function/Symbol 等原生构造函数时,Prop 当 type 类型为 String 构造函数时,它的调用签名返回为 string: interface StringConstructor {
new(value?: any): String; (value?: any): string; readonly prototype: String; fromCharCode(...codes: number[]): string; } 而这也是上文中,当指定 type 类型为 Object 构造函数时,经过 Vue 的声明文件处理,TypeScript 推断出为 any 类型的原因: 类似的,当我们使用关键字 从 type 第二部分可知,除传入原生构造函数外,我们还可传入自定义类: 此外,这里有个 PR 暴露一个更直观的类型( Vue 2.6 版本才可以用):
}
vue-class-component得益于 vue-propperty-decorator Prop 修饰器,当给 Prop 增加类型推断时,这些将变得简单: @Component
export default class Test extends Vue { @Prop({ type: Object }) private test: { value: string } } 当我们在组件内访问 mixinsmixins 是一种分发 Vue 组件中可复用功能的一种方式。当在 TypeScript 中使用它时,我们希望得到有关于 mixins 的类型信息。 当你使用 // other.vue
export default Vue.extend({ mixins: [ExampleMixin],created () { this.testValue // error,testValue 不存在! } }) 我们需要稍作修改: 但这会存在一个问题,当使用多个 mixins 且推断出类型时,这将无法工作。而在这个 Issuse 中官方也明确表示,这无法被修改。 使用 vue-class-component 这会方便很多: @Component
export class ExampleMixin extends Vue { public testValue = 'test' } // other.vue @Component({ 也支持可以传入多个 mixins。 一些其它做为 Vue 中最正统的方法(与标准形式最为接近), 而类做为 TypeScript 特殊的存在(它既可以作为类型,也可以作为值),当我们使用 导入 .vue 时,为什么会报错?当你在 Vue 中使用 TypeScript 时,所遇到的第一个问题即是在 ts 文件中找不到 .vue 文件,即使你所写的路径并没有问题: 在 TypeScript 中,它仅识别 js/ts/jsx/tsx 文件,为了让它识别 .vue 文件,我们需要显式告诉 TypeScript,vue 文件存在,并且指定导出 VueConstructor: 但是,这引起了另一个问题,当我们导入一个并不存在的 .vue 文件时,也能通过编译: 是的,这在情理之中。 当我尝试在 .vue 文件中导入已存在或者不存在的 .vue 文件时,却得到不同的结果: 文件不存在时: 文件存在时: 文件不存在时,引用 Vue 的声明文件。文件存在时,引用正确的文件定义。 这让人很困惑,而这些都是 Vetur 的功劳。 在这个 PR 下,我找到相关解答:这个 PR 里,Vetur 提供解析其他 .vue 文件的功能,以便能获取正确的信息,当 .vue 文件不存在时,会读取 .d.ts 里的信息。 参考https://github.com/vuejs/vue/pull/5887 https://github.com/vuejs/vue/issues/7211 https://github.com/vuejs/vue/pull/6856 https://github.com/vuejs/vue/pull/5887/files/1092efe6070da2052a8df97a802c9434436eef1e#diff-23d7799dcc9e9be419d28a15348b0d99 https://github.com/Microsoft/TypeScript/blob/8e47c18636da814117071a2640ccf87c5f16fcfd/src/compiler/types.ts#L3563-L3583 https://github.com/vuejs/vetur/pull/94 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |