用TypeScript開發Vue——如何經過vue實例化對象訪問實際ViewModel對象

用TypeScript開發Vue——如何經過vue實例化對象訪問實際ViewModel對象

背景

我我的很喜歡TypeScript也很喜歡Vue,但在二者共同使用的時候遇到一個問題。
Vue的實例化對象代理了全部實際ViewModel對象,具體可參見官方文檔
http://vuejs.org.cn/guide/instance.html#屬性與方法html

Vue的屬性與方法:
每一個 Vue 實例都會代理其 data 對象裏全部的屬性vue

實際上vue實例不單單是代理了data屬性,還代理了methods屬性、computed屬性等,能夠經過 這篇文檔 看到。那麼怎麼在TypeScript裏面經過vue實例訪問data屬性和methods屬性裏面的變量是最大問題,不然就沒辦法使用TS的最大的做用——強類型檢查。typescript

以下圖能夠看到:
app

雖然實際上vm.xxcanghaiFn是可用的,可是過不了TypeScript的編輯檢查,提示不在'xxcanghaiFn'不在'Vue'類型中。
由於類型'Vue'中確定只有內部方法,天然會報錯,雖然咱們能夠經過<any>語法強制使語法檢查失效,以下代碼:ide

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的typeofdeclare關鍵字將類型合併聲明。
  3. 最後new Vue時強制用<any>聲明並賦值。

以下代碼:ui

//核心聲明,利用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內置函數及屬性:
3d

也能實現識別咱們自定義的data屬性和methods屬性中的值:
代理

關於Vue中的計算屬性類型

Vue有有一種特殊的ViewModel的屬性——計算屬性
計算屬性在使用ts的強類型的時候就會出錯,代碼以下:code

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類型的規則爲:

一、任何類型均可以被轉換爲any類型。
二、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也尚未徹底瞭解,遂文中有不對的地方歡迎指正。:-)

相關文章
相關標籤/搜索