<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Chen's Blog</title>
 <link href="http://imzc.me/atom.xml" rel="self"/>
 <link href="http://imzc.me/"/>
 <updated>2017-10-23T12:00:14+00:00</updated>
 <id>http://imzc.me</id>
 <author>
   <name>Chen Zhang</name>
   <email></email>
 </author>

 
 <entry>
   <title>TypeScript 进阶：给第三方库编写声明文件</title>
   <link href="http://imzc.me/dev/2016/11/30/write-d-ts-files/"/>
   <updated>2016-11-30T14:15:45+00:00</updated>
   <id>http://imzc.me/dev/2016/11/30/write-d-ts-files</id>
   <content type="html">&lt;p&gt;知道了 &lt;a href=&quot;/dev/2016/11/22/getting-start-with-typescript/&quot;&gt;TS 项目的结构&lt;/a&gt;信息之后，编写代码是非常容易的。没那么容易的应该是怎么样使用第三方或者是项目原有的 JS。
今天我们来说一说。本文会涉及到大量原来我们在 JS 中经常使用的“奇技淫巧”在 TS 中的实现，值得一读。&lt;/p&gt;

&lt;h2 id=&quot;第三方库使用的关键dts-文件&quot;&gt;第三方库使用的关键：d.ts 文件&lt;/h2&gt;

&lt;p&gt;TS 目前支持三种文件格式：.ts .tsx 和 .d.ts，分别是普通的 ts 文件，主要用于 React 支持的 tsx 文件和
声明（declaration）文件。dts 文件会参与编译，但不会输出任何代码，它的主要作用是为其他 JS 文件提供类型声明。
比较像 C C++ 的 头文件。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;tsc-内置的-dts&quot;&gt;TSC 内置的 d.ts&lt;/h2&gt;

&lt;p&gt;默认情况下我们每个 TS 项目都包含了至少一个 dts 文件。为什么这么说呢，我们可以测试一下。&lt;/p&gt;

&lt;p&gt;在 index.ts 中输入下面的代码&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在 &lt;code class=&quot;highlighter-rouge&quot;&gt;forEach&lt;/code&gt; 上右击，选择“转到定义”。你用的是记事本，没有右键菜单？那就想象吧。IDE 会打开一个 “lib.d.ts” 文件。
你会看到一些这样的代码：&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 一些其他代码&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
      * Performs the specified action for each element in an array.
      * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
      * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
      */&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;callbackfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thisArg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 lib.d.ts 中定义了 &lt;code class=&quot;highlighter-rouge&quot;&gt;Array&lt;/code&gt; 这种类型拥有的属性和方法。lib.d.ts 中定义了数组有一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;forEach&lt;/code&gt; 方法。
它需要至少一个参数：&lt;code class=&quot;highlighter-rouge&quot;&gt;callbackfn&lt;/code&gt;，第二个参数 &lt;code class=&quot;highlighter-rouge&quot;&gt;thisArg&lt;/code&gt; 是可选的，类型是任意的 Object。&lt;/p&gt;

&lt;p&gt;lib.d.ts 是被 TSC 默认包含的，它里面定义了 JavaScript 的公共库，如 Array、Math、RegExp 等。
除了 JS 公共库，它里面还包含了 HTML DOM 的类型定义，比如 &lt;code class=&quot;highlighter-rouge&quot;&gt;window&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;document&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;DOMParser&lt;/code&gt; 等等。这样的默认设定
可以满足大部分 TS 开发的需求。&lt;/p&gt;

&lt;h3 id=&quot;指定项目需要的公共库&quot;&gt;指定项目需要的公共库&lt;/h3&gt;

&lt;p&gt;你可能会问，如果我开发的是一个 NodeJS 应用，我是不希望有 DOM 的 API 的，因为运行时肯定会报错。TSC 有对应的解决方案。
你可以在 tsconfig.json 中通过 &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; 指定需要包含的 libs。没有指定时，它的值相当于 &lt;code class=&quot;highlighter-rouge&quot;&gt;target&lt;/code&gt; 语言版本 + &lt;code class=&quot;highlighter-rouge&quot;&gt;dom&lt;/code&gt;。&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es2015&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;lib&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dom&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;我们可以通过指定 &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; 为 &lt;code class=&quot;highlighter-rouge&quot;&gt;es5&lt;/code&gt; 或者 &lt;code class=&quot;highlighter-rouge&quot;&gt;es2015&lt;/code&gt; 表示 NodeJS 这种没有 DOM 的开发环境。&lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; 的可选值非常多，TS team
针对当下的 JS 开发环境，对 &lt;code class=&quot;highlighter-rouge&quot;&gt;es2015&lt;/code&gt; 的库进行了细分，让开发者可以方便的使用部分 &lt;code class=&quot;highlighter-rouge&quot;&gt;es2015&lt;/code&gt; 中的库，比如可以通过添加
&lt;code class=&quot;highlighter-rouge&quot;&gt;es2015.promise&lt;/code&gt; 来增加 &lt;code class=&quot;highlighter-rouge&quot;&gt;Promise&lt;/code&gt; 支持。&lt;/p&gt;

&lt;h2 id=&quot;第三方库的-dts&quot;&gt;第三方库的 d.ts&lt;/h2&gt;

&lt;p&gt;知道了 JS 公共库的定义方式，其他第三方库也是一样的道理。社区中已经有大量常用库的 dts 文件，我们可以根据需要下载使用。
但是社区中的 dts 五花八门，良莠不齐。为了更好的让他们为我所用。我们还是需要了解一些编写 dts 的技巧，这样遇到不符合我们
需求的 dts 文件，我们可以对他们稍加修改。对于没那么热门的库，自己编写 dts 就尤为重要了。&lt;/p&gt;

&lt;h2 id=&quot;为-jquery-编写-dts&quot;&gt;为 jQuery 编写 d.ts&lt;/h2&gt;

&lt;p&gt;jQuery 作为瑞士军刀一样的库，大家已经非常熟悉了。我们来尝试为它写一个 dts。选它的原因当然是因为它够复杂！&lt;/p&gt;

&lt;h3 id=&quot;dts-中可以只包含自己需要的功能&quot;&gt;dts 中可以只包含自己需要的功能&lt;/h3&gt;

&lt;p&gt;如果我们只是希望在我们的项目中使用某个库，我们可以只写我们需要的部分。比如我们只希望用 jQuery 在 DOM Ready 的时候执行我们的
函数，比如在 index.ts 中加入下面的代码：&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;DOM Ready!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;TS 需要知道 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 是一个全局函数，接收一个函数作为参数。我们在项目根目录新建一个 jQuery.d.ts 文件。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里声明了一个 function &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt;，接收一个类型为 &lt;code class=&quot;highlighter-rouge&quot;&gt;Function&lt;/code&gt; 的参数，没有返回值。编译项目，没有问题，下班回家！&lt;/p&gt;

&lt;p&gt;这一切是怎么工作的呢， tsconfig.json 中我们没有指定 &lt;code class=&quot;highlighter-rouge&quot;&gt;files&lt;/code&gt; 项目目录中的 jQuery.d.ts 就被包括在了项目中。
它告诉编译器在运行环境中 JS 会定义一个名为 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 的全局函数。TSC 会根据这个声明来验证其他 TS 中 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 的调用是否满足定义。
比如 &lt;code class=&quot;highlighter-rouge&quot;&gt;$(123)&lt;/code&gt; 将会报错，因为 &lt;code class=&quot;highlighter-rouge&quot;&gt;123&lt;/code&gt; 不是一个函数。&lt;/p&gt;

&lt;h3 id=&quot;重载的声明方式&quot;&gt;重载的声明方式&lt;/h3&gt;

&lt;p&gt;我自己都看不下去了，这根本不是 jQuery，连 CSS Selector 都不支持。通常 jQuery 的使用场景是这样的：&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;#id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;button&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;20px&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Click!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;编译会有大量报错信息，因为我们之前定义的 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 只能接受一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;Function&lt;/code&gt; 而且没有返回值。为了支持 CSS Selector 我们
让 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 支持多种调用方式，一般语言中叫做 “重载” 。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里我们重复声明了 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt;，TSC 会根据 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 的参数类型自动匹配函数的返回值。这里我们给 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 增加了接收一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt; 类型
参数的重载，它返回一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;any&lt;/code&gt; 类型的结果。但在真实的 JS 中，它会返回一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;JQueryElement&lt;/code&gt; 有 &lt;code class=&quot;highlighter-rouge&quot;&gt;css&lt;/code&gt;、&lt;code class=&quot;highlighter-rouge&quot;&gt;click&lt;/code&gt; 等方法。
所以我们继续完善这个 dts。&lt;/p&gt;

&lt;h3 id=&quot;interface-声明&quot;&gt;Interface 声明&lt;/h3&gt;

&lt;p&gt;我们先定义一个 interface 叫做 &lt;code class=&quot;highlighter-rouge&quot;&gt;JQueryElement&lt;/code&gt;，并添加对应的方法。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;针对可以链式访问的方法返回类型同样设置成 &lt;code class=&quot;highlighter-rouge&quot;&gt;JQueryElement&lt;/code&gt;，值得注意的是 &lt;code class=&quot;highlighter-rouge&quot;&gt;css&lt;/code&gt; 这个方法也应用了刚刚说的重载，
根据参数的数量返回不同的类型。最终我们把 &lt;code class=&quot;highlighter-rouge&quot;&gt;$(selector: string)&lt;/code&gt; 的返回值改成 &lt;code class=&quot;highlighter-rouge&quot;&gt;JQueryElement&lt;/code&gt; 回去看 index.ts
中的代码，已经没有报错信息了。&lt;/p&gt;

&lt;h3 id=&quot;复杂类型的变量声明&quot;&gt;复杂类型的变量声明&lt;/h3&gt;

&lt;p&gt;jQuery 远没有这么简单，比如使用频度跟 Selector 差不多的还有它对 XHR 的封装。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://domain.com/data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 

&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://domain.com/data&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;此时 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 其实已经不是一个简单的 Function 了，它同时还是一个包含属性的 Object。于是我们需要给它单独定义一个 interface
来满足它的各种特性。我们先把刚刚写的 function 形式转化成 interface 形式&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryVariable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JQueryVariable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;我们可以简单的通过定义一个没有名字的方法来告诉 TSC，这个类型的变量是一个 Function。
然后我们生命一个类型是 &lt;code class=&quot;highlighter-rouge&quot;&gt;JQueryVariable&lt;/code&gt; 的变量 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;此时，为 &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; 添加 &lt;code class=&quot;highlighter-rouge&quot;&gt;get&lt;/code&gt; 方法就很容易了，完成后的效果如下&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryVariable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;回调函数的处理&quot;&gt;回调函数的处理&lt;/h3&gt;

&lt;p&gt;在上面的 dts 中所有的回调函数我都用使用了 Function 类型，但在实际项目中，应该尽量避免。它起不到任何约束或者智能提示
的作用。&lt;/p&gt;

&lt;p&gt;稍微总结一下，在 TS 中，函数的类型一般有下面几种表示方式：&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;// 直接声明&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// interface 形式&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Callback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;当然还有最常用的&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// lambda 表达式方式&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;给回调函数指定类型时，最常用的是 lambda 表达式方式，毕竟写起来比较简单。但是当一个回掉函数类型需要被重用，
或者回掉函数需要比较丰富的注释时，还是更加推荐 interface 的写法。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryAjaxCallback&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @param data 服务器返回的数据
     * @param xhr 原始的 XMLHttpRequeset 对象
     */&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryVariable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JQueryElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JQueryAjaxCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JQueryAjaxCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;待续…&lt;/p&gt;

&lt;p&gt;本文是我在微软 Ignite 2016 的一个演讲的文字版。这里附上 PPT 和部分实例代码，当然主要代码已经包括在了文章中。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/files/ts-session.pdf&quot;&gt;Ignite China 2016 TypeScript Session PPT&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/public/files/ignite2016-demos.zip&quot;&gt;Ignite China 2016 TypeScript Session Demo&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TypeScript 第一步</title>
   <link href="http://imzc.me/dev/2016/11/22/getting-start-with-typescript/"/>
   <updated>2016-11-22T14:15:45+00:00</updated>
   <id>http://imzc.me/dev/2016/11/22/getting-start-with-typescript</id>
   <content type="html">&lt;p&gt;不少小伙伴 (基友😏) 开始用 TS 了, 但现在的 JS 项目复杂度, 已经远不是 TS 刚出现时候的程度了.
各种第三方库,各种加载库(webpack, AMD, UMD, SystemJS, CommonJS), 各种运行环境 Node, Browser,
各种 JS 语言版本 es3 es5 es6 es2015 es2017. 还有 jsx 这种语言. 古人云:能用 JS 的地方就能用 TS.
那么, 怎么用呢. 今天咱们就来说一说.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;第一步当然还是 搭建一个简单的开发环境.&lt;/p&gt;

&lt;h2 id=&quot;安装-typescript&quot;&gt;安装 TypeScript&lt;/h2&gt;

&lt;p&gt;可以执行 &lt;code class=&quot;highlighter-rouge&quot;&gt;npm install typescript -g&lt;/code&gt; 来安装 TypeScript. 安装后你就能使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 命令了. 用来将 TS 文件编译成 JS 文件. 
我们先不管它,接着进行下面的步骤.&lt;/p&gt;

&lt;h2 id=&quot;typescript-项目结构&quot;&gt;TypeScript 项目结构&lt;/h2&gt;

&lt;h3 id=&quot;tsconfigjson&quot;&gt;tsconfig.json&lt;/h3&gt;

&lt;p&gt;TS 项目是通过 tsconfig.json 来定义的. 很多时候如果你的 IDE 没有很好的进行智能提示,一般是没有添加 tsconfig.json&lt;/p&gt;

&lt;p&gt;在命令行中执行 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc --init&lt;/code&gt; 可以在当前目录中快速创建一个 tsconfig.json 文件.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;commonjs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;noImplicitAny&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sourceMap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;compilerOptions 编译选项&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;先说一下对 TS 项目来说最重要的两个设置&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;module&lt;/code&gt; 定义生成的 js 中应该采用什么模块化组织方式. 可选的值有 &lt;code class=&quot;highlighter-rouge&quot;&gt;none&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;commonjs&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;AMD&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;UMD&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;System&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;es2015&lt;/code&gt;.
在 TS 中默认使用 es2015 的模块组织形式, 通过指定 &lt;code class=&quot;highlighter-rouge&quot;&gt;module&lt;/code&gt; 你可以将他们转化成自己熟悉的组织方式.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;target&lt;/code&gt; 定义生成的 JS 代码版本, 可选 &lt;code class=&quot;highlighter-rouge&quot;&gt;es3&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;es5&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;es2015&lt;/code&gt;. 你可以根据自己的运行时 JS 版本进行选择.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;注意: 因为 ES 不同版本的公共库不一致, 所以三个 target 有些语法和库上的差异. 比如 &lt;code class=&quot;highlighter-rouge&quot;&gt;es3&lt;/code&gt; 不支持 getter setter,
   &lt;code class=&quot;highlighter-rouge&quot;&gt;es5&lt;/code&gt; 默认没有 &lt;code class=&quot;highlighter-rouge&quot;&gt;Promise&lt;/code&gt;. 针对库不可用的情况, 我们可以通过添加 d.ts 的方式来使用.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;其他编译选项可以参考: 
&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot;&gt;TS 编译参数(官方英文)&lt;/a&gt;
或者 &lt;a href=&quot;http://tslang.cn/docs/handbook/compiler-options.html&quot;&gt;TS 编译参数(社区中文)&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;其他配置项&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;默认情况下, TS 项目会包含 该目录下所有的 &lt;code class=&quot;highlighter-rouge&quot;&gt;ts&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;tsx&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;.d.ts&lt;/code&gt; 文件. 我们可以通过
&lt;code class=&quot;highlighter-rouge&quot;&gt;files&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;exclude&lt;/code&gt; 来指定哪些文件应该在项目中.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a.ts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b.ts&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;src/**/*&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;exclude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;node_modules&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;**/*.spec.ts&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;files&lt;/code&gt; 一般单独使用, 穷举中所有要包含的 ts 文件, 我觉得, 定这么个规则还是挺需要勇气的. 在社区吐槽了 n 年后, TS team 才终于加上了
&lt;code class=&quot;highlighter-rouge&quot;&gt;include&lt;/code&gt;,&lt;code class=&quot;highlighter-rouge&quot;&gt;exclude&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;现在你已经大致了解 TS 项目是什么样子的了. 我们接下来按照 JS 发展的历史, 从简单到复杂来介绍
用 TS 如何更爽的开发 web 应用.&lt;/p&gt;

&lt;h2 id=&quot;传统浏览器运行环境&quot;&gt;传统浏览器运行环境&lt;/h2&gt;

&lt;p&gt;在传统的浏览器中, JS 加载过程是由浏览器控制的. 说是控制, 但其实非常简单粗暴. 按照先后顺序
阻塞加载. 造成的结果一般是浏览器会空白一段时间, &lt;code class=&quot;highlighter-rouge&quot;&gt;head&lt;/code&gt; 里所有的 JS 加载完成后, &lt;code class=&quot;highlighter-rouge&quot;&gt;body&lt;/code&gt; 才会
开始渲染. 但噩梦还没结束, “经典” 的 web 开发, JS 是无处不在的, 两个 &lt;code class=&quot;highlighter-rouge&quot;&gt;div&lt;/code&gt; 之间加个 &lt;code class=&quot;highlighter-rouge&quot;&gt;script&lt;/code&gt; 也
很常见. 然后页面再卡一段时间😩.&lt;/p&gt;

&lt;p&gt;因为没有模块化的组织方式,页面要加载哪些 JS 文件都是手动写在 html 中的, 而且顺序还不能错 😩. 
这就是 tsconfig 最先支持 &lt;code class=&quot;highlighter-rouge&quot;&gt;files&lt;/code&gt; 的原因 (再次吐槽没有 include 和 exclude ).&lt;/p&gt;

&lt;h3 id=&quot;一个最基本的-ts-项目&quot;&gt;一个最基本的 TS 项目&lt;/h3&gt;

&lt;p&gt;我们将 tsconfig.json 最简化&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;compilerOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;es5&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;添加一个 index.ts 我们就可以写代码了.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'div'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textContent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Hi TS'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;添加一段文字到 body 中. 这段代码根本不像 TS 啊, 是的, 毕竟 TS 是对 JS 的扩展, 写 JS 当然是
没有任何问题的. 但是在 TS 中, 借助强大的类型推倒(推导)功能, 编译器其实知道 body 是一个 HTMLElement,
div 是一个 HTMLDivElement 的. 至于为什么, 我们&lt;strong&gt;后面介绍 d.ts 的时候再说&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;我们在命令行中执行 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 编译这个 TS 项目. 当 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 命令没有指定任何参数时, 它将会在当前目录
寻找 tsconfig.json 并按照里面的配置编译项目中的 TS 文件.&lt;/p&gt;

&lt;p&gt;在这个 TS 文件中我们没有写任何的 &lt;code class=&quot;highlighter-rouge&quot;&gt;export&lt;/code&gt; 那么 TSC 会认为它是一个传统的 JS 文件. 
&lt;code class=&quot;highlighter-rouge&quot;&gt;body&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;div&lt;/code&gt; 都是全局变量. 当我们再添加一个 TS 文件时, 我们在 IDE 中是能够收到 &lt;code class=&quot;highlighter-rouge&quot;&gt;body&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;div&lt;/code&gt;
的智能提示的.&lt;/p&gt;

&lt;p&gt;我们再添加一个文件 &lt;code class=&quot;highlighter-rouge&quot;&gt;date-picker.ts&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'h1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;编译, 没有任何问题.&lt;/p&gt;

&lt;p&gt;每次执行 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 命令是一件挺麻烦的事情. 我们可以给 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 命令加一个参数
&lt;code class=&quot;highlighter-rouge&quot;&gt;-w&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;tsc&lt;/code&gt; 将会自动监听文件变化, 自动进行编译.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;经常遇到有开发者问, 我怎么在页面的 script 中使用 TS 定义的变量啊? 答案是, 直接用就行了. 
至于如何在 TS 中使用在 script 标签中定义的变量. 我们还是&lt;strong&gt;等到介绍 d.ts 的时候说&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;命名空间-namespace&quot;&gt;命名空间 namespace&lt;/h3&gt;

&lt;p&gt;即便在远古 JS 开发时代, 大家也是不希望有变量名污染的, 不然项目打(大)起来就是灾难了.&lt;/p&gt;

&lt;p&gt;TS 提供了 &lt;code class=&quot;highlighter-rouge&quot;&gt;namespace&lt;/code&gt; 关键字来更好的管理 class 变量名等.&lt;/p&gt;

&lt;p&gt;在 date-picker.ts 中我们定义下面的代码&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 公开变量&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 局部变量&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;kd&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTMLElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
            &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在 index.ts 中可以这样用&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;componentReady&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;componentCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 错误&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;namespace&lt;/code&gt; 中的局部变量外界是无法访问的, 可以配合 &lt;code class=&quot;highlighter-rouge&quot;&gt;export&lt;/code&gt; 关键字公开其访问级别.&lt;/p&gt;

&lt;p&gt;至于 &lt;code class=&quot;highlighter-rouge&quot;&gt;namespace&lt;/code&gt; 是怎么实现的, 我们看一下生成的代码就再清楚不过了.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}());&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从这段 JS 我们也能看出另外一个特性, 就是同名的 &lt;code class=&quot;highlighter-rouge&quot;&gt;namespace&lt;/code&gt; 是可以分布在不同的文件中的.
所有 &lt;code class=&quot;highlighter-rouge&quot;&gt;export&lt;/code&gt; 的属性都会合并到这个 &lt;code class=&quot;highlighter-rouge&quot;&gt;namespace&lt;/code&gt; 中.&lt;/p&gt;

&lt;p&gt;此外, namespace 是能够嵌套的, 下面的代码都是合法的&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;web&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTMLFormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;electron&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTMLFormElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;nodejs-以及其他模块化组织的项目&quot;&gt;NodeJS 以及其他模块化组织的项目&lt;/h2&gt;

&lt;p&gt;近几年 NodeJS 异军突起, 凭借良好的群众基础, 迅速占领了大片乡村, 有要与 PHP Java 大军决一死战的意思. 
也圆了很多小伙伴的全栈梦. 确实, 谁让浏览器现在还只认 JS 呢.&lt;/p&gt;

&lt;p&gt;NodeJS 所在的环境跟浏览器有非常大的不同. 所有的 JS 都在运行时本地. 代码加载起来没有任何障碍.
所以 NodeJS 采用了 CommonJS 组织代码. 每个 JS 文件都是一个 module, 通过 &lt;code class=&quot;highlighter-rouge&quot;&gt;exports.xxx = xxx&lt;/code&gt; 
来公开属性, 用 require 加载其他 JS, 加载过程是同步阻塞的. 总的来说 CommonJS 是一种比较简单的加载方式.&lt;/p&gt;

&lt;p&gt;让我们把 tsconfig.json 稍加修改,添加 &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;module&quot;: &quot;commonjs&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;date-picker.ts 改为&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ready&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
    &lt;span class=&quot;kd&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTMLElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
        &lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;区别于普通 CommonJS 的导出方式, TS 直接在需要导出的变量 / class 前加 &lt;code class=&quot;highlighter-rouge&quot;&gt;export&lt;/code&gt; 即可.&lt;/p&gt;

&lt;p&gt;在 index.ts 中引用 &lt;code class=&quot;highlighter-rouge&quot;&gt;DatePicker&lt;/code&gt; 的写法有很多, 先写一个经典的&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'./date-picker'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;import&lt;/code&gt; + &lt;code class=&quot;highlighter-rouge&quot;&gt;require&lt;/code&gt; 是 TS 最早支持的包引用方法, 跟 CommonJS 非常像. 随着 ES2015 的
确定, TS 中越来越多的语法开始跟 ES2015 取齐. 所以你还可以这么写&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'./date-picker'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;或者&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'./date-picker'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;因为我们在 tsconfig.json 中指定了 module 为 &lt;code class=&quot;highlighter-rouge&quot;&gt;CommonJS&lt;/code&gt; 生成的代码就是 CommonJS 风格的&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s2&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date_picker_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./date-picker&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date_picker_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;此时我们将 tsconfig 的 &lt;code class=&quot;highlighter-rouge&quot;&gt;module&lt;/code&gt; 改成其他值测试一下&lt;/p&gt;

&lt;p&gt;AMD:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;require&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;exports&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./date-picker&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date_picker_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date_picker_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;ES2015:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'./date-picker'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datePicker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;完美!&lt;/p&gt;

&lt;p&gt;至此, 你已经了解了 tsconfig.json, 知道如何用 TS 编写传统的浏览器项目
和模块化组织的 TS 项目了. 接下来我会介绍入门 TS 的最大障碍: 如何使用
现有的 JS 库.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Angular 2 two-way binding property</title>
   <link href="http://imzc.me/dev/2016/10/27/ng2-two-way-binding-prop/"/>
   <updated>2016-10-27T14:15:45+00:00</updated>
   <id>http://imzc.me/dev/2016/10/27/ng2-two-way-binding-prop</id>
   <content type="html">&lt;p&gt;希望有一个 Pager 组件，能够绑定 &lt;code class=&quot;highlighter-rouge&quot;&gt;total&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 效果如下面的代码。&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;mx-pager&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;]=&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;totalPage&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;]=&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentPage&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/mx-pager&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对应的 &lt;code class=&quot;highlighter-rouge&quot;&gt;Pager&lt;/code&gt; 代码应该是这样的&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PagerComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	
    &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;但是，我们的 Pager 不应该只是一个展示数据的组件，当用户点击新 page 的时候，
我们需要在父组件中执行相应的动作。也就是说，&lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 属性需要双向绑定。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;twe-way-binding-property&quot;&gt;Twe-way binding property&lt;/h2&gt;

&lt;p&gt;在 ng2 中可以通过 &lt;code class=&quot;highlighter-rouge&quot;&gt;Output&lt;/code&gt; 装饰器来实现双向绑定属性。&lt;/p&gt;

&lt;p&gt;首先添加一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;currentChange&lt;/code&gt; property。
类型为 &lt;code class=&quot;highlighter-rouge&quot;&gt;EventEmitter&amp;lt;number&amp;gt;&lt;/code&gt; 我们将通过这个 emitter 向外部派发 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 属性改变的事件。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;EventEmitter&amp;lt;number&amp;gt;&lt;/code&gt; 有一个泛型参数，需要跟 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 属性的类型一致。
表明 emitter 在 call 事件监听方法时传递的参数类型。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PagerComponent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	
    &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;currentChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;EventEmitter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后跟 &lt;code class=&quot;highlighter-rouge&quot;&gt;@Input()&lt;/code&gt; 类似，为 &lt;code class=&quot;highlighter-rouge&quot;&gt;currentChange&lt;/code&gt; 添加 &lt;code class=&quot;highlighter-rouge&quot;&gt;@Output()&lt;/code&gt; 装饰器&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Output&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;currentChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;EventEmitter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 变化的时候, 我们只需要执行 &lt;code class=&quot;highlighter-rouge&quot;&gt;currentChange&lt;/code&gt; 的 &lt;code class=&quot;highlighter-rouge&quot;&gt;emit&lt;/code&gt; 方法即可。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;一开始的 template 代码可以改为双向绑定了：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;mx-pager&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;]=&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;totalPage&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;)]=&quot;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentPage&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/mx-pager&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-accessor-提高一致性&quot;&gt;使用 Accessor 提高一致性&lt;/h2&gt;

&lt;p&gt;为了保持一致性，我习惯将 &lt;code class=&quot;highlighter-rouge&quot;&gt;emit&lt;/code&gt; 的调用跟 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 的赋值过程结合起来。
将 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 改成 &lt;code class=&quot;highlighter-rouge&quot;&gt;accessor&lt;/code&gt;。&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_currnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_currnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_currnet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_currnet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样在组件内部，我们只需要关心 &lt;code class=&quot;highlighter-rouge&quot;&gt;current&lt;/code&gt; 即可，在赋值过程中 &lt;code class=&quot;highlighter-rouge&quot;&gt;currentChange&lt;/code&gt; 事件会自动触发。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Have fun!&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>3) VS Code 插件示例，一个 TypeScript 即时预览插件</title>
   <link href="http://imzc.me/tools/2016/10/15/vscode-ext-typescript-live-preview/"/>
   <updated>2016-10-15T14:15:45+00:00</updated>
   <id>http://imzc.me/tools/2016/10/15/vscode-ext-typescript-live-preview</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/13/getting-started-with-vscode-ext/&quot;&gt;1) VS Code 插件创建与发布&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/14/vscode-ext-what-is-in-the-project/&quot;&gt;2) VS Code 插件项目结构与配置文件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;3) VS Code 插件示例，一个 TypeScript 即时预览插件&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;源代码：&lt;a href=&quot;https://github.com/imzc/vscode-live-code&quot;&gt;https://github.com/imzc/vscode-live-code&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;插件目标&quot;&gt;插件目标&lt;/h2&gt;

&lt;p&gt;这个插件最终的效果，希望是能够在编辑 TypeScript 时，能够即时在 HTML 中运行，看到运行效果。&lt;/p&gt;

&lt;p&gt;为了实现这个目标我们需要解决几个问题&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;插件需要在编辑 TypeScript 时激活&lt;/li&gt;
  &lt;li&gt;需要在用户输入的时候即时编译 TypeScript&lt;/li&gt;
  &lt;li&gt;需要注册 command 在 VS Code 中打开一个 WebView&lt;/li&gt;
  &lt;li&gt;在 WebView 中加载编译后的 JavaScript&lt;/li&gt;
&lt;/ol&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;创建项目&quot;&gt;创建项目&lt;/h2&gt;

&lt;p&gt;参考 &lt;a href=&quot;/tools/2016/10/13/getting-started-with-vscode-ext/&quot;&gt;VS Code 插件创建与发布&lt;/a&gt; 创建一个
TypeScript 项目。&lt;/p&gt;

&lt;h2 id=&quot;添加-command修改-activationevents&quot;&gt;添加 command，修改 activationEvents&lt;/h2&gt;

&lt;p&gt;如图添加一个 command 并添加一个 activationEvent，当文件语言为 TypeScript 的时候激活插件。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/addtscommands.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;同时我们还添加了一个快捷键 &lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+k, ctrl+t&lt;/code&gt; 来快速调用这个 command。&lt;/p&gt;

&lt;p&gt;在 scr/extensions.ts 中进行相应的修改，并添加一个 outputChannel 来往输出面板中打印消息，
方便我们输出信息和调试。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/2regcommands.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;调试并打开一个 TypeScript 文件，可以看到插件激活，输出面板显示出来。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/2run.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;处理用户输入&quot;&gt;处理用户输入&lt;/h2&gt;

&lt;p&gt;VS Code 提供了 &lt;code class=&quot;highlighter-rouge&quot;&gt;vscode.workspace.onDidChangeTextDocument&lt;/code&gt; 方法来处理文件变化。
这个方法跟 File Watcher 的区别是，用户没有执行 save 的时候我们也能收到消息，更加符合我们的需求。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/3handlechanges.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在回调函数中我们判断一下当前文件的语言，排除不需要处理的文件。然后打印一个消息。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/3output.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;处理-typescript-编译&quot;&gt;处理 TypeScript 编译&lt;/h2&gt;

&lt;p&gt;TypeScript 提供了丰富的 API 让我们能够用编程的方式编译 TypeScript。&lt;/p&gt;

&lt;p&gt;首先我们引入 &lt;code class=&quot;highlighter-rouge&quot;&gt;typescript&lt;/code&gt; 库。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意将 package.json 中的 typescript 库从 devDeps 转移到 deps 中。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;今天我们用到的是 ts 提供的最简化的一个 API &lt;code class=&quot;highlighter-rouge&quot;&gt;ts.transpileModule&lt;/code&gt;, 它能够将 TS 源码直接转化为 JS。
我们将转化的输出暂时输出到输出面板中。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/4compile.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;运行后，我们修改一个 ts 文件，可以看到即时生成的 JavaScript。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/4output.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;打开一个-webview&quot;&gt;打开一个 WebView&lt;/h2&gt;

&lt;p&gt;处理完了上面的流程，终于来到最关键的预览环节。这里用到 vscode 的另外一个 API&lt;/p&gt;

&lt;h3 id=&quot;vscodepreviewhtml&quot;&gt;vscode.previewHtml&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;vscode.commands.executeCommand(cmd:string, ...params:object[])&lt;/code&gt; 用来执行 vscode 中
支持的 command，包括内置的和其他插件扩展的，都可以。&lt;/p&gt;

&lt;p&gt;这里我们使用的是 &lt;code class=&quot;highlighter-rouge&quot;&gt;vscode.previewHtml&lt;/code&gt;,这个 command 支持打开一个 html url 在 vscode 进行展示。
但处于安全原因，vscode 对 url 进行了限制，只能支持 file 和 插件注册的 url schema。在这里我们使用
&lt;code class=&quot;highlighter-rouge&quot;&gt;livecode&lt;/code&gt;作为我们预览的 url schema，最终交给 vscode 的 url大概是这样的：&lt;code class=&quot;highlighter-rouge&quot;&gt;livecode:/c:/work/demo/test.ts?file:///c:/work/demo/test.ts&lt;/code&gt;
然后我们会注册这个 schema 并编写代码根据 这个 url来生成对应的 html 代码。&lt;/p&gt;

&lt;p&gt;我们先改一下 preview command 对应的代码，让它打开一个 webview&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/5openhtml.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;构建-html&quot;&gt;构建 html&lt;/h3&gt;
&lt;p&gt;我们使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;TextDocumengContentProvider&lt;/code&gt; 来给 webview 生成 html 代码。我们需要实现 
&lt;code class=&quot;highlighter-rouge&quot;&gt;provideTextDocumentContent(uri: Uri): Thenable&amp;lt;string&amp;gt;&lt;/code&gt; 根据 url 生成 html 代码。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6provider.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们添加一个文件 LiveCodeDocumentContentProvider.ts 来实现&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6livecodeprovide6r.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;provideTextDocumentContent&lt;/code&gt; 中我们简单的构建了一个 html 文档，其中 body 部分我们会添加一个 script tag。
用来承载编译后的 JavaScript 代码，我们会用一个 function 包裹 TS 编译的逻辑，将它传递给 provider，
也就是这里看到的 &lt;code class=&quot;highlighter-rouge&quot;&gt;this._render&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;回到 extensions.ts 我们来注册 livecode 这个schema。首先引入 LiveCodeDocumentContentProvider，
实例化，将TS compile function 传给它，然后注册。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6reg.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6compile.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最后，当TS文件变化时，通知 provider。
&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6update.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们来运行一下。可以看到 TypeScript 运行的效果，我们将它拖到右侧，修改代码，可以看到实时的效果&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/6preview.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;在右侧编辑区域预览&quot;&gt;在右侧编辑区域预览&lt;/h3&gt;
&lt;p&gt;我们稍微修改一下 previewHtml 的参数，让它在右侧的编辑区域打开，并在 title 中显示 “Preview”&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/7columntitle.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/7preview.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;另外，当我们代码中出现问题的时候，预览窗口中没有任何输出。我们稍微修改一下 compileTypeScript 在 JS 外层
包裹一层异常捕获代码。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/7trycatch.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/7error.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;next&quot;&gt;Next&lt;/h1&gt;
&lt;p&gt;至此，我们完成了一个 TypeScript 插件的基本功能。但是其实还有很多问题值得进一步深入。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;项目级别的预览，TS 之间相互引入&lt;/li&gt;
  &lt;li&gt;第三方库引入&lt;/li&gt;
  &lt;li&gt;Node.js 环境下的实时执行&lt;/li&gt;
  &lt;li&gt;等等&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>2) VS Code 插件项目结构与配置文件</title>
   <link href="http://imzc.me/tools/2016/10/14/vscode-ext-what-is-in-the-project/"/>
   <updated>2016-10-14T12:12:45+00:00</updated>
   <id>http://imzc.me/tools/2016/10/14/vscode-ext-what-is-in-the-project</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/13/getting-started-with-vscode-ext/&quot;&gt;1) VS Code 插件创建与发布&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;2) VS Code 插件项目结构与配置文件&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/15/vscode-ext-typescript-live-preview/&quot;&gt;3) VS Code 插件示例，一个 TypeScript 即时预览插件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;vs-code-extension-项目结构&quot;&gt;VS Code Extension 项目结构&lt;/h2&gt;

&lt;p&gt;打开 yo code 创建的项目，我们能看到下面的目录结构。
&lt;img src=&quot;http://imzc.me/public/images/openchina2016/project.jpg&quot; alt=&quot;yo code output&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;展开之后得到的是下面的层级结构（我省略了大部分用于测试的 node_modules）。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;├─.vscode
│      launch.json
│      settings.json
│      tasks.json
│          
├─src
│      extension.ts
│      
├─test
│       extension.test.ts
│       index.ts
│      
├─node_modules
│  ├─@types
│  │  ├─mocha
│  │  │      index.d.ts
│  │  │      
│  │  └─node
│  │          index.d.ts
│  │          
│  ├─typescript
│  │                  
│  └─vscode
│     │  thenable.d.ts
│     │  tslint.json
│     └─ vscode.d.ts     
│          
├─out
│  └─src
│     └─  extension.js
│  
│  .gitignore
│  .vscodeignore
│  package.json
│  README.md
│  tsconfig.json
└─ vsc-extension-quickstart.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; 是整个 extension 的配置文件。它除了描述 extension 的基本信息，如名称，作者版本等外，
更重要的是描述插件对 vscode 所做的扩展，注册用户可以执行的命令，标记该 extension 应该何时启动。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;src/extension.ts&lt;/code&gt; 是插件的入口，这个文件 export 了 &lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt; 方法，在插件被激活时，vscode 将调用这个方法，执行用户代码。
在这个例子中我们在这里用 &lt;code class=&quot;highlighter-rouge&quot;&gt;vscode.commands.registerCommand&lt;/code&gt; 注册了 &lt;code class=&quot;highlighter-rouge&quot;&gt;extension.sayHello&lt;/code&gt; 这个 command 的具体实现。显示一个消息：&lt;code class=&quot;highlighter-rouge&quot;&gt;Hello World&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;.vscode&lt;/code&gt; 这里是 vscode 的项目文件。其中
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;launch.json&lt;/code&gt; 定义了当前项目的调试方式。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tasks.json&lt;/code&gt; 定义了编译动作。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;settings.json&lt;/code&gt; 定义了针对当前项目的编辑器设定。例如排除不想要显示的文件。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; 中绝大多数 package 为 test 的 devDependencies。与插件开发相关的是 &lt;code class=&quot;highlighter-rouge&quot;&gt;typescript&lt;/code&gt;、 &lt;code class=&quot;highlighter-rouge&quot;&gt;vscode&lt;/code&gt; 和 &lt;code class=&quot;highlighter-rouge&quot;&gt;@types&lt;/code&gt;。
    &lt;ul&gt;
      &lt;li&gt;这里引入一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;typescript&lt;/code&gt; 的原因是为了更好的限定开发中使用的 TS 版本 和 JS 的运行环境。比如，在插件中是不能使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;window&lt;/code&gt; 对象的，通过在 &lt;code class=&quot;highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt; 中指定 &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; 即可。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;vscode&lt;/code&gt; 主要是为了引入 vscode package 的 TypeScript 定义。让开发体验更加友好。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;@types&lt;/code&gt; 是 TS 2.0 引入的第三方 js 库的 TypeScript 定义文件安装方式，这里引入了 nodejs 和 mocha 的定义文件。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;.vscodeignore&lt;/code&gt; 指定在发布插件时需要排除的文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;大体了解了整个项目的结构，让我们来看一下实际运行的效果。在 VS Code 中直接按 F5 即可启动调试。VS Code 会
启动一个新的 VS Code 窗口，在这个窗口中会额外加载我们的插件项目以便我们进行测试。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/1run.png&quot; alt=&quot;debug host&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们按 &lt;code class=&quot;highlighter-rouge&quot;&gt;F1&lt;/code&gt; 或者 &lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+shift+p&lt;/code&gt; 输入 hello 就能发现我们刚刚注册的 command。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/1command.png&quot; alt=&quot;debug host&quot; /&gt;&lt;/p&gt;

&lt;p&gt;执行这个 command 可以看到此时，我们项目调试控制台输出 
&lt;code class=&quot;highlighter-rouge&quot;&gt;Congratulations, your extension &quot;vscode-extension&quot; is now active!&lt;/code&gt; 插件的 &lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt; 方法被调用。
VS Code 显示一个 Hello World 信息。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/1runcommand.png&quot; alt=&quot;debug host&quot; /&gt;&lt;/p&gt;

&lt;p&gt;你可能会问，为什么我们的代码在我们真正执行了 command 的时候才会被激活，这是 VS Code 的一个优化。
vscode 可以直接根据 package.json 来展示插件定义的 command，而不必执行插件的代码，
保证 vscode 的启动速度。在这个插件模板中，我们注册了一个 title 为 Hello World 的 command。
&lt;code class=&quot;highlighter-rouge&quot;&gt;activationEvents&lt;/code&gt; 为 &lt;code class=&quot;highlighter-rouge&quot;&gt;onCommand:extension.sayHello&lt;/code&gt;, 仅当我们执行这个 command 的时候，插件才被激活。
VS Code 才会真正开始执行我们的代码。&lt;/p&gt;

&lt;h2 id=&quot;packagejson&quot;&gt;package.json&lt;/h2&gt;

&lt;h3 id=&quot;字段定义&quot;&gt;字段定义&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;名称&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;必需&lt;/th&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件扩展的名称, 全部是小写字母，并且不能有空格.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;version&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;参考&lt;a href=&quot;http://semver.org/lang/zh-CN/&quot;&gt;Semver&lt;/a&gt;. 例如: &lt;code class=&quot;highlighter-rouge&quot;&gt;1.0.0&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;publisher&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;发布者名称&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;engines&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;包含&lt;code class=&quot;highlighter-rouge&quot;&gt;vscode&lt;/code&gt;字段的对象， 定义所需环境的版本。例如 &lt;code class=&quot;highlighter-rouge&quot;&gt;^1.5.0&lt;/code&gt; 表示需要1.5.0或者更高版本.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;displayName&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件显示的名称.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;description&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件的描述文本.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;icon&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件使用的图标，大小为 128*128.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;main&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件入口的相对路径，当插件启动时将调用入口文件的&lt;code class=&quot;highlighter-rouge&quot;&gt;activate&lt;/code&gt;方法.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;categories&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件的分类，常用分类有: &lt;code class=&quot;highlighter-rouge&quot;&gt;[Languages, Snippets, Linters, Themes, Debuggers, Other]&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/extensionAPI/extension-points&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;contributes&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件扩展点的描述对象，详见 &lt;a href=&quot;https://code.visualstudio.com/docs/extensionAPI/extension-points&quot;&gt;contributions&lt;/a&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/extensionAPI/activation-events&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;activationEvents&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件激活事件的描述数组，详见 &lt;a href=&quot;https://code.visualstudio.com/docs/extensionAPI/activation-events&quot;&gt;activation events&lt;/a&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;keywords&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件的关键词，准确的关键词有助于更好的找到插件.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dependencies&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件依赖的 &lt;code class=&quot;highlighter-rouge&quot;&gt;Node.js&lt;/code&gt; 库. 参见 &lt;a href=&quot;https://docs.npmjs.com/files/package.json#dependencies&quot;&gt;npm dependencies&lt;/a&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;devDependencies&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件开发环境下依赖的 &lt;code class=&quot;highlighter-rouge&quot;&gt;Node.js&lt;/code&gt; 库. 例如，如果插件使用TypeScript编写，则开发环境需要依赖 &lt;code class=&quot;highlighter-rouge&quot;&gt;typescript&lt;/code&gt;. 参见 &lt;a href=&quot;https://docs.npmjs.com/files/package.json#devdependencies&quot;&gt;npm devDependencies&lt;/a&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;extensionDependencies&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;插件依赖的其他插件的id. 插件id为 &lt;code class=&quot;highlighter-rouge&quot;&gt;${publisher}.${name}&lt;/code&gt;. 例如: &lt;code class=&quot;highlighter-rouge&quot;&gt;egret.text-tools&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;scripts&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;object&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;详见 &lt;a href=&quot;https://docs.npmjs.com/misc/scripts&quot;&gt;npm scripts&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;contributes扩展点&quot;&gt;contributes（扩展点）&lt;/h3&gt;

&lt;p&gt;扩展点允许开发者在 vscode 中自定义一些扩展功能。&lt;/p&gt;

&lt;h4 id=&quot;contributescommands&quot;&gt;contributes.commands&lt;/h4&gt;

&lt;p&gt;自定义命令 &lt;code class=&quot;highlighter-rouge&quot;&gt;command&lt;/code&gt; 。定义的命令可以在命令面板(Command Palette)中找到并执行。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 当命令通过快捷键或者命令面板被执行时, 将派发 &lt;code class=&quot;highlighter-rouge&quot;&gt;activationEvent&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;onCommand:${command}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;可使用下列字段：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;名称&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;必需&lt;/th&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;command&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;表示命令的唯一id.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;title&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;表示命令的名称，此属性将显示在命令面板中.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;例子&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;commands&quot;: [{
		&quot;command&quot;: &quot;extension.sayHello&quot;,
		&quot;title&quot;: &quot;Hello World&quot;
	}]
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributeskeybindings&quot;&gt;contributes.keybindings&lt;/h4&gt;

&lt;p&gt;自定义快捷键 &lt;code class=&quot;highlighter-rouge&quot;&gt;keybinding&lt;/code&gt;。可以自定义命令执行的按键绑定。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 可以定义不同操作系统平台的快捷键。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 当命令通过快捷键或者命令面板被执行时, 将派发 &lt;code class=&quot;highlighter-rouge&quot;&gt;activationEvent&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;onCommand:${command}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;可使用下列字段：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;名称&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;必需&lt;/th&gt;
      &lt;th&gt;类型&lt;/th&gt;
      &lt;th&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;command&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;快捷键绑定的命令的id&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;key&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;是&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;快捷键的按键组合，可以的按键的组合字符串参见 附录1 .&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;win&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;在windows平台下的按键组合，如果用户在windows下，此属性将覆盖&lt;code class=&quot;highlighter-rouge&quot;&gt;key&lt;/code&gt;字段指定的按键组合.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;mac&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;在mac平台下的按键组合，如果用户在mac下，此属性将覆盖&lt;code class=&quot;highlighter-rouge&quot;&gt;key&lt;/code&gt;字段指定的按键组合.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;when&lt;/code&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;快捷键何时被触发的表达式，可用的属性值参见 附录2 .&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;附录1-key字段可用的按键组合字符串规则&quot;&gt;附录1 &lt;code class=&quot;highlighter-rouge&quot;&gt;key&lt;/code&gt;字段可用的按键组合字符串规则&lt;/h5&gt;

&lt;p&gt;按键规则一般由组合键 + 其他按键组成。&lt;/p&gt;

&lt;p&gt;组合按键表示如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;操作系统&lt;/th&gt;
      &lt;th&gt;组合键&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;MACOS X&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;shift+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;alt+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;cmd+&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Windows&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;shift+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;alt+&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;win+&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 特殊的可以使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;ctrlcmd&lt;/code&gt; 表示windows下的&lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl&lt;/code&gt;, mac下的&lt;code class=&quot;highlighter-rouge&quot;&gt;cmd&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;其他按键表示如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f1-f15&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;a-z&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;0-9&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;`&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;-&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;=&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;[&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;]&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;'&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;,&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;.&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;left&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;up&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;right&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;down&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;pageup&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;pagedown&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;end&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;home&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;tab&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;enter&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;escape&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;space&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;backspace&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;delete&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;pausebreak&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;capslock&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;insert&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用空格分割的按键序列，例如(ctrl+k ctrl+c)，表示先按ctrl+k，再按ctrl+c 才能触发该快捷键。&lt;/p&gt;

&lt;p&gt;如果要使某一命令既可以按ctrl+k触发，又可以按ctrl+c触发，请定义两组keybinding，command相同，但是key字段不同。&lt;/p&gt;

&lt;h5 id=&quot;附录2-when字段可用的字符串&quot;&gt;附录2 &lt;code class=&quot;highlighter-rouge&quot;&gt;when&lt;/code&gt;字段可用的字符串&lt;/h5&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;when&lt;/code&gt;字段可以使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;!&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;==&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;!=&lt;/code&gt; 等表达式限定条件。如&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;!inDebugMode&lt;/code&gt;  , &lt;code class=&quot;highlighter-rouge&quot;&gt;editorTextFocus &amp;amp;&amp;amp; editorLangId == 'ts'&lt;/code&gt; 都是可用的表达式。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;editorFocus&lt;/code&gt; 编辑器获得焦点时&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;editorTextFocus&lt;/code&gt; 文本编辑器获得焦点时&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;editorLangId&lt;/code&gt; 表示编辑器的语言id，&lt;code class=&quot;highlighter-rouge&quot;&gt;editorLangId&lt;/code&gt; 通常对应编辑器对应文档的扩展名&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;inDebugMode&lt;/code&gt; 表示启动调试时&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;例子-1&quot;&gt;例子&lt;/h5&gt;

&lt;p&gt;定义命令 &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;extension.sayHello&quot;&lt;/code&gt; 的windows下快捷键为 &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl+F1&lt;/code&gt;，mac下快捷键为 &lt;code class=&quot;highlighter-rouge&quot;&gt;Cmd+Shift+F1&lt;/code&gt; :&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;keybindings&quot;: [{
		&quot;command&quot;: &quot;extension.sayHello&quot;,
		&quot;key&quot;: &quot;ctrl+f1&quot;,
		&quot;mac&quot;: &quot;cmd+shift+f1&quot;,
		&quot;when&quot;: &quot;editorTextFocus&quot;
	}]
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributesconfiguration&quot;&gt;contributes.configuration&lt;/h4&gt;

&lt;p&gt;提供可设置的选项，用户可以在全局或者工作空间的设置中修改这些设置信息。&lt;/p&gt;

&lt;p&gt;插件的开发者需要提供一套 JSON schema 来描述这些可以配置的选项，这样用户在修改时，能够得到编辑器的智能提示。&lt;/p&gt;

&lt;p&gt;你可以通过下面的方法来读取用户自定义的配置信息
&lt;code class=&quot;highlighter-rouge&quot;&gt;vscode.workspace.getConfiguration('myExtension')&lt;/code&gt;.&lt;/p&gt;

&lt;h5 id=&quot;例子-2&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;configuration&quot;: {
		&quot;type&quot;: &quot;object&quot;,
		&quot;title&quot;: &quot;TypeScript configuration&quot;,
		&quot;properties&quot;: {
			&quot;typescript.useCodeSnippetsOnMethodSuggest&quot;: {
				&quot;type&quot;: &quot;boolean&quot;,
				&quot;default&quot;: false,
				&quot;description&quot;: &quot;Complete functions with their parameter signature.&quot;
			},
			&quot;typescript.tsdk&quot;: {
				&quot;type&quot;: &quot;string&quot;,
				&quot;default&quot;: null,
				&quot;description&quot;: &quot;Specifies the folder path containing the tsserver and lib*.d.ts files to use.&quot;
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributeslanguages&quot;&gt;contributes.languages&lt;/h4&gt;

&lt;p&gt;提供一种新语言的信息，以便 VS Code 能够支持它的开发.&lt;/p&gt;

&lt;p&gt;这这一节中, language 一般是指一个跟文件名相关的id (See &lt;code class=&quot;highlighter-rouge&quot;&gt;TextDocument.getLanguageId()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;VS Code 有三种方式确定一个文件使用的开发语言，这三种方式可以独立使用&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;文件的扩展名 (下面说的 &lt;code class=&quot;highlighter-rouge&quot;&gt;extensions&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;文件名 ( 下面说的 &lt;code class=&quot;highlighter-rouge&quot;&gt;filenames&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;文件的第一行中的文本 (下面说的 &lt;code class=&quot;highlighter-rouge&quot;&gt;firstLine&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;最后一项 VS Code 需要的信息就是 &lt;code class=&quot;highlighter-rouge&quot;&gt;aliases&lt;/code&gt;：语言的别名，这个属性值列表的第一个会作为语言的显示名称，显示在编辑器的右下角和语言选择列表中。&lt;/p&gt;

&lt;p&gt;当用户打开了一个文件，VS Code会用这三个规则匹配文件，来确认文件所使用的语言，同时，VS Code会抛出一个 activationEvent &lt;code class=&quot;highlighter-rouge&quot;&gt;onLanguage:${language}&lt;/code&gt;(例如下面例子的 &lt;code class=&quot;highlighter-rouge&quot;&gt;onLanguage:python&lt;/code&gt;),来激活对应的插件。&lt;/p&gt;

&lt;h5 id=&quot;例子-3&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;languages&quot;: [{
		&quot;id&quot;: &quot;python&quot;,
		&quot;extensions&quot;: [ &quot;.py&quot; ],
		&quot;aliases&quot;: [ &quot;Python&quot;, &quot;py&quot; ],
		&quot;filenames&quot;: [ ... ]
		&quot;firstLine&quot;: &quot;^#!/.*\\bpython[0-9.-]*\\b&quot;
	}]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;contributesdebuggers&quot;&gt;contributes.debuggers&lt;/h4&gt;

&lt;p&gt;为 VS Code 提供一个 debug 适配器，帮助 VS Code 连接到一个外部的 debug 服务，扩展 VS Code 的调试功能。&lt;/p&gt;

&lt;p&gt;debug 适配器运行在一个单独的进程中，与 VS Code 之间采用特定的协议来通信。你需要提供至少一个可执行的脚本来实现这个 debug 适配器。&lt;/p&gt;

&lt;h5 id=&quot;例子-4&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;debuggers&quot;: [{
        	&quot;type&quot;: &quot;node&quot;,
        	&quot;program&quot;: &quot;./debugger/out/node/nodeDebug.js&quot;,
        	&quot;runtime&quot;: &quot;node&quot;,
        	&quot;enableBreakpointsFor&quot;: { &quot;languageIds&quot;: [&quot;javascript&quot;, &quot;typescript&quot;, &quot;coffeescript&quot;] }
        }]
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributesgrammars&quot;&gt;contributes.grammars&lt;/h4&gt;

&lt;p&gt;提供一套 TextMate grammar 来为 VS Code 添加语言支持。你需要提供，这组语法需要适配的语言 &lt;code class=&quot;highlighter-rouge&quot;&gt;language&lt;/code&gt;，语法的 TextMate &lt;code class=&quot;highlighter-rouge&quot;&gt;scopeName&lt;/code&gt; 值，和 语法定义文件的路径&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;注意:&lt;/strong&gt; 语法定义文件的格式可以是 JSON (扩展名 .json) 或 XML plist 格式 (如果扩展名不是 json 就认为是这种格式).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;例子-5&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&quot;contributes&quot;: {
	&quot;grammars&quot;: [{
		&quot;language&quot;: &quot;shellscript&quot;,
		&quot;scopeName&quot;: &quot;source.shell&quot;,
		&quot;path&quot;: &quot;./syntaxes/Shell-Unix-Bash.tmLanguage&quot;
	}]
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributesthemes&quot;&gt;contributes.themes&lt;/h4&gt;

&lt;p&gt;为 VS Code 提供一个 TextMate theme 代码配色主题。你需要指定一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;label&lt;/code&gt; 表明这个主题是暗色主题还是浅色主题，还有主题文件的路径（XML plist 格式）&lt;/p&gt;

&lt;h5 id=&quot;例子-6&quot;&gt;例子&lt;/h5&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;contributes&quot;: {
	&quot;themes&quot;: [{
		&quot;label&quot;: &quot;Monokai&quot;,
		&quot;uiTheme&quot;: &quot;vs-dark&quot;,
		&quot;path&quot;: &quot;./themes/Monokai.tmTheme&quot;
	}]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributessnippets&quot;&gt;contributes.snippets&lt;/h4&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;contributes&quot;: {
	&quot;snippets&quot;: [{
			&quot;language&quot;: &quot;go&quot;,
			&quot;path&quot;: &quot;./snippets/go.json&quot;
	}]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;contributesjsonvalidation&quot;&gt;contributes.jsonValidation&lt;/h4&gt;

&lt;p&gt;提供特定 json 文件的 JSON schema， &lt;code class=&quot;highlighter-rouge&quot;&gt;url&lt;/code&gt;可以是插件中内置的文件，或者一个远程的url，例如 &lt;a href=&quot;http://schemastore.org/json&quot;&gt;json schema store&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;contributes&quot;: {
    &quot;jsonValidation&quot;: [{ 
 		&quot;fileMatch&quot;: &quot;.jshintrc&quot;,
 		&quot;url&quot;: &quot;http://json.schemastore.org/jshintrc&quot;
	}]
} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;更多信息可以参考 &lt;a href=&quot;https://code.visualstudio.com/docs/extensionAPI/extension-manifest&quot;&gt;Extension Manifest File - package.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;下面，让我们来写一个 即时预览 TypeScript 执行的插件。&lt;a href=&quot;/tools/2016/10/13/vscode-ext-typescript-live-preview/&quot;&gt;VS Code 插件示例，一个 TypeScript 即时预览插件&lt;/a&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>1) VS Code 插件向导</title>
   <link href="http://imzc.me/tools/2016/10/13/getting-started-with-vscode-ext/"/>
   <updated>2016-10-13T14:42:35+00:00</updated>
   <id>http://imzc.me/tools/2016/10/13/getting-started-with-vscode-ext</id>
   <content type="html">&lt;p&gt;我会通过几篇文章介绍一下 VS Code 的插件开发。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1) VS Code 插件创建与发布&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/14/vscode-ext-what-is-in-the-project/&quot;&gt;2) VS Code 插件项目结构与配置文件&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/tools/2016/10/15/vscode-ext-typescript-live-preview/&quot;&gt;3) VS Code 插件示例，一个 TypeScript 即时预览插件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VS Code 使用 Node.js 来开发插件，插件运行在单独的 Node.js 进程中。
你可以看这里了解更多 VS Code 插件系统的信息：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/15/vscode-the-architecture/&quot;&gt;VS Code 核心架构&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/16/vscode-the-extensions/&quot;&gt;VS Code 插件系统的能力&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;vs-code-插件创建与发布&quot;&gt;VS Code 插件创建与发布&lt;/h2&gt;

&lt;h2 id=&quot;创建项目&quot;&gt;创建项目&lt;/h2&gt;

&lt;p&gt;vscode team 开发了 &lt;a href=&quot;https://github.com/Microsoft/vscode-generator-code&quot;&gt;Yeoman generator&lt;/a&gt; 帮助大家快速开始创建一个 vscode extension.&lt;/p&gt;

&lt;!--more--&gt;
&lt;h3 id=&quot;安装生成器&quot;&gt;安装生成器&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; yo generator-code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;启动生成器&quot;&gt;启动生成器&lt;/h3&gt;

&lt;p&gt;vscode 的 Yeoman 生成器会引导你创建一个 vscode extension 项目&lt;/p&gt;

&lt;p&gt;在控制台执行:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yo code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://imzc.me/public/images/openchina2016/yocode.jpg&quot; alt=&quot;yo code output&quot; /&gt;&lt;/p&gt;

&lt;p&gt;生成器提供了空项目和若干其他项目类型的模板，可以按需选择。生成器的更多详细信息可以参考 &lt;a href=&quot;https://code.visualstudio.com/docs/tools/yocode&quot;&gt;vscode 的官方文档&lt;/a&gt;。
我们这里使用 TypeScript 创建一个新的 vscode extension。&lt;/p&gt;

&lt;h2 id=&quot;开发测试&quot;&gt;开发测试&lt;/h2&gt;

&lt;p&gt;我们稍后主要讲这一块&lt;/p&gt;

&lt;h2 id=&quot;发布-extension&quot;&gt;发布 extension&lt;/h2&gt;

&lt;h3 id=&quot;安装-vscode-extension-发布工具-vsce&quot;&gt;安装 vscode extension 发布工具 vsce&lt;/h3&gt;

&lt;p&gt;vsce 是 vscode team 开发的命令行工具，辅助开发者打包和发布 extension。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; vsce
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;打包插件&quot;&gt;打包插件&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vsce package
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;package&lt;/code&gt; 命令可以将 extension 打包为一个 &lt;code class=&quot;highlighter-rouge&quot;&gt;.vsix&lt;/code&gt; 文件，你可以用 vscode 打开它本机安装，或者将它分享给他人。&lt;/p&gt;

&lt;h3 id=&quot;发布到-vscode-marketplace&quot;&gt;发布到 vscode Marketplace&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vsce publish
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;你可以使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;publish&lt;/code&gt; 来将插件发布到 vscode 的官方市场，与全球数百万开发者分享。
需要注意的是，在执行命令之前你需要注册一个 &lt;a href=&quot;https://www.visualstudio.com/en-us/get-started/setup/sign-up-for-visual-studio-online&quot;&gt;Visual Studio Team Services&lt;/a&gt; 账号，
并对 vsce 进行一些设置。具体请参考 &lt;a href=&quot;https://code.visualstudio.com/docs/tools/vscecli&quot;&gt;vscode vsce 官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;我们继续看一下 &lt;a href=&quot;/tools/2016/10/13/vscode-ext-what-is-in-the-project/&quot;&gt;VS Code 插件项目的结构与配置文件&lt;/a&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>少点光芒 - 让 Web 开发环境全面黑化</title>
   <link href="http://imzc.me/dev/2016/08/25/make-them-all-dark/"/>
   <updated>2016-08-25T14:42:35+00:00</updated>
   <id>http://imzc.me/dev/2016/08/25/make-them-all-dark</id>
   <content type="html">&lt;p&gt;话不多说，这里介绍怎样将开发环境尽可能变成暗色，防止眼睛疲劳。&lt;/p&gt;

&lt;h2 id=&quot;ide&quot;&gt;IDE&lt;/h2&gt;

&lt;p&gt;目前主流的 IDE 都提供了主题选择，这里便不再多说。&lt;/p&gt;

&lt;h2 id=&quot;chrome-developer-tools&quot;&gt;Chrome Developer Tools&lt;/h2&gt;

&lt;p&gt;Chrome DevTools 是 Web 开发者必不可少的工具，借助一款 Extension 我们能够很容易将它改造成深色。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/devtools-theme-zero-dark/bomhdjeadceaggdgfoefmpeafkjhegbo&quot;&gt;DevTools Theme: Zero Dark Matrix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/devtools.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;安装步骤&quot;&gt;安装步骤&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;安装该 Extension&lt;/li&gt;
  &lt;li&gt;打开 &lt;code class=&quot;highlighter-rouge&quot;&gt;chrome://flags/#enable-devtools-experiments&lt;/code&gt; 启用 &lt;code class=&quot;highlighter-rouge&quot;&gt;开发者工具实验性功能&lt;/code&gt;，重启 Chrome。&lt;/li&gt;
  &lt;li&gt;打开 Chrome DevTools, 选择 &lt;code class=&quot;highlighter-rouge&quot;&gt;Experiments&lt;/code&gt; 标签, 选中 ‘Allow custom UI themes’.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/devtools-setting.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/devtools-allow-theme.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;重新打开 DevTools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;windows&quot;&gt;Windows&lt;/h2&gt;

&lt;p&gt;Windows 提供了主题机制，但是，只限于官方主题，大部分就是改改背景和 Title bar 配色，我们可以借助第三方软件实现更加定制化的主题。&lt;/p&gt;

&lt;p&gt;比如这个仿照 Gnome Arc Theme 来做的 Windows 主题&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://neiio.deviantart.com/art/Arc-618235768&quot;&gt;A Theme for Windows 10 - Arc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/arc.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;几个前置依赖：&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://neiio.deviantart.com/art/How-to-Install-Custom-Themes-262833454&quot;&gt;How to Install Custom Themes&lt;/a&gt; - 解除 Windows 对第三方主题的限制&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.msfn.org/board/topic/170375-oldnewexplorer-118/&quot;&gt;OldNewExplorer&lt;/a&gt; - （可选） 还原 Win7 的 资源管理器，因为 Win 8 / 10 的 Ribbon 菜单还不支持主题。&lt;/p&gt;

&lt;h2 id=&quot;mac-os-x&quot;&gt;Mac OS X&lt;/h2&gt;

&lt;p&gt;Mac OS 目前支持让 Dock 和 Menu 变反色，知道让 Finder 变深色方法的话请告诉我。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;have fun!&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>Visual Studio Code / Egret Wing 技术架构：Wing 对 VS Code 的扩展</title>
   <link href="http://imzc.me/dev/2016/08/17/wing-vs-vscode/"/>
   <updated>2016-08-17T14:42:35+00:00</updated>
   <id>http://imzc.me/dev/2016/08/17/wing-vs-vscode</id>
   <content type="html">&lt;h2 id=&quot;系列目录&quot;&gt;系列目录&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/15/vscode-the-architecture/&quot;&gt;核心架构&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/16/vscode-the-extensions/&quot;&gt;插件系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/17/wing-vs-vscode/&quot;&gt;Wing 对 VS Code 的扩展&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wing 的主要使命是进行可视化的游戏开发，但 VSC 现有的插件系统并不能满足可视化开发的需求，所以 Wing 对 VSC 进行了一系列扩展。&lt;/p&gt;

&lt;h2 id=&quot;wing-扩展-vsc-遵循的原则&quot;&gt;Wing 扩展 VSC 遵循的原则&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;优先使用插件完成新功能&lt;/li&gt;
  &lt;li&gt;不改动 VSC 的核心架构&lt;/li&gt;
  &lt;li&gt;遵循 VSC 内部组件的注册和管理方式&lt;/li&gt;
  &lt;li&gt;保证 Wing 跟新版本 VSC 的兼容性&lt;/li&gt;
&lt;/ul&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;ui-改动&quot;&gt;UI 改动&lt;/h1&gt;

&lt;p&gt;VSC 的 UI 是由一个个 &lt;code class=&quot;highlighter-rouge&quot;&gt;Part&lt;/code&gt; 组成的，每个 &lt;code class=&quot;highlighter-rouge&quot;&gt;Part&lt;/code&gt; 由 &lt;code class=&quot;highlighter-rouge&quot;&gt;Workbanch&lt;/code&gt; 统一管理，由 &lt;code class=&quot;highlighter-rouge&quot;&gt;WorkbanchLayout&lt;/code&gt; 负责布局。每个 &lt;code class=&quot;highlighter-rouge&quot;&gt;Part&lt;/code&gt; 功能独立，改变布局并不会对功能产生影响。添加新的 &lt;code class=&quot;highlighter-rouge&quot;&gt;Part&lt;/code&gt; 可以为 Wing 添加新的功能比如右边栏和工具栏。&lt;/p&gt;

&lt;h2 id=&quot;取消-activitybar&quot;&gt;取消 ActivityBar&lt;/h2&gt;

&lt;p&gt;为了使左边栏，下边栏（输出、错误窗口）和右边栏风格统一，我们在 Wing 3 的第一个版本中取消了 VSC 的ActivityBar 将它挪到了左边栏的上方。同时为下边栏添加了切换按钮，方便切换不同的面板。&lt;/p&gt;

&lt;h2 id=&quot;添加内置控制台&quot;&gt;添加内置控制台&lt;/h2&gt;

&lt;p&gt;早期版本的 VSC 中没有内置的控制台，这让很多开发者感到不便。所以我们在 Wing 3.0 的第二个版本中添加了内置的控制台。内置控制台派生自 VSC 的 Panel，对 VSC 本身改动非常小。只需要简单添加引用然后注册即可。在今年中 VSC 也是添加了内置控制台的功能，经过几个版本的更新，现在已经支持中文和复制粘贴，Wing 3.1 目前已经将控制台还原到 VSC 内置的版本。&lt;/p&gt;

&lt;h2 id=&quot;添加右边栏&quot;&gt;添加右边栏&lt;/h2&gt;

&lt;p&gt;右边栏在可视化编辑界面中非常重要，所以我们添加了右边栏这个 &lt;code class=&quot;highlighter-rouge&quot;&gt;Part&lt;/code&gt;, 并将接口通过插件 API 开放给了开发者。此次插件大赛中多款产品都使用了右边栏的功能。&lt;/p&gt;

&lt;h2 id=&quot;windows-下使用无边框窗口&quot;&gt;Windows 下使用无边框窗口&lt;/h2&gt;

&lt;p&gt;VSC 在 Windows 系统下，标题栏和菜单栏占据了很大的空间，而且在深色主题下，整体风格不太统一。我们重新设计了顶部区域，将菜单栏和标题栏合二为一，整体风格更加统一了。&lt;/p&gt;

&lt;h2 id=&quot;添加工具栏&quot;&gt;添加工具栏&lt;/h2&gt;

&lt;p&gt;工具栏集成了常用的操作按钮，这一点也是向传统 IDE 的回归，降低入手门槛。&lt;/p&gt;

&lt;h1 id=&quot;wing-对-插件-api-的扩展&quot;&gt;Wing 对 插件 API 的扩展&lt;/h1&gt;

&lt;h2 id=&quot;ui-扩展-api&quot;&gt;UI 扩展 API&lt;/h2&gt;

&lt;p&gt;VSC 的插件体系中没有 UI 相关的 API，让用户交互变得非常困难，为此 Wing 对插件 API 做的主要扩展就是添加 UI 相关的 API。现在 Wing 主要有两种 UI 展现方式。&lt;/p&gt;

&lt;h3 id=&quot;数据驱动的-ui&quot;&gt;数据驱动的 UI&lt;/h3&gt;

&lt;p&gt;你可以使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;wing.window.showPopup&amp;lt;O&amp;gt;(type: PopupType, store?: Store, options?: O): Thenable&amp;lt;Store&amp;gt;&lt;/code&gt; 来显示一个弹出窗体。&lt;code class=&quot;highlighter-rouge&quot;&gt;store&lt;/code&gt; 为一个类似 JSON Schema 的 object，通过这个 object Wing 会自动创建一个表单 UI，展现给用户，用户完成输入后，将结果返回给插件。这种方式的交互，插件开发者可以不关心 Wing 的主题样式，无需编写 UI 即可完成简单的交互操作，缺点就是对 UI 的控制性比较弱。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://edn.egret.com/cn/data/upload/asset/20160308/56de4ff73daba.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;使用-webview-编写-ui&quot;&gt;使用 WebView 编写 UI&lt;/h3&gt;

&lt;p&gt;在 WebView 中用户可以展示自己的 HTML page，可以完成非常复杂的 UI 交互。目前在 Wing 中，插件开发者可以在弹出窗口，代码编辑器区域和右边栏中使用 WebView 设计自己的界面。&lt;/p&gt;

&lt;p&gt;由于 WebView 是单独的进程，WebView 进程中的代码可以使用 Wing 提供的 IPC 通信与插件主进程进行通信，将 UI 跟用户的编辑器操作连接起来。&lt;/p&gt;

&lt;p&gt;Wing 内置的 HTTP Server 就是采用了 WebView 弹窗作为 UI 的插件，由插件进程启动 HTTP Server，当用户点击插件在状态栏中的 icon 时，插件进程启动一个WebView 来展示 Server 的状态。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://edn.egret.com/cn/data/upload/asset/20160621/57693c4dce59f.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;模板扩展-api&quot;&gt;模板扩展 API&lt;/h2&gt;

&lt;p&gt;项目模板也是非常常用的一个功能。Wing 为 VSC 添加了新建项目的向导。通过插件可以为这个向导添加项目模板。目前 Wing 内置的十几种项目模板都是由插件实现的。其中也包含了 Egret 这样具有外部依赖，比较复杂的项目模板。&lt;/p&gt;

&lt;p&gt;此外 Wing 还增加了文件创建模板，方便扩展新建文件的菜单，比如 Wing 3.1 内置的创建 EUI 组件的功能就是依靠这个 API 实现的，它能够同时创建两个相互关联的 EXML 和 TS 文件。&lt;/p&gt;

&lt;h2 id=&quot;集成常用插件&quot;&gt;集成常用插件&lt;/h2&gt;

&lt;p&gt;Wing 集成了 Egret 开发必备的 VSC 开源插件：Chrome Debugger，并对它进行了扩展和增强。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Visual Studio Code / Egret Wing 技术架构：插件系统</title>
   <link href="http://imzc.me/dev/2016/08/16/vscode-the-extensions/"/>
   <updated>2016-08-16T14:42:35+00:00</updated>
   <id>http://imzc.me/dev/2016/08/16/vscode-the-extensions</id>
   <content type="html">&lt;h2 id=&quot;系列目录&quot;&gt;系列目录&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/15/vscode-the-architecture/&quot;&gt;核心架构&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/16/vscode-the-extensions/&quot;&gt;插件系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/17/wing-vs-vscode/&quot;&gt;Wing 对 VS Code 的扩展&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在上一篇我介绍了 VSC 的基础架构。这篇我们来说一下对 VSC 来讲至关重要的插件系统。&lt;/p&gt;

&lt;h2 id=&quot;为什么插件系统对-vsc-如此重要&quot;&gt;为什么插件系统对 VSC 如此重要&lt;/h2&gt;

&lt;p&gt;在早期的版本中 VSC 并没有插件系统，只支持 TypeScript、JavaScript和C#的智能感知。还有其余40中语言的代码着色。所以 VSC 只是出现在微软技术的社区中。15 年 12 月份，VSC 发布了第一个支持扩展的版本。不久之后就出现了许多其他语言的支持，比如 Go 语言、C++、Java、Python、Ruby。&lt;/p&gt;

&lt;p&gt;所以说有了核心编辑器的极速体验，加上良好的扩展能力才成就了 VSC。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;vsc-支持哪些扩展&quot;&gt;VSC 支持哪些扩展&lt;/h1&gt;

&lt;h2 id=&quot;语言支持&quot;&gt;语言支持&lt;/h2&gt;

&lt;p&gt;VSC 制订了一套完善的语言支持体系，方便支持新的编程语言。&lt;/p&gt;

&lt;h3 id=&quot;一个代码编辑器需要哪些功能来支持一种新语言&quot;&gt;一个代码编辑器需要哪些功能来支持一种新语言&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;代码显示
    &lt;ul&gt;
      &lt;li&gt;代码着色&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;智能感知
    &lt;ul&gt;
      &lt;li&gt;代码提示&lt;/li&gt;
      &lt;li&gt;代码跳转&lt;/li&gt;
      &lt;li&gt;鼠标触碰提示&lt;/li&gt;
      &lt;li&gt;查找引用&lt;/li&gt;
      &lt;li&gt;错误提示&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;代码修改
    &lt;ul&gt;
      &lt;li&gt;自动补全&lt;/li&gt;
      &lt;li&gt;重构功能&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/lang-impls.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;兼容-textmate-的代码着色分析&quot;&gt;兼容 TextMate 的代码着色分析&lt;/h3&gt;
&lt;p&gt;可以简单的将 TextMate 的语言着色配置文件拷贝到插件中，并在 package.json 中指定即可。&lt;/p&gt;

&lt;h3 id=&quot;语言支持通用协议&quot;&gt;语言支持通用协议&lt;/h3&gt;
&lt;p&gt;VSC 约定了一种通用的通信协议来支持多种语言&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/lang-service.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;由于 VSC 采用多进程的架构，语言的开发者可以使用自己熟悉的语言编写这门语言的语言服务，VSC 将采用 JSON-RPC 通信的方式跟语言服务沟通，执行用户命令，获取结果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/protocols.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;debugger&quot;&gt;Debugger&lt;/h2&gt;

&lt;p&gt;同语言服务类似，VSC 开放了一组通用协议来满足不同语言不通平台的调试需求。&lt;/p&gt;

&lt;h2 id=&quot;主题配色方案&quot;&gt;主题/配色方案&lt;/h2&gt;

&lt;p&gt;VSC 采用了跟 TextMate 相同的配色方案文件格式。&lt;/p&gt;

&lt;h2 id=&quot;编辑器辅助&quot;&gt;编辑器辅助&lt;/h2&gt;

&lt;p&gt;VSC 提供了编辑器操作 API，你能够实时获取用户输入点、当前文件代码。从而可以根据用户当前文档确定可以提供的快捷操作。比如自动添加不存在的方法等。&lt;/p&gt;

&lt;h2 id=&quot;扩展命令&quot;&gt;扩展命令&lt;/h2&gt;

&lt;p&gt;开发者可以在插件中定义自己的命令，这些命令会出现在“命令面板” 中，开发者可以通过 “ctrl/cmd + shift + p” 或 “F1” 来调用这些命令，完成复杂的操作。&lt;/p&gt;

&lt;p&gt;插件可以使用所有的 NodeJS API，配合各种 NodeJS 库，能够完成非常有想象力的功能。&lt;/p&gt;

&lt;h2 id=&quot;扩展菜单&quot;&gt;扩展菜单&lt;/h2&gt;

&lt;p&gt;VSC 提供了文件管理器菜单，编辑器菜单，文件标题菜单扩展点。方便开发者针对不同的上下文进行操作。&lt;/p&gt;

&lt;h2 id=&quot;快捷键&quot;&gt;快捷键&lt;/h2&gt;

&lt;p&gt;开发者可以为各种自定义操作指定快捷键。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/extensions/overview&quot;&gt;VSC 插件开发文档&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.egret.com/cn/github/egret-docs/Wing/plugin/introduction/index.html&quot;&gt;Wing 插件开发文档&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Visual Studio Code / Egret Wing 技术架构：基础</title>
   <link href="http://imzc.me/dev/2016/08/15/vscode-the-architecture/"/>
   <updated>2016-08-15T14:42:35+00:00</updated>
   <id>http://imzc.me/dev/2016/08/15/vscode-the-architecture</id>
   <content type="html">&lt;h2 id=&quot;系列目录&quot;&gt;系列目录&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/15/vscode-the-architecture/&quot;&gt;核心架构&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/16/vscode-the-extensions/&quot;&gt;插件系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dev/2016/08/17/wing-vs-vscode/&quot;&gt;Wing 对 VS Code 的扩展&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;vs-code-简单介绍&quot;&gt;VS Code 简单介绍&lt;/h2&gt;

&lt;p&gt;Visual Studio Code (下面简称VSC) 是由微软公司开发的开源、免费、跨平台的代码编辑器，微软希望它在保持核心轻量化文本编辑器的基础上，为编辑器添加项目支持、智能感知和编译调试。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/codevside.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;VSC Team 由著名工程师 Erich Gamma 领导，Erich 是《设计模式》作者之一，Eclipse 之父，拥有多年的 IDE 开发经验。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/erich.jpg&quot; alt=&quot;Erich Gamma&quot; /&gt;&lt;/p&gt;

&lt;p&gt;VSC 的前身是微软基于云端的编辑器项目：Monaco 编辑器，它作为微软云服务的一部分，提供在线编辑源代码的能力。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/monaco.png&quot; alt=&quot;Monaco 编辑器&quot; /&gt;&lt;/p&gt;

&lt;p&gt;由于云端编辑器的种种限制，和微软近年来对Windows外平台的态度转变，微软决定由它扩展开发为一个全平台通用的代码编辑器。&lt;/p&gt;

&lt;h2 id=&quot;vsc-技术路线&quot;&gt;VSC 技术路线&lt;/h2&gt;

&lt;h3 id=&quot;electron&quot;&gt;Electron&lt;/h3&gt;

&lt;p&gt;为了保护本地文件的安全性，浏览器都没有提供直接的本地文件访问权限。为了实现本地文件系统的访问，VSC 采用了 Github 的开源项目 Electron。&lt;/p&gt;

&lt;p&gt;Electron 原名 Atom-Shell，是 Github 为 Atom 编辑器编写的一个开源框架。它将 Chromium 和 Node.js 完美融合，让开发者能用使用 HTML 来实现 App UI，用 Node.js API 来访问文件系统。&lt;/p&gt;

&lt;h3 id=&quot;typescript&quot;&gt;TypeScript&lt;/h3&gt;

&lt;p&gt;VSC 的主要代码都是用 TypeScript 编写，目前 VSC 的核心有 1100 多个 TS 文件，TypeScript 的语言优势为多次重构提供了保障。&lt;/p&gt;

&lt;h3 id=&quot;纯-dom-操作&quot;&gt;纯 DOM 操作&lt;/h3&gt;

&lt;p&gt;为了保证 UI 响应速度，VSC 没有采用现有的 UI 库，大部分 UI 采用绝对尺寸，简单粗暴的避免大面积 UI 的联动刷新。&lt;/p&gt;

&lt;h1 id=&quot;vsc-为优化性能做的努力&quot;&gt;VSC 为优化性能做的努力&lt;/h1&gt;

&lt;p&gt;VSC team 做了很多工作来提高 VSC 的性能，我们来看一下：&lt;/p&gt;

&lt;h2 id=&quot;启动速度优化&quot;&gt;启动速度优化&lt;/h2&gt;

&lt;p&gt;基于 HTML 技术的编辑器，受限于 Chrome 一般都会有启动速度慢的问题。除了基本的 JS / CSS 合并压缩外，VSC 还将特别常用的 ActivityBar icon 直接内嵌在了 css 中。但是即便如此，启动速度跟 Sublime Text 等编辑器还是有比较大的差距。&lt;/p&gt;

&lt;p&gt;这里说一个技巧，当我们用 VSC 打开一个文件的时候，VSC 会默认启动一个新的 VSC 窗口，这样启动的时间比较长，我们可以通过设置全局设置项里的 &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;window.openFilesInNewWindow&quot;: false&lt;/code&gt; 来使用已经打开的 VSC 实例打开新文件，这样就几乎没有了等待的时间。&lt;/p&gt;

&lt;h2 id=&quot;代码编辑器滚动虚拟化&quot;&gt;代码编辑器滚动虚拟化&lt;/h2&gt;

&lt;p&gt;让编辑器只渲染可见的部分，减小大文件编辑对浏览器的压力。同时配合 css translate3d 避免重复渲染没有改变的代码行。&lt;/p&gt;

&lt;h2 id=&quot;着色速度优化&quot;&gt;着色速度优化&lt;/h2&gt;

&lt;p&gt;为了不重复发明轮子，VSC 采用了跟 TextMate 一样的代码着色分析语法。它是基于正则表达式的一套分析方案，虽然 JS 原生支持正则表达式，但为了更高的效率，VSC 使用了 C++ 编写的一套正则表达式引擎来提高效率。&lt;/p&gt;

&lt;h2 id=&quot;多进程架构红利&quot;&gt;多进程架构红利&lt;/h2&gt;

&lt;p&gt;前面讲的这些都只是一些小的优化，真正保证响应速度的还是多进程架构带来的优势。&lt;/p&gt;

&lt;h1 id=&quot;vsc-的进程结构&quot;&gt;VSC 的进程结构&lt;/h1&gt;

&lt;p&gt;VSC 采用多进程架构，VSC 启动后主要有下面的几个进程：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;p 后台进程&lt;/li&gt;
  &lt;li&gt;p 编辑器窗口 - 由后台进程启动，也是多进程架构
    &lt;ul&gt;
      &lt;li&gt;HTML 编写的 UI
        &lt;ul&gt;
          &lt;li&gt;Activitybar&lt;/li&gt;
          &lt;li&gt;Viewlets&lt;/li&gt;
          &lt;li&gt;Panels&lt;/li&gt;
          &lt;li&gt;Editors&lt;/li&gt;
          &lt;li&gt;Statusbar&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Nodejs 异步 IO
        &lt;ul&gt;
          &lt;li&gt;FileService&lt;/li&gt;
          &lt;li&gt;ConfigurationService&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;p 插件宿主进程
        &lt;ul&gt;
          &lt;li&gt;插件实例
            &lt;ul&gt;
              &lt;li&gt;p 插件子进程 - 如 TS 语言服务&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;插件实例&lt;/li&gt;
          &lt;li&gt;插件实例&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;p Debug 进程&lt;/li&gt;
      &lt;li&gt;p Search 进程&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;p 编辑器窗口&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/processes.png&quot; alt=&quot;多进程&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;后台进程&quot;&gt;后台进程&lt;/h2&gt;

&lt;p&gt;后台进程是 VSC 的入口，主要负责管理编辑器生命周期，进程间通信，自动更新，菜单管理等。&lt;/p&gt;

&lt;p&gt;我们启动 VSC 的时候，后台进程会首先启动，读取各种配置信息和历史记录，然后将这些信息和主窗口 UI 的 HTML 主文件路径整合成一个 URL，启动一个浏览器窗口来显示编辑器的 UI。后台进程会一直关注 UI 进程的状态，当所有 UI 进程被关闭的时候，整个编辑器退出。&lt;/p&gt;

&lt;p&gt;此外后台进程还会开启一个本地的 Socket，当有新的 VSC 进程启动的时候，会尝试连接这个 Socket，并将启动的参数信息传递给它，由已经存在的 VSC 来执行相关的动作，这样能够保证 VSC 的唯一性，避免出现多开文件夹带来的问题。&lt;/p&gt;

&lt;h2 id=&quot;编辑器窗口&quot;&gt;编辑器窗口&lt;/h2&gt;

&lt;p&gt;编辑器窗口进程负责整个 UI 的展示。也就是我们所见的部分。UI 全部用 HTML 编写没有太多需要介绍的部分。&lt;/p&gt;

&lt;h2 id=&quot;io&quot;&gt;IO&lt;/h2&gt;

&lt;p&gt;项目文件的读取和保存由主进程的 NodeJS API 完成，因为全部是异步操作，即便有比较大的文件，也不会对 UI 造成阻塞。IO 跟 UI 在一个进程，并采用异步操作，在保证 IO 性能的基础上也保证了 UI 的响应速度。&lt;/p&gt;

&lt;h2 id=&quot;插件进程&quot;&gt;插件进程&lt;/h2&gt;

&lt;p&gt;每一个 UI 窗口会启动一个 NodeJS 子进程作为插件的宿主进程。所有的插件会共同运行在这个进程中。&lt;/p&gt;

&lt;p&gt;这样设计最主要的目的就是避免复杂的插件系统阻塞 UI 的响应。这要从JS和浏览器说起。&lt;/p&gt;

&lt;p&gt;在大部分的操作系统中，显示器的刷新频率是 60 帧每秒，也就是说应用需要在 16.7 毫秒内完成所有的计算和 UI 刷新。HTML DOM 的速度向来为人诟病，留给JS的时间就更少了。所以要在这么短的时间内完成所有指令才能保证 UI 的响应速度。&lt;/p&gt;

&lt;p&gt;但是事实上我们很难在这么短的时间内完成诸如对一万行代码进行着色这种任务。这就需要我们将这种耗时比较长的任务转移到其他的线程或进程来做，等耗时任务结束，再将结果返回给 UI 进程即可。&lt;/p&gt;

&lt;p&gt;VSC 最近的版本中将所有的语言支持都改成了插件。包括之前在 UI 进程用 Web Worker 实现的 Markdown 语言支持。后面我会介绍一个典型的语言服务的工作方式。&lt;/p&gt;

&lt;p&gt;但是将插件放在一个单独进程也有很明显的缺点，因为是一个单独的进程，而不是 UI 进程，所以没有办法直接访问 DOM 树，想要实时高效的改变 UI 变得很难，在 VSC 的扩展体系中几乎没有对 UI 进行扩展的 API。&lt;/p&gt;

&lt;h2 id=&quot;debug-进程&quot;&gt;Debug 进程&lt;/h2&gt;

&lt;p&gt;Debugger 插件跟普通的插件有一点区别，它不运行在插件进程中，而是在每次 debug 的时候由UI单独新开一个进程。&lt;/p&gt;

&lt;h2 id=&quot;搜索进程&quot;&gt;搜索进程&lt;/h2&gt;

&lt;p&gt;搜索是一个十分耗时的任务，VSC 也使用的单独的进程来实现这个功能，保证主窗口的效率。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;将耗时的任务分到多个进程中，有效的保证了主进程的响应速度。&lt;/strong&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Add Headers for Static Files with ASP.NET Core</title>
   <link href="http://imzc.me/dotnet/2016/08/10/add-header-for-static-files/"/>
   <updated>2016-08-10T14:42:35+00:00</updated>
   <id>http://imzc.me/dotnet/2016/08/10/add-header-for-static-files</id>
   <content type="html">&lt;p&gt;Sometimes we need to add some headers for static file requests.&lt;/p&gt;

&lt;p&gt;For example, if we want to allow third-party website to access images or audios 
through XHR (it’s usefull when you want to do some custom decoding with these files). 
You need to add &lt;code class=&quot;highlighter-rouge&quot;&gt;Access-Control-Allow-Origin: *&lt;/code&gt; (relpace &lt;code class=&quot;highlighter-rouge&quot;&gt;*&lt;/code&gt; with your domain if you don’t realy want to allow any domain to access).&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;If you use &lt;code class=&quot;highlighter-rouge&quot;&gt;Microsoft.AspNetCore.StaticFiles&lt;/code&gt; to handle static file requests, you should find &lt;code class=&quot;highlighter-rouge&quot;&gt;app.UseStaticFiles()&lt;/code&gt; in startup.cs.&lt;/p&gt;

&lt;p&gt;Then what we need to do is add an Option like this:&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;UseStaticFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StaticFileOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OnPrepareResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Access-Control-Allow-Origin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Done!&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;StaticFileOptions&lt;/code&gt; has some other properties to customize the StaticFileMiddleware behavior.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     Used to map files to content-types.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IContentTypeProvider&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ContentTypeProvider&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     The default content type for a request if the ContentTypeProvider cannot determine&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     one. None is provided by default, so the client must determine the format themselves.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DefaultContentType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     Called after the status code and headers have been set, but before the body has&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     been written. This can be used to add or change the response headers.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StaticFileResponseContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OnPrepareResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     If the file is not a recognized content-type should it be served? Default: false.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServeUnknownFileTypes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Have fun!&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>CSS Style inherit</title>
   <link href="http://imzc.me/css/2016/08/02/css-inherit/"/>
   <updated>2016-08-02T14:42:35+00:00</updated>
   <id>http://imzc.me/css/2016/08/02/css-inherit</id>
   <content type="html">&lt;p&gt;Take a look at this&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.content&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;green&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.content&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.content&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;purple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.content&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;h1&lt;/code&gt; will take the color &lt;code class=&quot;highlighter-rouge&quot;&gt;purple&lt;/code&gt; instead of &lt;code class=&quot;highlighter-rouge&quot;&gt;green&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The inherit CSS-value causes the element for which it is specified to take the computed value of the property from its parent element. It is allowed on every CSS property.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Run dotnet core on Azure.cn</title>
   <link href="http://imzc.me/dotnet/2016/07/15/run-dotnet-core-on-azure-cn/"/>
   <updated>2016-07-15T14:42:35+00:00</updated>
   <id>http://imzc.me/dotnet/2016/07/15/run-dotnet-core-on-azure-cn</id>
   <content type="html">&lt;p&gt;.net core RTM 了，Azure global 已经提供支持，但是慢半拍的 Azure 中国 WebSites 目前并不支持 asp.net core。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Orz&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;经过各种尝试，终于发现了临时解决的办法：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;让我们把整个 .net core 上传上去把&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;操作步骤&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;将系统安装的.net core 文件夹上传到 &lt;code class=&quot;highlighter-rouge&quot;&gt;wwwroot&lt;/code&gt; 的父级目录, 让我们能够在 &lt;code class=&quot;highlighter-rouge&quot;&gt;wwwroot&lt;/code&gt; 使用 &lt;code class=&quot;highlighter-rouge&quot;&gt;..\dotnet\dotnet.exe&lt;/code&gt; 访问到它。&lt;/li&gt;
  &lt;li&gt;修改发布后的 &lt;code class=&quot;highlighter-rouge&quot;&gt;web.config&lt;/code&gt; 将 &lt;code class=&quot;highlighter-rouge&quot;&gt;configuration\system.webServer\aspNetCore@processPath&lt;/code&gt; 由 &lt;code class=&quot;highlighter-rouge&quot;&gt;%LAUNCHER_PATH%&lt;/code&gt; 或 &lt;code class=&quot;highlighter-rouge&quot;&gt;dotnet&lt;/code&gt; 改为 &lt;code class=&quot;highlighter-rouge&quot;&gt;..\dotnet\dotnet.exe&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;:)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;有一个问题是，Visual Studio 发布项目后，会自动把 &lt;code class=&quot;highlighter-rouge&quot;&gt;processPath&lt;/code&gt; 改为 &lt;code class=&quot;highlighter-rouge&quot;&gt;dotnet&lt;/code&gt;，避免每次上传手动修改，我们在 &lt;code class=&quot;highlighter-rouge&quot;&gt;project.json&lt;/code&gt; 中添加一个后处理脚本&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;c1&quot;&gt;// project.json&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;postpublish&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;node azurecn.js %publish:OutputPath%&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;lt;====== 执行 node 脚本，替换processPath&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// azurecn.js&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'fs'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'path'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;folder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filePath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'web.config'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'utf-8'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'processPath=&quot;dotnet&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'processPath=&quot;dotnet&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'processPath=&quot;..&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;dotnet&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;dotnet.exe&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;整个世界都美好了！(●’◡’●)&lt;/p&gt;
&lt;/blockquote&gt;

</content>
 </entry>
 
 <entry>
   <title>Hi from new host</title>
   <link href="http://imzc.me/about/2016/04/15/hi-from-new-host/"/>
   <updated>2016-04-15T14:42:35+00:00</updated>
   <id>http://imzc.me/about/2016/04/15/hi-from-new-host</id>
   <content type="html">&lt;p&gt;今天换了新域名 &lt;code class=&quot;highlighter-rouge&quot;&gt;imzc.me&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;作为一个新的开始，好好写文章！&lt;/p&gt;
</content>
 </entry>
 

</feed>
