[轉] 純TypeScript開發Web前端(二)如何引入JS庫


背景

        總所周知,TS需要編譯成JS才能在瀏覽器上跑,TS也能夠調用JS的方法。但是,有一個現成的第三方JS類庫擺在面前,讓它如何能在TS中使用,很多剛入坑的朋友往往不得其門而入。下面我就講講我的辦法吧。

1、直接翻譯

        看了上面4個字,大家可能不會不約而同地眉頭一皺,立刻開噴:“喔靠,餿主意!”。我承認,這的確是個笨辦法,但是我的確這么做過。笨辦法也是辦法,重劍無鋒,大巧不工。
        對於一些JS庫只有不到200-300行代碼,直接翻譯成TS又何妨呢?自己用TS重寫,跟找typings(很多不一定能找到)或者自己寫*.d.ts的時間其實差不了多少。自己動手,也能加深對庫的理解,夯實自己。

2、頁面引入 + 全局定義

        如果對第一條不滿意,不用着急,咱還有別的辦法。第二招,其實也很簡單粗暴。所謂“頁面引入”就是最常規的用<script>標簽把js直接在html頁面引入,然后“全局定義”,就是聲明一個變量跟JS的全局變量名或者方法名一樣。
        下面用大家非常熟悉的jQuery舉例吧。

頁面里直接用<script>標簽引入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引用成功!");
  }
}

 

        簡單粗暴的副作用就是不夠優雅,聲明的全局變量$的類型只能是any,這意味着還是弱類型變量,因此IDE中沒有任何的方法和屬性還有類型的提示。因而,完全失去了寫TS的樂趣。下面重點說說怎樣做到優雅。

3、類型定義文件(.d.ts)

        相信閣下如果看本文之前百度過,肯定看過這種方法。說明,這是主流。所以,我也准備重點詳細地介紹一下。

  • 首先,什么是類型定義文件?

應該有點類似於C++后綴名為.h的頭文件,用於聲明JS主文件的函數接口和變量類型的定義,並且把這些定義暴露給TS使用。有了.d.ts的定義之后,TS就能感知到JS庫相關的代碼提示了。

  • 接着,如何得到.d.ts文件?
    1.可以先去DefinitelyTyped找找碰碰運氣,一般很流行的庫也許會有。
    2.用npm的typings查找獲取的,其實跟上面沒什么兩樣。
    3.網上還能還有一些工具,據說根據js庫能夠反向生成.d.ts。我試了都不靠譜,如果是C#生成.d.ts的成功率我是敢打包票,但是對JS我就只能呵呵了。
    4.最后,“拿來主義”都不行的情況下,只有自己動手豐衣足食了。

自己做.d.ts之前,先分析一下js庫的代碼,看看自己需要什么接口就定義什么。那些自己用不着的大可放過。
例如,我早前做的marked.js,節選一些代碼:

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的結構定義。這樣,我在TS調用就能用得很舒服了!至於,最后幾行的declare為什么那么寫?那是TS語法的套路,我這里就不多做解釋,能用就行。好奇寶寶們可以進入傳送門深入理解一下。

最后說一下,.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,講完,收工。



作者:ChenReal
鏈接:https://www.jianshu.com/p/3b154d6e231b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM