天天看點

用TypeScript開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

用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的最大的作用——強類型檢查。

如下圖可以看到:

用TypeScript開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

雖然實際上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内置函數及屬性:

用TypeScript開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

也能實作識别我們自定義的data屬性和methods屬性中的值:

用TypeScript開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

關于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開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

雖然計算屬性實際上确實是一個函數,但是我們希望能夠把計算屬性拿來當一個字元串變量來使用。

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

類型來使用。

用TypeScript開發Vue——如何通過vue執行個體化對象通路實際ViewModel對象

後記

本文比較初級,因為剛剛開始接觸Vue,因為之前用過Angular和Avalon,是以上手起來還算舒服,之前用Angular的時候就因為用TypeScript寫非常難受,遂打算好好研究下TypeScript與Vue的協同工作的問題。

寫的比較匆忙,vue也還沒有完全了解,遂文中有不對的地方歡迎指正。😃

如果您認為本文對得起您所閱讀他所花的時間,歡迎點選右下角↘ 推薦。您的支援是我繼續寫作最大的動力,謝謝

作者:小小滄海

出處:http://www.cnblogs.com/xxcanghai/

本文位址:http://www.cnblogs.com/xxcanghai/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

繼續閱讀