往日一去不复返 發表於 2019-6-26 18:14:00

typescript

<div>
<div>
<h2 class="heading" data-id="heading-1"><span style="font-family: 楷体; font-size: 16px">&nbsp;使用官方脚手架构建</span></h2>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">npm install -g @vue/cli
<span class="hljs-comment"># OR
yarn global add @vue/cli
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">新的<code>Vue CLI</code>工具允许开发者 使用 <code>TypeScript</code> 集成环境 创建新项目。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">只需运行<code>vue create my-app</code>。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">然后,命令行会要求选择预设。使用箭头键选择<code>Manually select features</code>。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">接下来,只需确保选择了<code>TypeScript</code>和<code>Babel</code>选项,如下图:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611163034679" width="729" height="578" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57d82715e9?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1140" data-height="904"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">完成此操作后,它会询问你是否要使用<code>class-style component syntax</code>。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">然后配置其余设置,使其看起来如下图所示。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611163127181" width="742" height="588" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57d83e1974?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1140" data-height="904"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">Vue CLI工具现在将安装所有依赖项并设置项目。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611163225739" width="916" height="726" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57dd7f8c66?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1140" data-height="904"> 接下来就跑项目喇。</span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611163245714" width="801" height="871" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57daeaf341?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1080" data-height="1175"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">总之,先跑起来再说。</span></p>
<h2 class="heading" data-id="heading-2"><span style="font-family: 楷体; font-size: 16px">2. 项目目录解析</span></h2>
<p><span style="font-family: 楷体; font-size: 16px">通过<code>tree</code>指令查看目录结构后可发现其结构和正常构建的大有不同。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611163812421" width="797" height="632" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57e05c4d0f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1140" data-height="904"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">这里主要关注<code>shims-tsx.d.ts</code>和 <code>shims-vue.d.ts</code>两个文件</span></p>
<p><span style="font-family: 楷体; font-size: 16px">两句话概括:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>shims-tsx.d.ts</code>,允许你以<code>.tsx</code>结尾的文件,在<code>Vue</code>项目中编写<code>jsx</code>代码</span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>shims-vue.d.ts</code> 主要用于 <code>TypeScript</code> 识别<code>.vue</code> 文件,<code>Ts</code>默认并不支持导入 <code>vue</code> 文件,这个文件告诉<code>ts</code> 导入<code>.vue</code> 文件都按<code>VueConstructor&lt;Vue&gt;</code>处理。</span></li>
</ul>
<p><span style="font-family: 楷体; font-size: 16px">此时我们打开亲切的<code>src/components/HelloWorld.vue</code>,将会发现写法已大有不同</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">&lt;template&gt;
&lt;div class=<span class="hljs-string">"hello"&gt;
    &lt;h1&gt;{{ msg }}&lt;/h1&gt;
    &lt;!-- 省略 --&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script lang=<span class="hljs-string">"ts"&gt;
import { Component, Prop, Vue } from <span class="hljs-string">'vue-property-decorator';

@Component
<span class="hljs-built_in">export default class HelloWorld extends Vue {
@Prop() private msg!: string;
}
&lt;/script&gt;

&lt;!-- Add <span class="hljs-string">"scoped" attribute to <span class="hljs-built_in">limit CSS to this component only --&gt;
&lt;style scoped&gt;&lt;/style&gt;
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">至此,准备开启新的篇章 <code>TypeScript</code>极速入门 和 <code>vue-property-decorator</code></span></p>
<h2 class="heading" data-id="heading-3"><span style="font-family: 楷体; font-size: 16px">3. <code>TypeScript</code>极速入门</span></h2>
<h3 class="heading" data-id="heading-4"><span style="font-family: 楷体; font-size: 16px">3.1 基本类型和扩展类型</span></h3>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611173126273" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a57de204bb4?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>Typescript</code>与<code>Javascript</code>共享相同的基本类型,但有一些额外的类型。</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px">元组 <code>Tuple</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px">枚举 <code>enum</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>Any</code> 与<code>Void</code></span></li>
</ul>
<h4 class="heading" data-id="heading-5"><span style="font-family: 楷体; font-size: 16px">1. 基本类型合集</span></h4>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 数字,二、八、十六进制都支持
<span class="hljs-built_in">let decLiteral: number = 6;
<span class="hljs-built_in">let hexLiteral: number = 0xf00d;

// 字符串,单双引都行
<span class="hljs-built_in">let name: string = <span class="hljs-string">"bob";
<span class="hljs-built_in">let sentence: string = `Hello, my name is <span class="hljs-variable">${ name }.

// 数组,第二种方式是使用数组泛型,Array&lt;元素类型&gt;:
<span class="hljs-built_in">let list: number[] = ;
<span class="hljs-built_in">let list: Array&lt;number&gt; = ;

<span class="hljs-built_in">let u: undefined = undefined;
<span class="hljs-built_in">let n: null = null;

<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<h4 class="heading" data-id="heading-6"><span style="font-family: 楷体; font-size: 16px">2. 特殊类型</span></h4>
<h5 class="heading" data-id="heading-7"><span style="font-family: 楷体; font-size: 16px">1. <strong>元组 <code>Tuple</code></strong><img class="lazyload inited loaded" alt="image-20190611174157121" width="731" height="200" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a58028534c2?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span></h5>
<p><span style="font-family: 楷体; font-size: 16px">想象 元组 作为有组织的数组,你需要以正确的顺序预定义数据类型。</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs javascript copyable" lang="javascript"><span class="hljs-keyword">const messyArray = [<span class="hljs-string">' something', <span class="hljs-number">2, <span class="hljs-literal">true, <span class="hljs-literal">undefined, <span class="hljs-literal">null];
<span class="hljs-keyword">const tuple: = [<span class="hljs-number">24, <span class="hljs-string">"Indrek" , <span class="hljs-string">"Lasn"]
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">如果不遵循 为元组 预设排序的索引规则,那么<code>Typescript</code>会警告。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611174515658" width="476" height="177" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a580a458319?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1001" data-height="372"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">​ (<code>tuple</code>第一项应为<code>number</code>类型)</span></p>
<h5 class="heading" data-id="heading-8"><span style="font-family: 楷体; font-size: 16px">2. 枚举 <code>enum</code></span></h5>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611174833904" width="586" height="160" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a580c96180f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>enum</code>类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 默认情况从0开始为元素编号,也可手动为1开始
enum Color {Red = 1, Green = 2, Blue = 4}
<span class="hljs-built_in">let c: Color = Color.Green;

<span class="hljs-built_in">let colorName: string = Color;
console.log(colorName);// 输出<span class="hljs-string">'Green'因为上面代码里它的值是2
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">另一个很好的例子是使用枚举来存储应用程序状态。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611175542886" width="652" height="334" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a580eb8d6f7?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="988" data-height="506"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<h5 class="heading" data-id="heading-9"><span style="font-family: 楷体; font-size: 16px">3. <code>Void</code></span></h5>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611175724302" width="384" height="105" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a5811b7c692?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">在<code>Typescript</code>中,<strong>你必须在函数中定义返回类型</strong>。像这样:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611175858587" width="804" height="432" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a58137c6084?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="986" data-height="530"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">若没有返回值,则会报错:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611175932713" width="724" height="286" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a58322260c4?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="998" data-height="394"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">我们可以将其返回值定义为<code>void</code>:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611180043827" width="780" height="462" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a582b658d41?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1000" data-height="592"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">此时将无法 <code>return</code></span></p>
<h5 class="heading" data-id="heading-10"><span style="font-family: 楷体; font-size: 16px">4. <code>Any</code></span></h5>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611180255381" width="824" height="225" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a58357d0129?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">Emmm...就是什么类型都行,当你无法确认在处理什么类型时可以用这个。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">但要慎重使用,用多了就失去使用Ts的意义。</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">let person: any = <span class="hljs-string">"前端劝退师"
person = 25
person = <span class="hljs-literal">true
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">主要应用场景有:</span></p>
<ol>
<li><span style="font-family: 楷体; font-size: 16px">接入第三方库</span></li>
<li><span style="font-family: 楷体; font-size: 16px">Ts菜逼前期都用</span></li>
</ol>
<h5 class="heading" data-id="heading-11"><span style="font-family: 楷体; font-size: 16px">5. <code>Never</code></span></h5>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611180943940" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a5836a7344f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">用很粗浅的话来描述就是:"<code>Never</code>是你永远得不到的爸爸。"</span></p>
<p><span style="font-family: 楷体; font-size: 16px">具体的行为是:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>throw new Error(message)</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>return error("Something failed")</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>while (true) {} // 存在无法达到的终点</code></span></li>
</ul>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611181410052" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a5839fb5caa?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1000" data-height="352"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<h4 class="heading" data-id="heading-12"><span style="font-family: 楷体; font-size: 16px">3. 类型断言</span></h4>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190611182337690" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a584a48d1d6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1003" data-height="274"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">简略的定义是:可以用来手动指定一个值的类型。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">有两种写法,尖括号和<code>as</code>:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">let someValue: any = <span class="hljs-string">"this is a string";

<span class="hljs-built_in">let strLength: number = (&lt;string&gt;someValue).length;
<span class="hljs-built_in">let strLength: number = (someValue as string).length;
<span class="copy-code-btn">复制代码</span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">使用例子有:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-keyword">function getLength(something: string | number): number {
    <span class="hljs-built_in">return something.length;
}

// index.ts(2,22): error TS2339: Property <span class="hljs-string">'length' does not exist on <span class="hljs-built_in">type <span class="hljs-string">'string | number'.
//   Property <span class="hljs-string">'length' does not exist on <span class="hljs-built_in">type <span class="hljs-string">'number'.
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">如果你访问长度将会报错,而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型的属性或方法,此时需要断言才不会报错:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-keyword">function getLength(something: string | number): number {
    <span class="hljs-keyword">if ((&lt;string&gt;something).length) {
      <span class="hljs-built_in">return (&lt;string&gt;something).length;
    } <span class="hljs-keyword">else {
      <span class="hljs-built_in">return something.toString().length;
    }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></code></span></pre>
<h3 class="heading" data-id="heading-13"><span style="font-family: 楷体; font-size: 16px">3.2 泛型:<code>Generics</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px">软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">在<code>C#</code>和<code>Java</code>中,可以使用"泛型"来创建可复用的组件,并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。</span></p>
<h4 class="heading" data-id="heading-14"><span style="font-family: 楷体; font-size: 16px">1. 泛型方法</span></h4>
<p><span style="font-family: 楷体; font-size: 16px">在TypeScript里,<strong>声明泛型方法</strong>有以下两种方式:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-keyword">function gen_func1&lt;T&gt;(arg: T): T {
    <span class="hljs-built_in">return arg;
}
// 或者
<span class="hljs-built_in">let gen_func2: &lt;T&gt;(arg: T) =&gt; T = <span class="hljs-keyword">function (arg) {
    <span class="hljs-built_in">return arg;
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>调用方式</strong>也有两种:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">gen_func1&lt;string&gt;(<span class="hljs-string">'Hello world');
gen_func2(<span class="hljs-string">'Hello world');
// 第二种调用方式可省略类型参数,因为编译器会根据传入参数来自动识别对应的类型。
<span class="copy-code-btn">复制代码</span></span></span></code></span></pre>
<h4 class="heading" data-id="heading-15"><span style="font-family: 楷体; font-size: 16px">2. 泛型与<code>Any</code></span></h4>
<p><span style="font-family: 楷体; font-size: 16px"><code>Ts</code> 的特殊类型 <code>Any</code> 在具体使用时,可以代替任意类型,咋一看两者好像没啥区别,其实不然:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 方法一:带有any参数的方法
<span class="hljs-keyword">function any_func(arg: any): any {
    console.log(arg.length);
                <span class="hljs-built_in">return arg;
}

// 方法二:Array泛型方法
<span class="hljs-keyword">function array_func&lt;T&gt;(arg: Array&lt;T&gt;): Array&lt;T&gt; {
          console.log(arg.length);
                <span class="hljs-built_in">return arg;
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></code></span></pre>
<ul>
<li><span style="font-family: 楷体; font-size: 16px">方法一,打印了<code>arg</code>参数的<code>length</code>属性。因为<code>any</code>可以代替任意类型,所以该方法在传入参数不是数组或者带有<code>length</code>属性对象时,会抛出异常。</span></li>
<li><span style="font-family: 楷体; font-size: 16px">方法二,定义了参数类型是<code>Array</code>的泛型类型,肯定会有<code>length</code>属性,所以不会抛出异常。</span></li>
</ul>
<h4 class="heading" data-id="heading-16"><span style="font-family: 楷体; font-size: 16px">3. 泛型类型</span></h4>
<p><span style="font-family: 楷体; font-size: 16px">泛型接口:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface Generics_interface&lt;T&gt; {
    (arg: T): T;
}

<span class="hljs-keyword">function func_demo&lt;T&gt;(arg: T): T {
    <span class="hljs-built_in">return arg;
}

<span class="hljs-built_in">let func1: Generics_interface&lt;number&gt; = func_demo;
func1(123);   // 正确类型的实际参数
func1(<span class="hljs-string">'123');   // 错误类型的实际参数
<span class="copy-code-btn">复制代码</span></span></span></span></span></code></span></pre>
<h3 class="heading" data-id="heading-17"><span style="font-family: 楷体; font-size: 16px">3.3 自定义类型:<code>Interface</code> vs <code>Type alias</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px"><code>Interface</code>,国内翻译成接口。</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>Type alias</code>,类型别名。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190613192317416" data-src="https://user-gold-cdn.xitu.io/2019/6/13/16b512f2dc49f9e5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1000" data-height="300"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">以下内容来自:</span></p>
<blockquote>
<p><span style="font-family: 楷体; font-size: 16px">Typescript 中的 interface 和 type 到底有什么区别</span></p>
</blockquote>
<h4 class="heading" data-id="heading-18"><span style="font-family: 楷体; font-size: 16px">1. 相同点</span></h4>
<p><span style="font-family: 楷体; font-size: 16px"><strong>都可以用来描述一个对象或函数:</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface User {
name: string
age: number
}

<span class="hljs-built_in">type User = {
name: string
age: number
};

interface SetUser {
(name: string, age: number): void;
}
<span class="hljs-built_in">type SetUser = (name: string, age: number): void;

<span class="copy-code-btn">复制代码</span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>都允许拓展(extends):</strong></span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>interface</code> 和 <code>type</code> 都可以拓展,并且两者并不是相互独立的,也就是说<code>interface</code>可以 <code>extends type</code>, <code>type</code> 也可以 <code>extends interface</code> 。 <strong>虽然效果差不多,但是两者语法不同</strong>。</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><strong>interface extends interface</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface Name {
name: string;
}
interface User extends Name {
age: number;
}
<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>type extends type</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">type Name = {
name: string;
}
<span class="hljs-built_in">type User = Name &amp; { age: number};
<span class="copy-code-btn">复制代码</span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>interface extends type</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">type Name = {
name: string;
}
interface User extends Name {
age: number;
}
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>type extends interface</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface Name {
name: string;
}
<span class="hljs-built_in">type User = Name &amp; {
age: number;
}

<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<h4 class="heading" data-id="heading-19"><span style="font-family: 楷体; font-size: 16px">2. 不同点</span></h4>
<p><span style="font-family: 楷体; font-size: 16px"><strong><code>type</code> 可以而 <code>interface</code> 不行</strong></span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>type</code> 可以声明基本类型别名,联合类型,元组等类型</span></li>
</ul>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 基本类型别名
<span class="hljs-built_in">type Name = string

// 联合类型
interface Dog {
    wong();
}
interface Cat {
    miao();
}

<span class="hljs-built_in">type Pet = Dog | Cat

// 具体定义数组每个位置的类型
<span class="hljs-built_in">type PetList =
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>type</code> 语句中还可以使用 <code>typeof</code>获取实例的 类型进行赋值</span></li>
</ul>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 当你想获取一个变量的类型时,使用 typeof
<span class="hljs-built_in">let div = document.createElement(<span class="hljs-string">'div');
<span class="hljs-built_in">type B = typeof div
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<ul>
<li><span style="font-family: 楷体; font-size: 16px">其他骚操作</span></li>
</ul>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">type StringOrNumber = string | number;
<span class="hljs-built_in">type Text = string | { text: string };
<span class="hljs-built_in">type NameLookup = Dictionary&lt;string, Person&gt;;
<span class="hljs-built_in">type Callback&lt;T&gt; = (data: T) =&gt; void;
<span class="hljs-built_in">type Pair&lt;T&gt; = ;
<span class="hljs-built_in">type Coordinates = Pair&lt;number&gt;;
<span class="hljs-built_in">type Tree&lt;T&gt; = T | { left: Tree&lt;T&gt;, right: Tree&lt;T&gt; };
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong><code>interface</code>可以而 <code>type</code>不行</strong></span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>interface</code> 能够声明合并</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface User {
name: string
age: number
}

interface User {
sex: string
}

/*
User 接口为 {
name: string
age: number
sex: string
}
*/

<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><code>interface</code> 有可选属性和只读属性</span></p>
<ul>
<li>
<p><span style="font-family: 楷体; font-size: 16px">可选属性</span></p>
<p><span style="font-family: 楷体; font-size: 16px">接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 例如给函数传入的参数对象中只有部分属性赋值了。带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个<code>?</code>符号。如下所示</span></p>
</li>
</ul>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface Person {
name: string;
age?: number;
gender?: number;
}
<span class="copy-code-btn">复制代码</span></code></span></pre>
<ul>
<li>
<p><span style="font-family: 楷体; font-size: 16px">只读属性</span></p>
<p><span style="font-family: 楷体; font-size: 16px">顾名思义就是这个属性是不可写的,对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 <code>readonly</code>来指定只读属性,如下所示:</span></p>
</li>
</ul>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface User {
    <span class="hljs-built_in">readonly loginName: string;
    password: string;
}
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">上面的例子说明,当完成User对象的初始化后loginName就不可以修改了。</span></p>
<h3 class="heading" data-id="heading-20"><span style="font-family: 楷体; font-size: 16px">3.4 实现与继承:<code>implements</code>vs<code>extends</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px"><code>extends</code>很明显就是ES6里面的类继承,那么<code>implement</code>又是做什么的呢?它和<code>extends</code>有什么不同?</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>implement</code>,实现。与C#或Java里接口的基本作用一样,<code>TypeScript</code>也能够用它来明确的强制一个类去符合某种契约</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><strong>implement基本用法</strong>:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">interface IDeveloper {
   name: string;
   age?: number;
}
// OK
class dev implements IDeveloper {
    name = <span class="hljs-string">'Alex';
    age = 20;
}
// OK
class dev2 implements IDeveloper {
    name = <span class="hljs-string">'Alex';
}
// Error
class dev3 implements IDeveloper {
    name = <span class="hljs-string">'Alex';
    age = <span class="hljs-string">'9';
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">而<code>extends</code>是继承父类,两者其实可以混着用:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"> class A extends B implements C,D,E
<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">搭配 <code>interface</code>和<code>type</code>的用法有:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190612003025759" data-src="https://user-gold-cdn.xitu.io/2019/6/12/16b47a58564149b6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1000" data-height="812"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<h3 class="heading" data-id="heading-21"><span style="font-family: 楷体; font-size: 16px">3.5 声明文件与命名空间:<code>declare</code> 和 <code>namespace</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px">前面我们讲到Vue项目中的<code>shims-tsx.d.ts</code>和<code>shims-vue.d.ts</code>,其初始内容是这样的:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// shims-tsx.d.ts
import Vue, { VNode } from <span class="hljs-string">'vue';

<span class="hljs-built_in">declare global {
namespace JSX {
    // tslint:<span class="hljs-built_in">disable no-empty-interface
    interface Element extends VNode {}
    // tslint:<span class="hljs-built_in">disable no-empty-interface
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      : any;
    }
}
}

// shims-vue.d.ts
<span class="hljs-built_in">declare module <span class="hljs-string">'*.vue' {
import Vue from <span class="hljs-string">'vue';
<span class="hljs-built_in">export default Vue;
}

<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><code>declare</code>:当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">这里列举出几个常用的:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">declare var 声明全局变量
<span class="hljs-built_in">declare <span class="hljs-keyword">function 声明全局方法
<span class="hljs-built_in">declare class 声明全局类
<span class="hljs-built_in">declare enum 声明全局枚举类型
<span class="hljs-built_in">declare global 扩展全局变量
<span class="hljs-built_in">declare module 扩展模块
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><code>namespace</code>:“内部模块”现在称做“命名空间”</span></p>
<p><span style="font-family: 楷体; font-size: 16px"><code>module X {</code> 相当于现在推荐的写法 <code>namespace X {</code>)</span></p>
<h2 class="heading" data-id="heading-22"><span style="font-family: 楷体; font-size: 16px">跟其他 JS 库协同</span></h2>
<p><span style="font-family: 楷体; font-size: 16px">类似模块,同样也可以通过为其他 JS 库使用了命名空间的库创建 <code>.d.ts</code> 文件的声明文件,如为 <code>D3</code> JS 库,可以创建这样的声明文件:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">declare namespace D3{
    <span class="hljs-built_in">export interface Selectors { ... }
}
<span class="hljs-built_in">declare var d3: D3.Base;
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">所以上述两个文件:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>shims-tsx.d.ts</code>, 在全局变量 <code>global</code>中批量命名了数个内部模块。</span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>shims-vue.d.ts</code>,意思是告诉 <code>TypeScript</code> <code>*.vue</code> 后缀的文件可以交给 <code>vue</code> 模块来处理。</span></li>
</ul>
<h3 class="heading" data-id="heading-23"><span style="font-family: 楷体; font-size: 16px">3.6 访问修饰符:<code>private</code>、<code>public</code>、<code>protected</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px">其实很好理解:</span></p>
<ol>
<li>
<p><span style="font-family: 楷体; font-size: 16px">默认为<code>public</code></span></p>
</li>
<li>
<p><span style="font-family: 楷体; font-size: 16px">当成员被标记为<code>private</code>时,它就不能在声明它的类的外部访问,比如:</span></p>
</li>
</ol>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">class Animal {
    private name: string;
    constructor(theName: string) {
      this.name = theName;
    }
}

<span class="hljs-built_in">let a = new Animal(<span class="hljs-string">'Cat').name; //错误,‘name’是私有的
<span class="copy-code-btn">复制代码</span></span></span></code></span></pre>
<ol start="3">
<li><span style="font-family: 楷体; font-size: 16px"><code>protected</code>和<code>private</code>类似,但是,<code>protected</code>成员在派生类中可以访问</span></li>
</ol>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">class Animal {
    protected name: string;
    constructor(theName: string) {
      this.name = theName;
    }
}

class Rhino extends Animal {
    <span class="hljs-function"><span class="hljs-title">constructor() {
      super(<span class="hljs-string">'Rhino');
   }         
   <span class="hljs-function"><span class="hljs-title">getName() {
       console.log(this.name) //此处的name就是Animal类中的name
   }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></code></span></pre>
<h3 class="heading" data-id="heading-24"><span style="font-family: 楷体; font-size: 16px">3.7 可选参数 ( ?: )和非空断言操作符(!.)</span></h3>
<p><span style="font-family: 楷体; font-size: 16px"><strong>可选参数</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-keyword">function buildName(firstName: string, lastName?: string) {
    <span class="hljs-built_in">return firstName + <span class="hljs-string">' ' + lastName
}

// 错误演示
buildName(<span class="hljs-string">"firstName", <span class="hljs-string">"lastName", <span class="hljs-string">"lastName")
// 正确演示
buildName(<span class="hljs-string">"firstName")
// 正确演示
buildName(<span class="hljs-string">"firstName", <span class="hljs-string">"lastName")
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>非空断言操作符:</strong></span></p>
<p><span style="font-family: 楷体; font-size: 16px">能确定变量值一定不为空时使用。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">与可选参数 不同的是,非空断言操作符不会防止出现 null 或 undefined。</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">let s = e!.name;// 断言e是非空并访问name属性
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<h2 class="heading" data-id="heading-25"><span style="font-family: 楷体; font-size: 16px">4. <code>Vue</code>组件的<code>Ts</code>写法</span></h2>
<p><span style="font-family: 楷体; font-size: 16px">从 vue2.5 之后,vue 对 ts 有更好的支持。根据官方文档,vue 结合 typescript ,有两种书写方式:</span></p>
<p><span style="font-family: 楷体; font-size: 16px">**Vue.extend **</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import Vue from <span class="hljs-string">'vue'

const Component = Vue.extend({
        // <span class="hljs-built_in">type inference enabled
})
<span class="copy-code-btn">复制代码</span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><strong>vue-class-component</strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import { Component, Vue, Prop } from <span class="hljs-string">'vue-property-decorator'

@Component
<span class="hljs-built_in">export default class Test extends Vue {
@Prop({ <span class="hljs-built_in">type: Object })
private <span class="hljs-built_in">test: { value: string }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">理想情况下,<code>Vue.extend</code> 的书写方式,是学习成本最低的。在现有写法的基础上,几乎 0 成本的迁移。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">但是<code>Vue.extend</code>模式,需要与<code>mixins</code> 结合使用。在 mixin 中定义的方法,不会被 typescript 识别到</span></p>
<p><span style="font-family: 楷体; font-size: 16px">,这就意味着会出现<strong>丢失代码提示、类型检查、编译报错等问题。</strong></span></p>
<p><span style="font-family: 楷体; font-size: 16px">菜鸟才做选择,大佬都挑最好的。直接讲第二种吧:</span></p>
<h3 class="heading" data-id="heading-26"><span style="font-family: 楷体; font-size: 16px">4.1 <code>vue-class-component</code></span></h3>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="image-20190613013846506" data-src="https://user-gold-cdn.xitu.io/2019/6/14/16b53b466001ed96?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="996" data-height="561"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<p><span style="font-family: 楷体; font-size: 16px">我们回到<code>src/components/HelloWorld.vue</code></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">&lt;template&gt;
&lt;div class=<span class="hljs-string">"hello"&gt;
    &lt;h1&gt;{{ msg }}&lt;/h1&gt;
    &lt;!-- 省略 --&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script lang=<span class="hljs-string">"ts"&gt;
import { Component, Prop, Vue } from <span class="hljs-string">'vue-property-decorator';

@Component
<span class="hljs-built_in">export default class HelloWorld extends Vue {
@Prop() private msg!: string;
}
&lt;/script&gt;

&lt;!-- Add <span class="hljs-string">"scoped" attribute to <span class="hljs-built_in">limit CSS to this component only --&gt;
&lt;style scoped&gt;&lt;/style&gt;
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">有写过<code>python</code>的同学应该会发现似曾相识:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>vue-property-decorator</code>这个官方支持的库里,提供了函数 **装饰器(修饰符)**语法</span></li>
</ul>
<h4 class="heading" data-id="heading-27"><span style="font-family: 楷体; font-size: 16px">1. 函数修饰符 <code>@</code></span></h4>
<p><span style="font-family: 楷体; font-size: 16px">“@”,与其说是修饰函数倒不如说是引用、调用它修饰的函数。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">或者用句大白话描述:<code>@</code>: "下面的被我包围了。"</span></p>
<p><span style="font-family: 楷体; font-size: 16px">举个栗子,下面的一段代码,里面两个函数,没有被调用,也会有输出结果:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs html copyable" lang="html">test(f){
    console.log("before ...");
    f()
                console.log("after ...");
}

@test
func(){
        console.log("func was called");
}
<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">直接运行,输出结果:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">before ...
func was called
after ...
<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">上面代码可以看出来:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px">只定义了两个函数:<code>test</code>和<code>func</code>,没有调用它们。</span></li>
<li><span style="font-family: 楷体; font-size: 16px">如果没有“@test”,运行应该是没有任何输出的。</span></li>
</ul>
<p><span style="font-family: 楷体; font-size: 16px">但是,解释器读到函数修饰符“@”的时候,后面步骤会是这样:</span></p>
<ol>
<li>
<p><span style="font-family: 楷体; font-size: 16px">去调用<code>test</code>函数,<code>test</code>函数的入口参数就是那个叫“<code>func</code>”的函数;</span></p>
</li>
<li>
<p><span style="font-family: 楷体; font-size: 16px"><code>test</code>函数被执行,入口参数的(也就是<code>func</code>函数)会被调用(执行);</span></p>
</li>
</ol>
<p><span style="font-family: 楷体; font-size: 16px">换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。有点儿类似<code>JavaScrip</code>t里面的 <code>function a (function () { ... });</code></span></p>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<span style="font-family: 楷体; font-size: 16px"><img class="lazyload inited loaded" alt="狗狗祟祟,鬼鬼祟祟表æƒ
åŒ
,三狗并祟,三个狗穿着小裙子,鬼鬼祟祟表æƒ
åŒ
.jpg" data-src="https://user-gold-cdn.xitu.io/2019/6/13/16b512f30ff5e238?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="198" data-height="198"></span>
<p><span style="font-family: 楷体; font-size: 16px">&nbsp;</span></p>
<h4 class="heading" data-id="heading-28"><span style="font-family: 楷体; font-size: 16px">2. <code>vue-property-decorator</code>和<code>vuex-class</code>提供的装饰器</span></h4>
<p><span style="font-family: 楷体; font-size: 16px"><code>vue-property-decorator</code>的装饰器:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Prop</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@PropSync</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Provide</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Model</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Watch</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Inject</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Provide</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Emit</code></span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>@Component</code> (<strong>provided by</strong> vue-class-component)</span></li>
<li><span style="font-family: 楷体; font-size: 16px"><code>Mixins</code> (the helper function named <code>mixins</code> <strong>provided by</strong> vue-class-component)</span></li>
</ul>
<p><span style="font-family: 楷体; font-size: 16px"><code>vuex-class</code>的装饰器:</span></p>
<ul>
<li><span style="font-family: 楷体; font-size: 16px">@State</span></li>
<li><span style="font-family: 楷体; font-size: 16px">@Getter</span></li>
<li><span style="font-family: 楷体; font-size: 16px">@Action</span></li>
<li><span style="font-family: 楷体; font-size: 16px">@Mutation</span></li>
</ul>
<p><span style="font-family: 楷体; font-size: 16px">我们拿原始Vue组件模版来看:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import {componentA,componentB} from <span class="hljs-string">'@/components';

<span class="hljs-built_in">export default {
        components: { componentA, componentB},
        props: {
    propA: { <span class="hljs-built_in">type: Number },
    propB: { default: <span class="hljs-string">'default value' },
    propC: { <span class="hljs-built_in">type: },
}
// 组件数据
<span class="hljs-function"><span class="hljs-title">data () {
    <span class="hljs-built_in">return {
      message: <span class="hljs-string">'Hello'
    }
},
// 计算属性
computed: {
    <span class="hljs-function"><span class="hljs-title">reversedMessage () {
      <span class="hljs-built_in">return this.message.split(<span class="hljs-string">'').reverse().join(<span class="hljs-string">'')
    }
    // Vuex数据
    <span class="hljs-function"><span class="hljs-title">step() {
            <span class="hljs-built_in">return this.<span class="hljs-variable">$store.state.count
    }
},
methods: {
    <span class="hljs-function"><span class="hljs-title">changeMessage () {
      this.message = <span class="hljs-string">"Good bye"
    },
    <span class="hljs-function"><span class="hljs-title">getName() {
            <span class="hljs-built_in">let name = this.<span class="hljs-variable">$store.getters[<span class="hljs-string">'person/name']
            <span class="hljs-built_in">return name
    }
},
// 生命周期
<span class="hljs-function"><span class="hljs-title">created () { },
<span class="hljs-function"><span class="hljs-title">mounted () { },
<span class="hljs-function"><span class="hljs-title">updated () { },
<span class="hljs-function"><span class="hljs-title">destroyed () { }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">以上模版替换成修饰符写法则是:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import { Component, Vue, Prop } from <span class="hljs-string">'vue-property-decorator';
import { State, Getter } from <span class="hljs-string">'vuex-class';
import { count, name } from <span class="hljs-string">'@/person'
import { componentA, componentB } from <span class="hljs-string">'@/components';

@Component({
    components:{ componentA, componentB},
})
<span class="hljs-built_in">export default class HelloWorld extends Vue{
        @Prop(Number) <span class="hljs-built_in">readonly propA!: number | undefined
    @Prop({ default: <span class="hljs-string">'default value' }) <span class="hljs-built_in">readonly propB!: string
    @Prop() <span class="hljs-built_in">readonly propC!: string | boolean | undefined

// 原data
message = <span class="hljs-string">'Hello'

// 计算属性
        private get reversedMessage (): string[] {
        <span class="hljs-built_in">return this.message.split(<span class="hljs-string">'').reverse().join(<span class="hljs-string">'')
}
// Vuex 数据
@State((state: IRootState) =&gt; state . booking. currentStep) step!: number
        @Getter( <span class="hljs-string">'person/name') name!: name

// method
public changeMessage (): void {
    this.message = <span class="hljs-string">'Good bye'
},
public getName(): string {
    <span class="hljs-built_in">let storeName = name
    <span class="hljs-built_in">return storeName
}
        // 生命周期
private created ():void { },
private mounted ():void { },
private updated ():void { },
private destroyed ():void { }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">正如你所看到的,我们在生命周期 列表那都添加<code>private XXXX</code>方法,因为这不应该公开给其他组件。</span></p>
<p><span style="font-family: 楷体; font-size: 16px">而不对<code>method</code>做私有约束的原因是,可能会用到<code>@Emit</code>来向父组件传递信息。</span></p>
<h3 class="heading" data-id="heading-29"><span style="font-family: 楷体; font-size: 16px">4.2 添加全局工具</span></h3>
<p><span style="font-family: 楷体; font-size: 16px">引入全局模块,需要改<code>main.ts</code>:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import Vue from <span class="hljs-string">'vue';
import App from <span class="hljs-string">'./App.vue';
import router from <span class="hljs-string">'./router';
import store from <span class="hljs-string">'./store';

Vue.config.productionTip = <span class="hljs-literal">false;

new Vue({
router,
store,
render: (h) =&gt; h(App),
}).<span class="hljs-variable">$mount(<span class="hljs-string">'#app');
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><code>npm i VueI18n</code></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import Vue from <span class="hljs-string">'vue';
import App from <span class="hljs-string">'./App.vue';
import router from <span class="hljs-string">'./router';
import store from <span class="hljs-string">'./store';
// 新模块
import i18n from <span class="hljs-string">'./i18n';

Vue.config.productionTip = <span class="hljs-literal">false;

new Vue({
    router,
    store,
    i18n, // 新模块
    render: (h) =&gt; h(App),
}).<span class="hljs-variable">$mount(<span class="hljs-string">'#app');
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">但仅仅这样,还不够。你需要动<code>src/vue-shim.d.ts</code>:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// 声明全局方法
<span class="hljs-built_in">declare module <span class="hljs-string">'vue/types/vue' {
interface Vue {
      <span class="hljs-built_in">readonly <span class="hljs-variable">$i18n: VueI18Next;
      <span class="hljs-variable">$t: TranslationFunction;
    }
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">之后使用<code>this.$i18n()</code>的话就不会报错了。</span></p>
<h3 class="heading" data-id="heading-30"><span style="font-family: 楷体; font-size: 16px">4.3 Axios 使用与封装</span></h3>
<p><span style="font-family: 楷体; font-size: 16px"><code>Axios</code>的封装千人千面</span></p>
<p><span style="font-family: 楷体; font-size: 16px">如果只是想简单在Ts里体验使用<code>Axios</code>,可以安装<code>vue-axios</code> <strong>简单使用<code>Axios</code></strong></span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">$ npm i axios vue-axios
<span class="copy-code-btn">复制代码</span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px"><code>main.ts</code>添加:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import Vue from <span class="hljs-string">'vue'
import axios from <span class="hljs-string">'axios'
import VueAxios from <span class="hljs-string">'vue-axios'

Vue.use(VueAxios, axios)
<span class="copy-code-btn">复制代码</span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">然后在组件内使用:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">Vue.axios.get(api).then((response) =&gt; {
console.log(response.data)
})

this.axios.get(api).then((response) =&gt; {
console.log(response.data)
})

this.<span class="hljs-variable">$http.get(api).then((response) =&gt; {
console.log(response.data)
})
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<h4 class="heading" data-id="heading-31"><span style="font-family: 楷体; font-size: 16px">1. 新建文件<code>request.ts</code></span></h4>
<p><span style="font-family: 楷体; font-size: 16px">文件目录:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">-api
    - main.ts   // 实际调用
-utils
    - request.ts// 接口封装
<span class="copy-code-btn">复制代码</span></code></span></pre>
<h4 class="heading" data-id="heading-32"><span style="font-family: 楷体; font-size: 16px">2. <code>request.ts</code>文件解析</span></h4>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">import * as axios from <span class="hljs-string">'axios';
import store from <span class="hljs-string">'@/store';
// 这里可根据具体使用的UI组件库进行替换
import { Toast } from <span class="hljs-string">'vant';
import { AxiosResponse, AxiosRequestConfig } from <span class="hljs-string">'axios';

/* baseURL 按实际项目来定义 */
const baseURL = process.env.VUE_APP_URL;

/* 创建axios实例 */
const service = axios.default.create({
    baseURL,
    timeout: 0, // 请求超时时间
    maxContentLength: 4000,
});

service.interceptors.request.use((config: AxiosRequestConfig) =&gt; {
    <span class="hljs-built_in">return config;
}, (error: any) =&gt; {
    Promise.reject(error);
});

service.interceptors.response.use(
    (response: AxiosResponse) =&gt; {
      <span class="hljs-keyword">if (response.status !== 200) {
            Toast.fail(<span class="hljs-string">'请求错误!');
      } <span class="hljs-keyword">else {
            <span class="hljs-built_in">return response.data;
      }
    },
    (error: any) =&gt; {
      <span class="hljs-built_in">return Promise.reject(error);
    });
   
<span class="hljs-built_in">export default service;
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">为了方便,我们还需要定义一套固定的 axios 返回的格式,新建<code>ajax.ts</code>:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash"><span class="hljs-built_in">export interface AjaxResponse {
    code: number;
    data: any;
    message: string;
}
<span class="copy-code-btn">复制代码</span></span></code></span></pre>
<h4 class="heading" data-id="heading-33"><span style="font-family: 楷体; font-size: 16px">3. <code>main.ts</code>接口调用:</span></h4>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">// api/main.ts
import request from <span class="hljs-string">'../utils/request';

// get
<span class="hljs-built_in">export <span class="hljs-keyword">function getSomeThings(params:any) {
    <span class="hljs-built_in">return request({
      url: <span class="hljs-string">'/api/getSomethings',
    });
}

// post
<span class="hljs-built_in">export <span class="hljs-keyword">function postSomeThings(params:any) {
    <span class="hljs-built_in">return request({
      url: <span class="hljs-string">'/api/postSomethings',
      methods: <span class="hljs-string">'post',
      data: params
    });
}
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<h2 class="heading" data-id="heading-34"><span style="font-family: 楷体; font-size: 16px">5. 编写一个组件</span></h2>
<p><span style="font-family: 楷体; font-size: 16px">为了减少时间,我们来替换掉<code>src/components/HelloWorld.vue</code>,做一个博客帖子组件:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">&lt;template&gt;
        &lt;div class=<span class="hljs-string">"blogpost"&gt;
                &lt;h2&gt;{{ post.title }}&lt;/h2&gt;
                &lt;p&gt;{{ post.body }}&lt;/p&gt;
                &lt;p class=<span class="hljs-string">"meta"&gt;Written by {{ post.author }} on {{ date }}&lt;/p&gt;
        &lt;/div&gt;
&lt;/template&gt;

&lt;script lang=<span class="hljs-string">"ts"&gt;
import { Component, Prop, Vue } from <span class="hljs-string">'vue-property-decorator';

// 在这里对数据进行类型约束
<span class="hljs-built_in">export interface Post {
        title: string;
        body: string;
        author: string;
        datePosted: Date;
}

@Component
<span class="hljs-built_in">export default class HelloWorld extends Vue {
        @Prop() private post!: Post;

        get <span class="hljs-function"><span class="hljs-title">date() {
                <span class="hljs-built_in">return `<span class="hljs-variable">${this.post.datePosted.getDate()}/<span class="hljs-variable">${this.post.datePosted.getMonth()}/<span class="hljs-variable">${this.post.datePosted.getFullYear()}`;
        }
}
&lt;/script&gt;

&lt;style scoped&gt;
h2 {
text-decoration: underline;
}
p.meta {
font-style: italic;
}
&lt;/style&gt;
<span class="copy-code-btn">复制代码</span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p><span style="font-family: 楷体; font-size: 16px">然后在<code>Home.vue</code>中使用:</span></p>
<pre><span style="font-family: 楷体; font-size: 16px"><code class="hljs bash copyable" lang="bash">&lt;template&gt;
&lt;div class=<span class="hljs-string">"home"&gt;
    &lt;img alt=<span class="hljs-string">"Vue logo" src=<span class="hljs-string">"../assets/logo.png"&gt;
           &lt;HelloWorld v-for=<span class="hljs-string">"blogPost in blogPosts" :post=<span class="hljs-string">"blogPost" :key=<span class="hljs-string">"blogPost.title" /&gt;
&lt;/div&gt;
&lt;/template&gt;

&lt;script lang=<span class="hljs-string">"ts"&gt;
import { Component, Vue } from <span class="hljs-string">'vue-property-decorator';
import HelloWorld, { Post } from <span class="hljs-string">'@/components/HelloWorld.vue'; // @ is an <span class="hljs-built_in">alias to /src

@Component({
components: {
    HelloWorld,
},
})
<span class="hljs-built_in">export default class Home extends Vue {
    private blogPosts: Post[] = [
      {
          title: <span class="hljs-string">'My first blogpost ever!',
          body: <span class="hljs-string">'Lorem ipsum dolor sit amet.',
          author: <span class="hljs-string">'Elke',
          datePosted: new Date(2019, 1, 18),
      },
      {
          title: <span class="hljs-string">'Look I am blogging!',
          body: <span class="hljs-string">'Hurray for me, this is my second post!',
          author: <span class="hljs-string">'Elke',
          datePosted: new Date(2019, 1, 19),
      },
      {
          title: <span class="hljs-string">'Another one?!',
          body: <span class="hljs-string">'Another one!',
          author: <span class="hljs-string">'Elke',
          datePosted: new Date(2019, 1, 20),
      },
      ];
}
&lt;/script&gt;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
</div>
<br><span style="font-family: 楷体; font-size: 16px">作者:前端劝退师</span><br><span style="font-family: 楷体; font-size: 16px">链接:https://juejin.im/post/5d0259f2518825405d15ae62</span><br><span style="font-family: 楷体; font-size: 16px">来源:掘金</span><br><span style="font-family: 楷体; font-size: 16px">著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。</span></div><br><br>
来源:https://www.cnblogs.com/objectjj/p/11092240.html
頁: [1]
查看完整版本: typescript