背景
? ? ? ? 總所周知,TS需要編譯成JS才能在瀏覽器上跑碰逸,TS也能夠調(diào)用JS的方法。但是阔加,有一個現(xiàn)成的第三方JS類庫擺在面前饵史,讓它如何能在TS中使用,很多剛?cè)肟拥呐笥淹坏闷溟T而入胜榔。下面我就講講我的辦法吧胳喷。
1、直接翻譯
? ? ? ? 看了上面4個字夭织,大家可能不會不約而同地眉頭一皺吭露,立刻開噴:“喔靠,餿主意尊惰!”讲竿。我承認(rèn),這的確是個笨辦法弄屡,但是我的確這么做過题禀。笨辦法也是辦法,重劍無鋒琢岩,大巧不工投剥。
? ? ? ? 對于一些JS庫只有不到200-300行代碼,直接翻譯成TS又何妨呢担孔?自己用TS重寫江锨,跟找typings(很多不一定能找到)或者自己寫*.d.ts的時間其實差不了多少吃警。自己動手,也能加深對庫的理解啄育,夯實自己酌心。
2、頁面引入 + 全局定義
? ? ? ? 如果對第一條不滿意挑豌,不用著急安券,咱還有別的辦法。第二招氓英,其實也很簡單粗暴侯勉。所謂“頁面引入”就是最常規(guī)的用<script>
標(biāo)簽把js直接在html頁面引入,然后“全局定義”铝阐,就是聲明一個變量跟JS的全局變量名或者方法名一樣址貌。
? ? ? ? 下面用大家非常熟悉的jQuery舉例吧。
頁面里直接用<script>標(biāo)簽引入jquery.js
<html>
<head>
<script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<body>
......
TS中聲明全局變量
$
徘键,然后就可以直接開擼
declare var $;
class App {
init(){
$("#msg").html("jquery引用成功!");
}
}
? ? ? ? 簡單粗暴的副作用就是不夠優(yōu)雅练对,聲明的全局變量$
的類型只能是any,這意味著還是弱類型變量吹害,因此IDE中沒有任何的方法和屬性還有類型的提示螟凭。因而,完全失去了寫TS的樂趣它呀。下面重點說說怎樣做到優(yōu)雅螺男。
3、類型定義文件(.d.ts)
? ? ? ? 相信閣下如果看本文之前百度過钟些,肯定看過這種方法烟号。說明绊谭,這是主流政恍。所以,我也準(zhǔn)備重點詳細(xì)地介紹一下达传。
- 首先篙耗,什么是類型定義文件?
應(yīng)該有點類似于C++后綴名為.h的頭文件宪赶,用于聲明JS主文件的函數(shù)接口和變量類型的定義宗弯,并且把這些定義暴露給TS使用。有了.d.ts的定義之后搂妻,TS就能感知到JS庫相關(guān)的代碼提示了蒙保。
- 接著,如何得到.d.ts文件欲主?
1.可以先去DefinitelyTyped找找碰碰運氣邓厕,一般很流行的庫也許會有逝嚎。
2.用npm的typings查找獲取的,其實跟上面沒什么兩樣详恼。
3.網(wǎng)上還能還有一些工具补君,據(jù)說根據(jù)js庫能夠反向生成.d.ts。我試了都不靠譜昧互,如果是C#生成.d.ts的成功率我是敢打包票挽铁,但是對JS我就只能呵呵了。
4.最后敞掘,“拿來主義”都不行的情況下叽掘,只有自己動手豐衣足食了。
自己做.d.ts之前玖雁,先分析一下js庫的代碼够掠,看看自己需要什么接口就定義什么。那些自己用不著的大可放過茄菊。
例如疯潭,我早前做的marked.js,節(jié)選一些代碼:
marked.options =
marked.setOptions = function(opt) {
merge(marked.defaults, opt);
return marked;
};
marked.getDefaults = function () {
return {
baseUrl: null,
breaks: false,
gfm: true,
headerIds: true,
headerPrefix: '',
highlight: null,
langPrefix: 'language-',
mangle: true,
pedantic: false,
renderer: new Renderer(),
sanitize: false,
sanitizer: null,
silent: false,
smartLists: false,
smartypants: false,
tables: true,
xhtml: false
};
};
marked.defaults = marked.getDefaults();
/**
* Expose
*/
marked.Parser = Parser;
marked.parser = Parser.parse;
marked.Renderer = Renderer;
marked.TextRenderer = TextRenderer;
marked.Lexer = Lexer;
marked.lexer = Lexer.lex;
marked.InlineLexer = InlineLexer;
marked.inlineLexer = InlineLexer.output;
marked.Slugger = Slugger;
marked.parse = marked;
這一段面殖,很直觀地看出它有什么接口可以暴露出來了竖哩。其實,我只需要一個parse
的方法足矣脊僚。那么相叁,我的marked.d.ts就會這么寫。
interface MDOption {
baseUrl?: string;
breaks?: boolean;
gfm?: boolean;
headerIds?: boolean;
headerPrefix?: string;
highlight?: any;
langPrefix?: string;
mangle?: boolean;
pedantic?: boolean;
sanitize?: boolean;
sanitizer?: any;
silent?: boolean;
smartLists?: boolean;
smartypants?: boolean;
tables?: boolean;
xhtml?: boolean;
}
interface MarkDown {
parse(src: string, opt?: MDOption, callback?: Function);
}
declare module "marked" {
export = marked;
}
declare var marked: MarkDown;
方法定義只有MarkDown.parse
一個辽幌,外加一個MDOption
的結(jié)構(gòu)定義增淹。這樣,我在TS調(diào)用就能用得很舒服了乌企!至于虑润,最后幾行的declare為什么那么寫?那是TS語法的套路加酵,我這里就不多做解釋拳喻,能用就行。好奇寶寶們可以進(jìn)入傳送門深入理解一下猪腕。
最后說一下冗澈,.d.ts怎么使用。直接上代碼:
///<reference path="../typings/marked.d.ts" />
import * as marked from "marked";
var md_html = marked.parse("### Hello TypeScript");
1.引用路徑
2.引入模塊
3.使用方法
很簡單的三行代碼
至于陋葡,主體庫mark.js怎么引入頁面亚亲,方法很多,八仙過海各顯神通。我用的是require.js捌归。
require.config({
paths: {
'jquery': '//g.alicdn.com/sj/lib/jquery/dist/jquery.min',
'marked': '/js/lib/marked.min'
}
});
OK颊亮,講完,收工陨溅。