用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象

背景

我个人很喜欢TypeScript也很喜欢Vue,但在两者共同使用的时候遇到一些问题。
Vue的实例化对象代理了所有实际ViewModel对象,具体可参见官方文档
http://vuejs.org.cn/guide/instance.html#属性与方法

Vue的属性与方法:
每个 Vue 实例都会代理其 data 对象里所有的属性

实际上vue实例不仅仅是代理了data属性,还代理了methods属性、computed属性等,可以通过这篇文档 看到。那么怎么在TypeScript里面通过vue实例访问data属性和methods属性里面的变量是最大问题,否则就没办法使用TS的最大的作用——强类型检查。

如下图可以看到:

虽然实际上vm.xxcanghaiFn是可用的,但是过不了TypeScript的编辑检查,提示不在'xxcanghaiFn'不在'Vue'类型中。
因为类型'Vue'中肯定只有内部方法,自然会报错,虽然我们可以通过<any>语法强制使语法检查失效,如下代码:

  1. var vm: any = new Vue({//vm变量增加any声明
  2. el: "#app",
  3. data: {
  4. xxcanghaiData: "xxcanghai"
  5. },
  6. methods: {
  7. xxcanghaiFn: function () { }
  8. }
  9. });
  10. vm.xxcanghaiFn//无编译器报错

虽然没有编译器报错,但同时也无法再使用TS提供的智能补全,强类型检查等功能。这就跟直接写js没有任何区别了。

解决方案

  1. 将data属性,以及methods等需要合并进vue类型的对象分开写
  2. 利用TypeScript的typeofdeclare关键字将类型合并声明。
  3. 最后new Vue时强制用<any>声明并赋值。

如下代码:

  1. //核心声明,利用typeof将data和methods属性合并进Vue类型
  2. declare var VM: typeof vmData & typeof vmMethods & vuejs.Vue;
  3. var vmData = {
  4. xxcanghaiData: "xxcanghai"
  5. };
  6. var vmMethods = {
  7. xxcanghaiFn: () => { }
  8. }
  9. var vm: typeof VM = <any>new Vue({
  10. el: "#app",
  11. data: vmData,
  12. methods: <any>vmMethods
  13. });

效果如下,既可以实现识别Vue内置函数及属性:

也能实现识别我们自定义的data属性和methods属性中的值:

关于Vue中的计算属性类型

Vue中有一种特殊的ViewModel的属性——计算属性
计算属性在使用ts的强类型的时候就会出错,代码如下:

  1. declare var VM: vuejs.Vue & typeof vmComputed;
  2. var vmComputed = {
  3. /**
  4. * 字符串计算属性
  5. */
  6. xxcanghaiCom: function () {
  7. return "xxcanghaiCom";
  8. }
  9. }
  10. var vm: typeof VM = <any>new Vue({
  11. el: "#app",
  12. computed: <any>vmComputed
  13. });

计算属会被ts的类型系统识别为一个函数,而出现函数相关的方法,此时调用字符串方法自然会报错。如图:

虽然计算属性实际上确实是一个函数,但是我们希望能够把计算属性拿来当一个字符串变量来使用。

TypeScript的强制类型声明语法

这里可以使用ts的强制类型声明语法 <TYPE>,来把指定类型强制声明为其他类型,如下:

  1. var a;
  2. (<string>a).charAt(0);//合法
  3. (<number>a).toFixed();//合法

强制类型声明的局限性

但是此语法也有局限性,即只能强制声明那些未知类型的变量,不能强制声明已知类型的变量,如下:

  1. var a = 0;
  2. (<string>a);//报错 Neither type 'number' nor type 'string' is assignable to the other.

因为变量a已经可以被类型推断出为number类型了,遂不能再强制声明为string类型。

计算属性类型的解决方案

解决方案为 利用any类型中转来实现强制类型声明转换。
在TypeScript中的any类型的规则为:

1、任何类型都可以被转换为any类型。
2、any 类型可以转换为任何类型。

所以先将计算属性的函数,或是getter,setter的Object声明为any类型,再声明为你想实际使用的变量类型。如下:

  1. declare var VM: vuejs.Vue & typeof vmComputed;
  2. var vmComputed = {
  3. /**
  4. * 字符串计算属性
  5. */
  6. xxcanghaiCom: <string>(<any>function () {
  7. return "xxcanghaiCom";
  8. }),
  9. /**
  10. * getter和setter形式的字符串计算属性
  11. */
  12. xxcanghaiGetSet: <string>(<any>{
  13. get: function () {
  14. return vm.xxcanghaiCom;
  15. },
  16. set: function (newVal: string) {
  17. vm.xxcanghaiCom = newVal;
  18. }
  19. })
  20. }
  21. var vm: typeof VM = <any>new Vue({
  22. el: "#app",
  23. computed: <any>vmComputed
  24. });

效果如下图,虽然xxcanghaiGetSet是object,但此处可以按照我们想要的string类型来使用。

后记

本文比较初级,因为刚刚开始接触Vue,因为之前用过Angular和Avalon,所以上手起来还算舒服,之前用Angular的时候就因为用TypeScript写非常难受,遂打算好好研究下TypeScript与Vue的协同工作的问题。
写的比较匆忙,vue也还没有完全了解,遂文中有不对的地方欢迎指正。:-)

如果您认为本文对得起您所阅读他所花的时间,欢迎点击右下角推荐。您的支持是我继续写作最大的动力,谢谢

作者:小小沧海

TypeScript开发Vue的更多相关文章

  1. 用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象

    用TypeScript开发Vue--如何通过vue实例化对象访问实际ViewModel对象 背景 我个人很喜欢TypeScript也很喜欢Vue,但在两者共同使用的时候遇到一个问题. Vue的实例化对 ...

  2. 使用 typescript 开发 Vue

    基础配置: 1. 准备一个使用 vue-cli 生成的项目 2. 使用 npm 一建安装基础配置 npm i -S @types/node typescript vue-class-component ...

  3. Vue使用Typescript开发编译时提示“ERROR in ./src/main.ts Module build failed: TypeError: Cannot read property 'afterCompile' of undefined”的解决方法

    使用Typescript开发Vue,一切准备就绪.但npm start 时,提示“ ERROR in ./src/main.tsModule build failed: TypeError: Cann ...

  4. TypeScript编写Vue项目结构解析

    使用TypeScript编写Vue项目也已经有了一段时间,笔者在刚刚使用TypeScript时候也是很茫然,不知道从何下手,感觉使用TypeScript写项目感觉很累赘并不像JavaScript那么灵 ...

  5. 001——Typescript 介绍 、Typescript 安 装、Typescript 开发工具

    一. Typescript 介绍 1. TypeScript 是由微软开发的一款开源的编程语言. 4. TypeScript 是 Javascript 的超级,遵循最新的 ES6.Es5 规范.Typ ...

  6. 使用 VS Code 搭建 TypeScript 开发环境

    使用 VS Code 搭建 TypeScript 开发环境 TypeScript 是 JavaScript 的超集,TypeScript 只是增强了 JavaScript 而非改变了 JavaScri ...

  7. 搜狗高级架构师帮你系统掌握TypeScript开发

    JavaScript 是一门动态弱类型语言,对变量的类型非常宽容,而且不会在这些变量和它们的调用者之间建立结构化的契约. Angular 已经使用 TypeScript 重构了代码,另一大前端框架 V ...

  8. 如何用TypeScript开发微信小程序

    微信小程序来了!这个号称干掉传统app的玩意儿虽然目前处于内测阶段,不过目前在应用号的官方文档里已经放出了没有内测号也能使用的模拟器了. 工具和文档可以参考官方文档:https://mp.weixin ...

  9. 使用TypeScript开发

    学习过一段时间CoffeeScript,然后再学习TypeScript,最后还是决定使用TypeScript开发. CofeeScript主要是给js添加一些语法糖,编写代码要快捷的多,少量的代码开发 ...

随机推荐

  1. laravel跟jquery之间传输json数据

    laravel代码: public function test(){ $arr = ["test1"=>"1","test2"=> ...

  2. Selenium2Library关键字

    对Selenium2Library关键字的整理和翻译.英文不好,仅供参考. 1.Add Cookie [ name | value | path=None | domain=None | secure ...

  3. python的工作记录B

    这次很强了.就差最后一步,判断一下SVN的版本是否是真的库里的. #!/usr/bin/env python # -*- coding: utf-8 -*- import os,sys,command ...

  4. 这样就算会了PHP么?-2

    学些关于函数FUNCTION方面的东东.. 感觉和PYTHON的APLLY功能差不多.. <?php function come(){ echo "来啦<p>"; ...

  5. TVS管

    1.原理 TVS二极管在线路板上与被保护线路并联,当瞬时电压超过电路正常工作电压后,TVS二极管便产生雪崩,提供给瞬时电流一个超低电阻通路,其结果是瞬时电流透过二极管被引开,避开被保护元件,并且在电压 ...

  6. cocos2d-x Loading界面实现资源加载

    有时候场景中的资源加载过多的话就会引起游戏进入的时候很卡,因为那是边加载边显示.在tests例子里面有一个很好的例子叫做TextureCacheTest,里面讲解了如何写loading. #inclu ...

  7. Eclipse中安装TestNG插件

    在Eclipse中安装TestNG也像安装其他插件一样非常方便,如下: 选择菜单:Help->Install New Software,然后在弹出窗口中的“Work with”中输入地址: ht ...

  8. pmp论坛

    PMP论坛: http://www.px101.com/specialpmp/ http://www.pmp.cn/ http://www.pmptuan.com/ http://www.mypm.n ...

  9. mv,Directory not empty不能目录覆盖

    一.mv /test1/* /test2/test1rm -rf /test1 二. You can however use rsync with the --remove-source-files ...

  10. NOI2012 魔幻棋盘

    http://www.lydsy.com/JudgeOnline/problem.php?id=2877 二维线段树. 好恶...... B类数据: 棋盘是一维的. 我们有一个结论: $gcd(a_{ ...