用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>语法强制使语法检查失效,如下代码:

var vm: any = new Vue({//vm变量增加any声明
el: "#app",
data: {
xxcanghaiData: "xxcanghai"
},
methods: {
xxcanghaiFn: function () { }
}
}); vm.xxcanghaiFn//无编译器报错

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

解决方案

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

如下代码:

//核心声明,利用typeof将data和methods属性合并进Vue类型
declare var VM: typeof vmData & typeof vmMethods & vuejs.Vue;
var vmData = {
xxcanghaiData: "xxcanghai"
};
var vmMethods = {
xxcanghaiFn: () => { }
}
var vm: typeof VM = <any>new Vue({
el: "#app",
data: vmData,
methods: <any>vmMethods
});

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



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



关于Vue中的计算属性类型

Vue有有一种特殊的ViewModel的属性——计算属性。

计算属性在使用ts的强类型的时候就会出错,代码如下:

declare var VM: vuejs.Vue & typeof vmComputed;
var vmComputed = {
/**
* 字符串计算属性
*/
xxcanghaiCom: function () {
return "xxcanghaiCom";
}
}
var vm: typeof VM = <any>new Vue({
el: "#app",
computed: <any>vmComputed
});

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



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

TypeScript的强制类型声明语法

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

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

强制类型声明的局限性

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

var a = 0;
(<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类型,再声明为你想实际使用的变量类型。如下:

declare var VM: vuejs.Vue & typeof vmComputed;
var vmComputed = {
/**
* 字符串计算属性
*/
xxcanghaiCom: <string>(<any>function () {
return "xxcanghaiCom";
}),
/**
* getter和setter形式的字符串计算属性
*/
xxcanghaiGetSet: <string>(<any>{
get: function () {
return vm.xxcanghaiCom;
},
set: function (newVal: string) {
vm.xxcanghaiCom = newVal;
}
})
}
var vm: typeof VM = <any>new Vue({
el: "#app",
computed: <any>vmComputed
});

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



后记

本文比较初级,因为刚刚开始接触Vue,因为之前用过Angular和Avalon,所以上手起来还算舒服,之前用Angular的时候就因为用TypeScript写非常难受,遂打算好好研究下TypeScript与Vue的协同工作的问题。

写的比较匆忙,vue也还没有完全了解,遂文中有不对的地方欢迎指正。

用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象的更多相关文章

  1. vue构造函数(根实例化时和组件实例对象选项)参数:选项详解

    实例选项(即传给构造函数的options):数据,DOM,生命周期钩子函数,资源,组合,其他 数据 data 属性能够响应数据变化,当这些数据改变时,视图会进行重渲染. 访问方式: 1.通过 vm.$ ...

  2. TypeScript开发Vue

    用TypeScript开发Vue——如何通过vue实例化对象访问实际ViewModel对象 目录 背景 解决方案 关于Vue中的计算属性类型 TypeScript的强制类型声明语法 强制类型声明的局限 ...

  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

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

  5. Vue 开发技巧或者说Vue知识点梳理(转,自个学习)

    Vue 组件通讯 ——常见使用场景可以分为三类: 父子通信: 父向子传递数据是通过 props,子向父是通过 events($emit):通过父链 / 子链也可以通信($parent / $child ...

  6. 使用@vue/cli搭建vue项目开发环境

    当前系统版本 mac OS 10.14.2 1.安装node.js开发环境 前端开发框架和环境都是需要 Node.js  vue的运行是要依赖于node的npm的管理工具来实现 <mac OS ...

  7. 前端开发组件化设计vue,react,angular原则漫谈

    前端开发组件化设计vue,react,angular原则漫谈 https://www.toutiao.com/a6346443500179505410/?tt_from=weixin&utm_ ...

  8. Vue.js_构造器及其实例化概念

    Vue构造器 1.Vue.js是一个构造函数,编程中称之为构造器 2.每一个new Vue() 都是一个Vue构造函数的实例,这个过程叫做实例化 3.构造函数需要将其实例化后才会启用 var vm = ...

  9. beego-vue URL重定向(beego和vue前后端分离开发,beego承载vue前端分离页面部署)

    具体过程就不说,是搞这个的自然会动,只把关键代码贴出来. beego和vue前后端分离开发,beego承载vue前端分离页面部署 // landv.cnblogs.com //没有授权转载我的内容,再 ...

随机推荐

  1. JQuery插件:遮罩+数据加载中。。。(特点:遮你想遮,罩你想罩)

    在很多项目中都会涉及到数据加载.数据加载有时可能会是2-3秒,为了给一个友好的提示,一般都会给一个[数据加载中...]的提示.今天就做了一个这样的提示框. 先去jQuery官网看看怎么写jQuery插 ...

  2. 按要求编写Java应用程序。 (1)创建一个叫做机动车的类: 属性:车牌号(String),车速(int),载重量(double) 功能:加速(车速自增)、减速(车速自减)、修改车牌号,查询车的载重量。 编写两个构造方法:一个没有形参,在方法中将车牌号设置“XX1234”,速 度设置为100,载重量设置为100;另一个能为对象的所有属性赋值; (2)创建主类: 在主类中创建两个机动车对象。 创建第

    package com.hanqi.test; public class jidongche { private String chepaihao;//车牌号 private int speed;// ...

  3. HTTP状态码206和416

    HTTP 2xx范围内的状态码表明了:"客户端发送的请求已经被服务器接受并且被成功处理了". TTP/1.1 200 OK是HTTP请求成功后的标准响应 HTTP/1.1 206状 ...

  4. SQLHelp帮助类

    public readonly static string connStr = ConfigurationManager.ConnectionStrings["conn"].Con ...

  5. WIN 下的超动态菜单(二)用法

    WIN 下的超动态菜单(一)简介 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/     ...

  6. android EditText光标位置(定位到最后)

    方法:edittext.setSelection(int); et.setText(content);//设置EditText控件的内容et.setSelection(content.length() ...

  7. 如何更改nginx网站根目录 以及解析php

    nginx默认网站根目录为/usr/local/nginx/html,如果想要将它改成/data/www 需配置 vim /usr/local/nginx/conf/nginx.conf 将其中的字段 ...

  8. Hive分析hadoop进程日志

    想把hadoop的进程日志导入hive表进行分析,遂做了以下的尝试. 关于hadoop进程日志的解析 使用正则表达式获取四个字段,一个是日期时间,一个是日志级别,一个是类,最后一个是详细信息, 然后在 ...

  9. Python教程[廖雪峰],主要是实践

  10. laravel administrator 一款通用的后台插件(PHP框架扩展)

    前几天我看了一下zend framework 2的一些官方文档,也找了一些例子,可惜所有的资料少之甚少.于是我就开始去找这国外用的比较流行的PHP框架laravel,希望能够找到其合适的例子,而且我本 ...