工资蹭蹭张女士 發表於 2020-11-25 17:36:00

Angular(1)

<h1 id="一补充">一、补充</h1>
<h2 id="1-引入第三方库bootstrap为例">1. 引入第三方库(bootstrap为例)</h2>
<h3 id="a-mdn-引入">a. MDN 引入</h3>
<ul>
<li>在index.html中直接引入mdn</li>
</ul>
<pre><code class="language-html">&lt;link rel="stylesheet" href="..." integrity="..." crossorigin="anonymous"&gt;
&lt;script src="..." integrity="..." crossorigin="anonymous"&gt;&lt;/script&gt;

&lt;script src="..." integrity="..." crossorigin="anonymous"&gt;&lt;/script&gt;
&lt;script src="..." integrity="..." crossorigin="anonymous"&gt;&lt;/script&gt;
</code></pre>
<ul>
<li>先下载,然后在package.json中引入,重启后生效</li>
</ul>
<pre><code class="language-js">"styles":[
        "src/assets/styles/bootstrap@4.min.css"
        "src/styles.scss"
]
"scripts":[
        "..."
]
</code></pre>
<ul>
<li>先下载,在styles.scss中引入css,在main.ts中引入js</li>
</ul>
<pre><code class="language-js">@import "./assets/styles/bootstrap@4.min.css";
</code></pre>
<h3 id="b-npm-引入">b. npm 引入</h3>
<p>npm安装</p>
<pre><code class="language-js">npm install bootstrap
</code></pre>
<p>styles.scss引入</p>
<pre><code class="language-jsx">@import "~bootstrap";
</code></pre>
<p>main.ts引入js(依赖jQuery和popper.js)</p>
<pre><code class="language-jsx">import 'bootstrap'
</code></pre>
<p>安装jQuery和popper.js</p>
<pre><code class="language-js">npm i jquery popper.js
</code></pre>
<h2 id="2-npm换源">2. npm换源</h2>
<p>由于node下载第三方依赖包是从国外服务器下载,虽然没有被墙,但是下载的速度是非常的缓慢且有可能会出现异常。所以为了提高效率,我们还是把npm的镜像源替换成淘宝的镜像源。有几种方式供我们选择。</p>
<h3 id="21-使用cnpm">2.1 使用cnpm</h3>
<p>使用阿里定制的cnpm命令行工具代替默认的npm,输入以下代码</p>
<pre><code class="language-npm">npm install -g cnpm --registry=https://registry.npm.taobao.org
</code></pre>
<p>检测是否安装成功</p>
<pre><code>cnpm -v
</code></pre>
<ul>
<li>
<p>安装成功之后,以后安装依赖包的方式和npm的是一样的,只是npm的命令换成是cnpm就可以了</p>
</li>
<li>
<p>假如你已经习惯了使用npm的安装方式的,不想去下载阿里的cnpm命令工具的话,很简单,我们直接将node的仓库地址换成淘宝仓库地址即可</p>
</li>
</ul>
<h3 id="22-换源单次使用">2.2 换源(单次使用)</h3>
<pre><code>npm install --registry=https://registry.npm.taobao.org
</code></pre>
<h3 id="23-永久使用">2.3 永久使用</h3>
<p>在开发react-native的时候,不要使用cnpm!cnpm安装的模块路径比较奇怪,packager不能正常识别。所以,为了方便开发,我们最好是直接永久使用淘宝的镜像源</p>
<ul>
<li>直接命令行的设置</li>
</ul>
<pre><code>npm config set registry https://registry.npm.taobao.org
</code></pre>
<ul>
<li>手动修改设置</li>
</ul>
<pre><code>1.打开.npmrc文件(C:\Program Files\nodejs\node_modules\npm\npmrc,没有的话可以使用git命令行建一个( touch .npmrc),用cmd命令建会报错)
2.增加 registry =https://registry.npm.taobao.org即可。
</code></pre>
<ul>
<li>检测是否修改成功</li>
</ul>
<pre><code>// 配置后可通过下面方式来验证是否成功
npm config get registry
// 或
npm info express
</code></pre>
<p>注:如果想还原npm仓库地址的话,只需要在把地址配置成npm镜像就可以了</p>
<pre><code>npm config set registry https://registry.npmjs.org/
</code></pre>
<h2 id="3-npm设置代理proxy">3. npm设置代理(proxy)</h2>
<p>https://blog.csdn.net/yanzi1225627/article/details/80247758</p>
<h3 id="31-设置代理">3.1 设置代理</h3>
<pre><code>npm config set proxy=http://10.46.148.28:8080
npm config set registry=http://registry.npmjs.org
</code></pre>
<h3 id="32-关于https">3.2 关于https</h3>
<p>经过上面设置使用了http开头的源,因此不需要设https_proxy了,否则还要增加一句:</p>
<pre><code>npm config set https-proxy http://10.46.148.28:8080
</code></pre>
<h3 id="33-代理用户名和密码">3.3 代理用户名和密码</h3>
<pre><code>npm config set proxy http://S2020011:Happy-765432@10.46.148.28:8080
npm confit set https-proxy http://S2020011:Happy-765432@10.46.148.28:8080
</code></pre>
<h3 id="34-取消代理">3.4 取消代理</h3>
<pre><code class="language-js">npm config delete proxy
npm config delete https-proxy
</code></pre>
<h1 id="二-显示数据">二、 显示数据</h1>
<h2 id="1-使用插值显示组件属性">1. 使用插值显示组件属性'{{...}}'</h2>
<pre><code class="language-typescript">import { Component } from '@angular/core';

@Component({
selector: 'app-root',
template: `
    &lt;h1&gt;{{title}}&lt;/h1&gt;
    &lt;h2&gt;My favorite hero is: {{myHero}}&lt;/h2&gt;
    `
})
export class AppComponent {
title = 'Tour of Heroes';
myHero = 'Windstorm';
}
</code></pre>
<h2 id="2-初始化变量">2. 初始化变量</h2>
<pre><code class="language-ts">export class AppComponent {
title: string;
myHero: string;

constructor() {
    this.title = 'Tour of Heroes';
    this.myHero = 'Windstorm';
}
}
</code></pre>
<h2 id="3-模板来源">3. 模板来源</h2>
<blockquote>
<p>ng的模版和样式可以是内联(上述示例),也可以是单独的文件</p>
</blockquote>
<pre><code class="language-js">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;h1&gt;{{title}}&lt;/h1&gt;
    &lt;h2&gt;My favorite hero is: {{myHero}}&lt;/h2&gt;
    `,
styles: [
      `h1 { color: red }`
]
})
export class AppComponent {
title = 'Tour of Heroes';
myHero = 'Windstorm';
}
</code></pre>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Tour of Heroes';
myHero = 'Windstorm';
}
</code></pre>
<h1 id="三模板语法">三、模板语法</h1>
<h2 id="1-模板中的-html">1. 模板中的 HTML</h2>
<p><strong>大部分html标签都能在模版中使用,但有一些是毫无意义的:</strong>html body script base</p>
<h2 id="2-插值--和模板表达式">2. 插值 {{...}} 和模板表达式</h2>
<ul>
<li>插值{</li>
</ul>
<pre><code>&lt;h3&gt;Current customer: {{ currentCustomer }}&lt;/h3&gt;
</code></pre>
<ul>
<li>模板表达式</li>
</ul>
<pre><code class="language-ts">&lt;!-- "The sum of 1 + 1 is not 4" --&gt;
&lt;p&gt;The sum of 1 + 1 is not {{1 + 1 + getVal()}}.&lt;/p&gt;
&lt;p&gt;{{1+1}}&lt;/p&gt;
</code></pre>
<h3 id="a-绑定变量">a. 绑定变量</h3>
<pre><code class="language-js">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;h1&gt;{{title}}&lt;/h1&gt;
    &lt;h2&gt;My favorite hero is: {{myHero}}&lt;/h2&gt;
    `,
styles: [`h1 { color: red }`]
})
export class AppComponent {
title = 'Tour of Heroes';
myHero = 'Windstorm';
}
</code></pre>
<h4 id="b-绑定方法">b. 绑定方法</h4>
<p><strong>模版中除了绑定变量,还能绑定方法</strong></p>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;div&gt;Value: {{ getVal() }}/div&gt;
`,
})
export class AppComponent {
getVal(): number {
    return 33;
}
}
</code></pre>
<h4 id="c-模板表达式">c. 模板表达式</h4>
<p><strong>模版中还可以写些简单的逻辑,比如判断或运算</strong></p>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;p&gt;The sum of 1 + 1 is {{1 + 1}}.&lt;/p&gt;
      &lt;p&gt;price的7折 {{price * 0.7}}.&lt;/p&gt;
      &lt;p&gt;与方法结合 {{price * 0.7 + getVal()}}.&lt;/p&gt;
`,
})
export class AppComponent {
price = 30
getVal(): number {
    return 33;
}
}
</code></pre>
<p><strong>当使用模板表达式时,请遵循下列指南:</strong></p>
<ul>
<li>
<p>非常简单</p>
</li>
<li>
<p>执行迅速</p>
</li>
<li>
<p>没有可见的副作用(即模版中的逻辑不能改变组件的变量)</p>
</li>
</ul>
<h2 id="3-绑定语法">3. 绑定语法</h2>
<h3 id="31-绑定属性">3.1. 绑定属性</h3>
<ul>
<li>绑定图片</li>
</ul>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;img src="../assets/images/madao.jpg" alt="madao" /&gt;
    &lt;img ="madaoSrc" alt="madao" /&gt;
    &lt;img bind-src="madaoSrc" alt="madao" /&gt;
    `,
styles: []
})
export class AppComponent {
madaoSrc = '../assets/images/madao.jpg';
}
</code></pre>
<ul>
<li>绑定普通属性</li>
</ul>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;img ="user.pic" ="user.name" /&gt;
    &lt;table class="table-bordered"&gt;
      &lt;tr&gt;
      &lt;th&gt;name&lt;/th&gt;
      &lt;th&gt;phone&lt;/th&gt;
      &lt;th&gt;age&lt;/th&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
      &lt;td&gt;张三&lt;/td&gt;
      &lt;td&gt;13398490594&lt;/td&gt;
      &lt;td&gt;33&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
      &lt;td ="colSpan"&gt;李四&lt;/td&gt;
      &lt;td&gt;15079049984&lt;/td&gt;
      &lt;td&gt;22&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
    &lt;button class="btn btn-primary" ="isDisabled"&gt;click&lt;/button&gt;
    `,
styles: []
})
export class AppComponent {
madaoSrc = '../assets/images/madao.jpg';
user = {
   name: 'madao',
   pic: this.madaoSrc
};
colSpan = 2;
isDisabled = false;
}
</code></pre>
<ul>
<li>绑定自定义属性</li>
</ul>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;span ="customTitle"&gt;一行文字&lt;/span&gt;
    &lt;span ="customTitle"&gt;test title&lt;/span&gt;
    &lt;span ="customTitle"&gt;test title&lt;/span&gt;
    `,
styles: []
})
export class AppComponent {
madaoSrc = '../assets/images/madao.jpg';
customTitle = 'bbb';
}
</code></pre>
<ul>
<li>使用插值表达式绑定属性</li>
</ul>
<blockquote>
<p>插值也可以用于属性,但常规做法还是用中括号[],建议整个项目保持风格统一</p>
</blockquote>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
    &lt;img src="{{ user.pic }}" alt="{{ user.name }}" /&gt;
    `,
styles: []
})
export class AppComponent {
madaoSrc = '../assets/images/madao.jpg';
user = {
    name: 'madao',
    pic: this.madaoSrc
};
}


&lt;img ="' madao'" ="user"/&gt;等价于
&lt;img src="madao" ="'user' + user2.pic" /&gt;
</code></pre>
<h3 id="32-绑定样式classstyle">3.2. 绑定样式class,style</h3>
<h5 id="绑定单个class">绑定单个class</h5>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;button type="button" class="btn" ="theme === 'primary'"&gt;Primary&lt;/button&gt;
      &lt;button type="button" class="btn" ="true"&gt;secondary&lt;/button&gt;
      &lt;button type="button" class="btn" ="isSuccess"&gt;success&lt;/button&gt;
      &lt;button type="button" class="btn" ="'啦啦啦'"&gt;danger&lt;/button&gt;
      &lt;button type="button" class="btn" ="0"&gt;danger&lt;/button&gt;
      &lt;button type="button" class="btn" ="undefined"&gt;danger&lt;/button&gt;
    `,
styles: []
})
export class AppComponent {
    theme = 'primary';
    isSuccess = true;
}
</code></pre>
<h5 id="绑定多个class">绑定多个class</h5>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;button type="button" ="btnCls"&gt;btnCls&lt;/button&gt;
      &lt;button type="button" ="btnCls2"&gt;btnCls2&lt;/button&gt;
      &lt;button type="button" ="btnCls3"&gt;btnCls3&lt;/button&gt;

      &lt;!-- 也可以用内置指令ngClass --&gt;
      &lt;button type="button" ="btnCls"&gt;btnCls&lt;/button&gt;
      &lt;button type="button" ="btnCls2"&gt;btnCls2&lt;/button&gt;
      &lt;button type="button" ="btnCls3"&gt;btnCls3&lt;/button&gt;
    `,
styles: []
})
export class AppComponent {
    btnCls = 'btn btn-primary';
    btnCls2 = ['btn', 'btn-success'];
    btnCls3 = {
      btn: true,
      'btn-info': true
    };
}
</code></pre>
<h5 id="绑定单个style">绑定单个style</h5>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;p ="'#f60'"&gt;一段文字&lt;/p&gt;
      &lt;p ="'50px'" ="'1px solid'"&gt;设置高度&lt;/p&gt;
      &lt;p ="50" ="'1px solid'"&gt;设置高度&lt;/p&gt;
    `,
styles: []
})
export class AppComponent {}
</code></pre>
<h5 id="绑定多个style">绑定多个style</h5>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;p ="style1"&gt;style1&lt;/p&gt;
      &lt;p ="style2"&gt;style2&lt;/p&gt;
      &lt;p ="style3"&gt;style3&lt;/p&gt;
      &lt;!-- 也可以用内置指令ngStyle, 但不推荐,以后可能会弃用 --&gt;
      &lt;!--&lt;p ="style1"&gt;style1&lt;/p&gt;--&gt;
      &lt;!--&lt;p ="style2"&gt;style2&lt;/p&gt;--&gt;

      &lt;!-- ngStyle只接收对象 --&gt;
      &lt;p ="style3"&gt;style3&lt;/p&gt;
    `,
styles: []
})
export class AppComponent {
style1 = 'width: 200px;height: 50px;text-align: center;border: 1px solid;';
style2 = ['width', '200px', 'height', '50px', 'text-align', 'center', 'border', '1px solid']; // 有问题
style3 = {
    width: '200px',
    height: '50px',
    'text-align': 'center',
    border: '1px solid'
};
}
</code></pre>
<p>样式优先级</p>
<ul>
<li>某个类或样式绑定越具体,它的优先级就越高</li>
<li>绑定总是优先于静态属性</li>
</ul>
<h3 id="33-绑定事件">3.3. 绑定事件</h3>
<h5 id="基本用法">基本用法</h5>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;button type="button" class="btn btn-primary" (click)="onClick()"&gt;Primary&lt;/button&gt;
    `,
styles: []
})
export class AppComponent {
    onClick() {
      console.log('onClick');
    }
}
</code></pre>
<h5 id="事件对象">事件对象</h5>
<blockquote>
<p>$event就是原生的事件对象</p>
</blockquote>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
      &lt;button type="button" class="btn btn-primary" (click)="onClick($event)"&gt;Primary&lt;/button&gt;
    `,
styles: []
})
export class AppComponent {
    onClick(event: MouseEvent) {
      console.log('onClick', event.target);
    }
}
</code></pre>
<ul>
<li>阻止事件冒泡</li>
</ul>
<pre><code class="language-ts">&lt;div (click)="clickParent($event)" class="wrap" style="width: 200px;background-color: #0c5460;"&gt;
&lt;div (click) = "clickChild($event)" class="child" style="width: 100px;height: 200px;background-color: #ff8f77;"&gt;&lt;/div&gt;
&lt;!-- &lt;div (click) = "clickChild($event.stopPropagation())" class="child" style="width: 100px;height: 200px;background-color: #ff8f77;"&gt;&lt;/div&gt; --&gt;
&lt;/div&gt;
</code></pre>
<pre><code class="language-ts">clickParent(event: MouseEvent){
event.stopPropsgation();
console.log("parent")
}

clickChild(event: MouseEvent){
event.stopPropsgation();
console.log("child")
}
</code></pre>
<ul>
<li>不是所有元素 event.target都有value</li>
</ul>
<pre><code class="language-ts">&lt;input type="text" (keyup)="onKeyup($event)"&gt;
</code></pre>
<pre><code class="language-ts">onKeyup(event:KeyboardEvent){
    console.log("onInput:",(event.target as HTMLInputElement).value);
}

&lt;!-- onInput(event:keyboardEvent) {
console.log('onInput',event.target.value);
} --&gt;
</code></pre>
<h2 id="4-input和output">4. @Input和@Output</h2>
<h3 id="41-input输入属性">4.1 @Input输入属性</h3>
<p>子组件中:</p>
<pre><code class="language-ts">import { Component, Input } from '@angular/core';
@Component({
selector: 'app-root',
template: `&lt;p&gt;
               Today's item: {{item}}
             &lt;/p&gt;`
})
export class ItemDetailComponent{
@Input() item: string; // decorate the property with @Input()
}
</code></pre>
<p>父组件中:</p>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;app-item-detail ="currentItem"&gt;&lt;/app-item-detail&gt;
`,
})
export class AppComponent {
currentItem = 'Television';
}
</code></pre>
<h3 id="42-output输出属性">4.2 @Output输出属性</h3>
<p>子组件中:</p>
<pre><code class="language-ts">import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-root',
template: `
           &lt;label&gt;Add an item: &lt;input #newItem&gt;&lt;/label&gt;
       &lt;button (click)="addNewItem(newItem.value)"&gt;Add to parent's list&lt;/button&gt;
`,
})
export class ItemOutputComponent {
@Output() newItemEvent = new EventEmitter&lt;string&gt;();
addNewItem(value: string) {
    this.newItemEvent.emit(value);
}
}
</code></pre>
<p>父组件中:</p>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;app-item-output (newItemEvent)="addItem($event)"&gt;&lt;/app-item-output&gt;
`,
})
export class AppComponent {
    items = ['item1', 'item2', 'item3', 'item4'];
    addItem(newItem: string) {
      this.items.push(newItem);
    }
}
</code></pre>
<h3 id="43-bootstart模态框组件">4.3 bootstart模态框组件</h3>
<p>app.components.html</p>
<pre><code class="language-ts">&lt;!-- Button trigger modal --&gt;
&lt;button type="button" class="btn-primary" (click)="showModal=true"&gt;
Launch demo modal
&lt;/button&gt;

&lt;app-dialog
="showModal"
="'标题'"
(confirm)="onConfirm()"
(close)="onClose()"
(backdropClick)="onClose()"&gt;
&lt;/app-dialog&gt;
</code></pre>
<p>app.components.ts</p>
<pre><code class="language-ts">import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'hero';
showModal = false;
onConfirm() {
    console.log('接收 onConfirm');
}
onClose() {
    this.showModal = false;
}
}
</code></pre>
<p>dialog.components.html</p>
<pre><code class="language-ts">&lt;!-- Modal --&gt;
&lt;div class="modal fade show black-back" (click)="backdropClick.emit()" ="show"id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"&gt;
    &lt;div class="modal-dialog modal-dialog-centered" (click)="$event.stopPropagation()"&gt;
      &lt;div class="modal-content"&gt;
      &lt;div class="modal-header"&gt;
          &lt;h5 class="modal-title" id="exampleModalLabel"&gt;{{title}}&lt;/h5&gt;
          &lt;button type="button" (click)="onClose()" class="close" data-dismiss="modal" aria-label="Close"&gt;
            &lt;span aria-hidden="true" &gt;&amp;times;&lt;/span&gt;
          &lt;/button&gt;
      &lt;/div&gt;
      &lt;div class="modal-body"&gt;
          ...
      &lt;/div&gt;
      &lt;div class="modal-footer"&gt;
          &lt;button type="button"
                  (click)="onClose()"
                  class="btn btn-secondary"
                  data-dismiss="modal"&gt;
            {{cancelLabel}}
         &lt;/button&gt;
          &lt;button type="button" class="btn btn-primary" (click)=onConfirm()&gt;{{confirmLable}}&lt;/button&gt;
      &lt;/div&gt;
      &lt;/div&gt;ts
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>dialog.componen.ts</p>
<pre><code class="language-ts">import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';

@Component({
selector: 'app-dialog',
templateUrl: './dialog.component.html',
styleUrls: ['./dialog.component.scss']
})
export class DialogComponent implements OnInit {
@Input() show = false;
@Input() title = '';
@Input() confirmLable = "确定";
@Input() cancelLabel = "取消";

@Output() close = new EventEmitter&lt;void&gt;();
@Output() backdropClick = new EventEmitter&lt;void&gt;();
@Output() confirm = new EventEmitter&lt;void&gt;();

constructor() { }

ngOnInit(): void {
}

onClose(){
    // this.show = false;
    this.close.emit()
    console.log("发射成功1");
}

onConfirm(){
    // this.show = false;
    this.confirm.emit()
    console.log("发射成功2");
}

// backdropClick(){
//   console.log("遮罩")
// }
}
</code></pre>
<h3 id="在元数据中声明输入和输出属性">在元数据中声明输入和输出属性</h3>
<blockquote>
<p>固然可以在 @Directive 和 @Component 元数据中声明 inputs 和 outputs,但不推荐示例请看视频演示</p>
</blockquote>
<h3 id="提供别名">提供别名</h3>
<blockquote>
<p>@Input()和@Output()可以接收一个参数,作为变量的别名,那么父组件中只能用别名绑定</p>
</blockquote>
<p>子组件中:</p>
<pre><code class="language-ts">import { Component, Input, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-root',
template: `&lt;p&gt;
               Today's item: {{item}}
             &lt;/p&gt;`
})
export class ItemDetailComponent{
@Input('aliasItem') item: string; // decorate the property with @Input()
@Output('newItem') newItemEvent = new EventEmitter&lt;string&gt;();
addNewItem(value: string) {
   this.newItemEvent.emit(value);
   }
}
</code></pre>
<p>父组件中:</p>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;app-item-detail ="currentItem" (newItem)="addItem($event)"&gt;&lt;/app-item-detail&gt;
`,
})
export class AppComponent {
currentItem = 'Television';
items = ['item1', 'item2', 'item3', 'item4'];
addItem(newItem: string) {
    this.items.push(newItem);
}
}
</code></pre>
<h3 id="输入属性一定要用中括号绑定">输入属性一定要用中括号[]绑定?</h3>
<blockquote>
<p>如果绑定的值是静态的,就不需要[]</p>
</blockquote>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;app-item-detail item="static item"&gt;&lt;/app-item-detail&gt;
`,
})
export class AppComponent {
// currentItem = 'Television';
}
</code></pre>
<h2 id="5基本双向绑定">5.基本双向绑定</h2>
<p>sizer.components.html</p>
<pre><code class="language-html">&lt;div&gt;
    &lt;button class="btn btn-danger" (click)="dec()" title="smaller"&gt;-&lt;/button&gt;
    &lt;button class="btn btn-primary" (click)="inc()" title="bigger"&gt;+&lt;/button&gt;
    &lt;label ="size"&gt;FontSize: {{size}}px&lt;/label&gt;
&lt;/div&gt;
</code></pre>
<p>sizer.components.ts</p>
<pre><code class="language-ts">import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';

@Component({
selector: 'app-sizer',
templateUrl: './sizer.component.html',
styleUrls: ['./sizer.component.scss']
})
export class SizerComponent implements OnInit {
@Input() size = 16;
@Output() sizeChange = new EventEmitter&lt;Number&gt;()
constructor() { }
ngOnInit(): void {}

dec() {
    // this.size-- ;
    this.sizeChange.emit(this.size - 1);
}
inc() {
    // this.size++;
    this.sizeChange.emit(this.size + 1);
}

}
</code></pre>
<p>app.components.html</p>
<pre><code class="language-html">&lt;app-sizer = "size" (change)="size = $event"&gt;&lt;/app-sizer&gt;
&lt;app-sizer [(size)] = "size"&gt;&lt;/app-sizer&gt;
&lt;p&gt;&lt;label ="size"&gt;FontSize: {{size}}px&lt;/label&gt;&lt;/p&gt;
</code></pre>
<p>app.components.ts</p>
<pre><code class="language-ts">import { Component } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
size = 16;

title = 'ngone';
con = "OK";
}
</code></pre>
<h2 id="6-表单双向绑定">6. 表单双向绑定</h2>
<h3 id="基本使用">基本使用</h3>
<blockquote>
<p>根据之前基本的双向绑定知识,[(ngModel)]语法可拆解为:</p>
</blockquote>
<ol>
<li>名为ngModel的输入属性</li>
<li>名为ngModelChange的输出属性</li>
</ol>
<pre><code class="language-ts">import {Component} from '@angular/core';

@Component({
selector: 'example-app',
template: `
    &lt;input [(ngModel)]="name" #ctrl="ngModel" required&gt;

    &lt;p&gt;Value: {{ name }}&lt;/p&gt;
    &lt;p&gt;Valid: {{ ctrl.valid }}&lt;/p&gt;

    &lt;button (click)="setValue()"&gt;Set value&lt;/button&gt;
`,
})
export class SimpleNgModelComp {
name: string = '';

setValue() {
    this.name = 'Nancy';
}
}
</code></pre>
<p><code>&lt;input [(ngModel)]="name" /&gt; </code></p>
<p>上面这行代码相当于:</p>
<p><code>&lt;input ="name" (input)="name = $event.target.value" /&gt;</code></p>
<h3 id="在表单中使用">在表单中使用</h3>
<blockquote>
<p>表单中使用[(ngModel)],需要做下面两件事的其中之一:</p>
</blockquote>
<ul>
<li>给控件加上name属性</li>
<li>将ngModelOptions.standalone设为true</li>
</ul>
<pre><code class="language-js">&lt;form&gt;
    &lt;input [(ngModel)]="value" name="name" /&gt;//第一种,更推荐
    &lt;input [(ngModel)]="value" ="{ standalone: true }" /&gt; //第二种
    &lt;input [(ngModel)]="value" ="{name: 'name' }" /&gt; //第二种   
&lt;/form&gt;
</code></pre>
<h2 id="7-模板引用变量">7. 模板引用变量</h2>
<h3 id="基本使用-1">基本使用</h3>
<blockquote>
<p>使用井号(#)声明模板引用变量,可以获取DOM 元素、指令、组件、TemplateRef 或 Web Component。</p>
</blockquote>
<p>之前用到的ng-template上的 # ,就是模板引用变量,并在组件中获取到了对应的TemplateRef</p>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;input #phone placeholder="phone number" /&gt;
    &lt;button (click)="callPhone(phone.value)"&gt;Call&lt;/button&gt;
`,
})
export class TplVarComponent {
constructor() { }
callPhone(value: string) {
    console.log('callPhone', value);
}
}
</code></pre>
<h3 id="ref">ref</h3>
<blockquote>
<p>还有种写法就是ref, 下面两种写法是一样的</p>
</blockquote>
<pre><code class="language-html">&lt;input #fax placeholder="fax number" /&gt;
&lt;br /&gt;
&lt;input ref-fax placeholder="fax number" /&gt;
</code></pre>
<h3 id="引用组件">引用组件</h3>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;div class="demo-sec"&gt;
      &lt;button class="btn btn-primary" (click)="sizer.inc()"&gt;app inc&lt;/button&gt;
      &lt;app-sizer [(size)]="size" #sizer&gt;&lt;/app-sizer&gt;
      size: {{ size }}
    &lt;/div&gt;
`,
})
export class TplVarComponent {
size = 16;
constructor() { }
}
</code></pre>
<h2 id="8-模板运算符">8. 模板运算符</h2>
<h3 id="管道--">管道( | )</h3>
<blockquote>
<p>管道可以理解为把模板上的值丢进一条或多条管道,经过管道的处理输出一条新的值</p>
</blockquote>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;p&gt;Title through uppercase pipe: {{title | uppercase}}&lt;/p&gt;
    &lt;p&gt;Title through uppercase pipe: {{title | uppercase | lowercase}}&lt;/p&gt;
    &lt;p&gt;json: {{ obj | json }}&lt;/p&gt;
`,
})
export class TplOperatorsComponent {
title = 'aBc';
obj = {
      name: 'aaa',
      time: '1980-02-25T05:00:00.000Z',
      price: '$333'
    };
constructor() {}
}
</code></pre>
<h4 id="带参数的管道">带参数的管道</h4>
<p><strong>如内置的date管道</strong></p>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;p&gt;Manufacture date with date format pipe: {{now | date:'longDate'}}&lt;/p&gt;
    &lt;p&gt;Manufacture date with date format pipe: {{now | date:'yyyy-MM-dd'}}&lt;/p&gt;
`,
})
export class TplOperatorsComponent {
now = Date.now();
constructor() {}
}
</code></pre>
<h4 id="所有内置管道">所有内置管道</h4>
<h3 id="可选链">可选链(?)</h3>
<blockquote>
<p>安全导航运算符是 es2020 中的新语法,又叫可选链</p>
</blockquote>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;!--&lt;p *ngIf="hero"&gt;hero: {{ hero.name }}&lt;/p&gt;--&gt;
    &lt;p&gt;hero: {{ hero?.name }}&lt;/p&gt;
`,
})
export class TplOperatorsComponent {
   hero: Hero;
    constructor() {
      setTimeout(() =&gt; {
      this.hero = {
          id: 'hero_00',
          name: '龙龟'
      };
      }, 2000);
    }
}
</code></pre>
<p>空属性路径</p>
<h3 id="非空断言">非空断言(!)</h3>
<blockquote>
<p>在ts中,开启--strictNullChecks后,将一个可能是undefined或null的变量赋给一个有确切类型的变量时,会报错</p>
</blockquote>
<p>但在特定情况下,我们很确定那个变量一定不是undefined或null,这个时候就可以用非空断言操作符<br>
用了这个操作符的变量,可以理解为叫ts不要去操心了,我这个变量一定是有值的 非空断言生效的前提是开启 --strictNullChecks</p>
<p><strong>使用非空断言的两个步骤:</strong></p>
<ul>
<li>tsconfig.json中设置"strictNullChecks": true,</li>
<li>tslint.json中设置 "no-non-null-assertion": false</li>
</ul>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-tpl-var',
template: `
    &lt;input #phone placeholder="phone number" /&gt;
    &lt;button (click)="callPhone(phone.value)"&gt;Call&lt;/button&gt;
`,
})
export class TplOperatorsComponent {
name: string | null = '';
constructor() {
    // 报错,this.name可能为null, 不能赋给heroName
    const heroName: string = this.name;

    // 不报错,告诉ts,this.name一定不是null
    const heroName: string = this.name!;

    // 以上写法相当于
    if (this.name) {
      const heroName: string = this.name;
    }
}
}
</code></pre>
<h3 id="类型转换函数-any">类型转换函数 $any()</h3>
<p>有时候,绑定的表达式不能或很难指定类型。要消除这种报错,你可以使用 $any() 转换函数来把表达式转换成 any 类型<br>
假设无法确定item的类型,也就不能确定item是否有bestByDate,这时就会报错,可以用$any()把item视为any类型,避免其报错</p>
<pre><code class="language-html">&lt;p&gt;The item's undeclared best by date is: {{$any(item).bestByDate}}&lt;/p&gt;
</code></pre>
<p>也可以用这个函数绑定组件中不存在的变量</p>
<pre><code class="language-html">&lt;p&gt;The item's undeclared best by date is: {{$any(this).bestByDate}}&lt;/p&gt;
</code></pre>
<h1 id="四属性型指令">四、属性型指令</h1>
<pre><code class="language-js">ng generate directive highlight
</code></pre>
<h2 id="组件是一种特殊的指令">组件是一种特殊的指令</h2>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: '',
//selector: 'app-for',
template: `
    &lt;!--&lt;app-for&gt;&lt;/app-for&gt;--&gt;
    &lt;div app-for&gt;dasfsada&lt;/div&gt;
`,
})
export class AppComponent {
constructor() {}
}
</code></pre>
<h2 id="example">example</h2>
<p>app.component.html</p>
<pre><code class="language-html">&lt;p appHighlight&gt;Highlight me!&lt;/p&gt;
&lt;p appHighlight ="orange"&gt;Highlight me!&lt;/p&gt;
&lt;p appHighlight highlightColor="color"&gt;Highlight me!&lt;/p&gt;
&lt;p appHighlight = "blue"&gt;Highlight me!&lt;/p&gt;
</code></pre>
<p>highlight.directive.ts</p>
<pre><code class="language-ts">import {Directive, ElementRef, EventEmitter, HostListener, Input, Output} from '@angular/core';

@Directive({
selector: ''
})
export class HighlightDirective {
@Input('appHighlight') highlightColor: string;
@Output() colorChange = new EventEmitter&lt;string&gt;();
   
constructor(private el: ElementRef) {
    console.log('appHighlight');
    this.el.nativeElement.style.backgroundColor = color;
}
    //监听宿主p
@HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'yellow');
}
// @HostListener('mouseenter',['$event']) onMouseEnter(event) {
// console.log('event',event)
//   this.highlight(this.highlightColor || 'yellow');
// }
@HostListener('mouseleave') onMouseLeave() {
    this.highlight('');
}

private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
    this.colorChange.emit(color);
}
}
</code></pre>
<h1 id="五结构型指令">五、结构型指令</h1>
<h2 id="1-ngif">1. *ngIf</h2>
<h4 id="基本使用-2">基本使用</h4>
<blockquote>
<p>ngIf是内置的结构型指令,控制宿主元素的添加或删除,取决于绑定的值是否为真</p>
</blockquote>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-if',
template: `
    &lt;div *ngIf="condition"&gt;Content to render when condition is true.&lt;/div&gt;
`,
})
export class IfComp {
condition = true;
}
</code></pre>
<h4 id="扩展写法">扩展写法</h4>
<blockquote>
<p>*ngIf是个语法糖,上个例子完整的写法如下</p>
</blockquote>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-if',
template: `
    &lt;ng-template ="condition"&gt;
      &lt;div&gt;Content to render when condition is true.&lt;/div&gt;
    &lt;/ng-template&gt;
`,
})
export class IfComp {
condition = true;
}
</code></pre>
<ul>
<li>ng-template是一块内嵌模板,类型是TemplateRef</li>
</ul>
<h3 id="使用templateref">使用TemplateRef</h3>
<blockquote>
<p>上面示例中的else 或 then 后面跟的变量都是模板的引用而非组件中的变量,下面演示怎么用组件中的变量</p>
</blockquote>
<pre><code class="language-ts">import {Component, OnInit, ChangeDetectionStrategy, ViewChild, TemplateRef, AfterViewInit} from '@angular/core';
@Component({
selector: 'app-if',
template: `
    &lt;button class="btn btn-primary" (click)="condition = !condition"&gt;toggle block&lt;/button&gt;
    &lt;p *ngIf="condition else elseBlocks"&gt;{{ condition }} === true 时显示&lt;/p&gt;
    &lt;ng-template #firstTpl&gt;
      &lt;p&gt;{{ condition }} === false 时显示&lt;/p&gt;
    &lt;/ng-template&gt;
`,
})
export class IfComponent implements OnInit, AfterViewInit {
elseBlocks: TemplateRef&lt;any&gt; = null;
@ViewChild('firstTpl', {static: true}) primaryBlock: TemplateRef&lt;any&gt; = null;
condition = false;
constructor() {

}
ngOnInit(): void {
    console.log('ngOnInit', this.primaryBlock);
    this.elseBlocks = this.primaryBlock;
}
}
</code></pre>
<h2 id="2-ngswitch">2. *ngSwitch</h2>
<ul>
<li>基本使用<br>
ngSwitch是内置的结构型指令,控制显示那个模版,类似js中的switch</li>
<li>Angular 的 <code>NgSwitch</code> 实际上是一组相互合作的指令:<code>NgSwitch</code>、<code>NgSwitchCase</code> 和 <code>NgSwitchDefault</code>。</li>
</ul>
<pre><code class="language-html">import {Component} from '@angular/core';
@Component({
selector: 'app-switch',
template: `
    &lt;p&gt;
      &lt;input type="radio" name="fruit" value="apple" id="apple" [(ngModel)]="fruit" /&gt;
      &lt;label for="apple"&gt;苹果&lt;/label&gt;
    &lt;/p&gt;
    &lt;p&gt;
      &lt;input type="radio" name="fruit" value="pear" id="pear" [(ngModel)]="fruit" /&gt;
      &lt;label for="pear"&gt;梨&lt;/label&gt;
    &lt;/p&gt;
    &lt;p&gt;
      &lt;input type="radio" name="fruit" value="grape" id="grape" [(ngModel)]="fruit" /&gt;
      &lt;label for="grape"&gt;葡萄&lt;/label&gt;
    &lt;/p&gt;
    &lt;p&gt;
      &lt;input type="radio" name="fruit" value="other" id="other" [(ngModel)]="fruit" /&gt;
      &lt;label for="other"&gt;other&lt;/label&gt;
    &lt;/p&gt;
   
    selected fruit: {{ fruit }}
   
    &lt;div class="content" ="fruit"&gt;
      &lt;p *ngSwitchCase="'apple'"&gt;这是 苹果&lt;/p&gt;
      &lt;p *ngSwitchCase="'pear'"&gt;这是 梨&lt;/p&gt;
      &lt;p *ngSwitchCase="'grape'"&gt;这是 葡萄&lt;/p&gt;
      &lt;p *ngSwitchDefault&gt;啥都不是&lt;/p&gt;
    &lt;/div&gt;
`,
})
export class SwitchComponent {
fruit = '';
}
</code></pre>
<h2 id="3-ngfor">3. *ngFor</h2>
<h3 id="基本使用-3">基本使用</h3>
<pre><code class="language-ts">import {Component} from '@angular/core';
const Heros = [
{
    id: 'hero_0',
    name: '盖伦'
},
{
    id: 'hero_1',
    name: '赵信'
},
{
    id: 'hero_2',
    name: '嘉文'
},
{
    id: 'hero_3',
    name: '易大师'
},
{
    id: 'hero_3',
    name: '泰达米尔'
}
];
interface Hero {
id: string;
name: string;
}

@Component({
selector: 'app-switch',
template: `
    &lt;ul&gt;
      &lt;li *ngFor="let item of heros" ="item.id === 'hero_2' ? 'orange' : '#333'"&gt;{{ item.id }}&lt;/li&gt;
    &lt;/ul&gt;
`,
})
export class SwitchComponent {
heros: Hero[] = Heros;
}
</code></pre>
<h3 id="trackby">trackBy</h3>
<blockquote>
<p>trackBy接收一个函数,返回 NgFor 应该跟踪的值(比如id),这样刷新列表时,id相同的dom不会触发更新</p>
</blockquote>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-switch',
template: `
    &lt;p&gt;
      add hero:
      &lt;button class="btn btn-info" (click)="reset()"&gt;reset&lt;/button&gt;
    &lt;/p&gt;
    &lt;ul&gt;
      &lt;li *ngFor="let item of heros; trackBy: trackByHero" ="item.id === 'hero_2' ? 'orange' : '#333'"&gt;{{ item.id }}&lt;/li&gt;
    &lt;/ul&gt;
`,
})
export class SwitchComponent {
heros: Hero[] = Heros;
reset() {
    this.heros = [
      {
      id: 'hero_4',
      name: '盖伦4'
      },
      {
      id: 'hero_5',
      name: '赵信5'
      },
      {
      id: 'hero_2',
      name: '嘉文'
      },
      {
      id: 'hero_6',
      name: '易大师6'
      },
      {
      id: 'hero_7',
      name: '泰达米尔7'
      }
    ];
}
trackByHero(hero: Hero): string {
    return hero.id;
}
}
</code></pre>
<h3 id="局部变量">局部变量</h3>
<ul>
<li>$implicit: T:迭代目标(绑定到ngForOf)中每个条目的值。</li>
<li>ngForOf: NgIterable:迭代表达式的值。当表达式不局限于访问某个属性时,这会非常有用,比如在使用 async 管道时(userStreams | async)。</li>
<li>index: number:可迭代对象中当前条目的索引。</li>
<li>count: number:可迭代对象的长度。</li>
<li>first: boolean:如果当前条目是可迭代对象中的第一个条目则为 true。</li>
<li>last: boolean:如果当前条目是可迭代对象中的最后一个条目则为 true。</li>
<li>even: boolean:如果当前条目在可迭代对象中的索引号为偶数则为 true。</li>
<li>odd: boolean:如果当前条目在可迭代对象中的索引号为奇数则为 true。</li>
</ul>
<pre><code class="language-ts">import {Component} from '@angular/core';
@Component({
selector: 'app-switch',
template: `
    &lt;ul&gt;
      &lt;li
      *ngFor="let item of heros; index as i count as len; let ev = even; let od = odd; let f = first; let l = last trackBy: trackByHero"
      ="ev"
      ="od"&gt;
      &lt;p&gt;first: {{ f }} -- last: {{ l }}&lt;/p&gt;
      &lt;p&gt;name: {{ item.name }}&lt;/p&gt;
      &lt;p&gt;length: {{ len }}&lt;/p&gt;
      &lt;p&gt;index: {{ i }}&lt;/p&gt;
      &lt;hr /&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
`,
    styles: [`
    .even {
      color: #82fa54;
    }

    .odd {
      color: #698efa;
    }
`]
})
export class SwitchComponent {
heros: Hero[] = Heros;
trackByHero(hero: Hero): string {
    return hero.id;
}
}
</code></pre>
<h2 id="4-内置指令的展开写法">4. 内置指令的展开写法</h2>
<h3 id="ngif">ngIf</h3>
<pre><code class="language-ts">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;button (click)="show = !show"&gt;toggle&lt;/button&gt;
   &lt;p *ngIf="show as aa"&gt;一段文字 {{ aa }}&lt;/p&gt;

   &lt;ng-template ="show" let-aa="ngIf"&gt;
   &lt;p&gt;一段文字 {{ aa }}&lt;/p&gt;
   &lt;/ng-template&gt;
`,
})
export class AppComponent {
show = true;
}
</code></pre>
<h3 id="ngswitch">ngSwitch</h3>
<pre><code class="language-html">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `

    &lt;div class="content" ="fruit"&gt;
      &lt;p *ngSwitchCase="'apple'"&gt;这是苹果&lt;/p&gt;
      &lt;p *ngSwitchCase="'pear'"&gt;这是梨&lt;/p&gt;
      &lt;p *ngSwitchCase="'grape'"&gt;这是葡萄&lt;/p&gt;
      &lt;p *ngSwitchDefault&gt;啥都不是&lt;/p&gt;
    &lt;/div&gt;

   &lt;div class="content" ="fruit"&gt;
       &lt;ng-template ngSwitchCase="apple"&gt;
         &lt;p&gt;这是苹果&lt;/p&gt;
       &lt;/ng-template&gt;
       &lt;ng-template ngSwitchCase="pear"&gt;
         &lt;p&gt;这是梨&lt;/p&gt;
       &lt;/ng-template&gt;
       &lt;ng-template ngSwitchCase="grape"&gt;
         &lt;p&gt;这是葡萄&lt;/p&gt;
       &lt;/ng-template&gt;
       &lt;ng-template ngSwitchDefault&gt;
         &lt;p&gt;啥都不是&lt;/p&gt;
       &lt;/ng-template&gt;
   &lt;/div&gt;
`,
})
export class AppComponent {
fruit = 'pear';
}
</code></pre>
<h3 id="ngfor">ngFor</h3>
<pre><code class="language-html">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;ul class="list"&gt;
   &lt;li
       *ngFor="let item of heros; index as i; count as len; let ev = even;
               let od = odd; let f = first; let l = last; trackBy: trackByHero"
       ="ev"
       ="od"
   &gt;
       &lt;p&gt;index: {{ i }}&lt;/p&gt;
       &lt;p&gt;count: {{ len }}&lt;/p&gt;
       &lt;p&gt;name: {{ item.name }}&lt;/p&gt;
       &lt;p&gt;first: {{ f }} -- last: {{ l }}&lt;/p&gt;
       &lt;hr&gt;
   &lt;/li&gt;
   &lt;/ul&gt;
   
   &lt;ul&gt;
   &lt;ng-template
       ngFor
       ="heros"
       ="trackByHero"
       let-item
       let-i="index"
       let-od="odd"
       let-ev="even"
       let-len="count"
       let-f="first"
       let-l="last"&gt;
       &lt;li ="ev" ="od"&gt;
         &lt;p&gt;index: {{ i }}&lt;/p&gt;
         &lt;p&gt;count: {{ len }}&lt;/p&gt;
         &lt;p&gt;name: {{ item.name }}&lt;/p&gt;
         &lt;p&gt;first: {{ f }} -- last: {{ l }}&lt;/p&gt;
         &lt;hr&gt;
       &lt;/li&gt;
   &lt;/ng-template&gt;
   &lt;/ul&gt;
`,
})
export class AppComponent {
show = true;
heros = [
            {
                id: 'hero_4',
                name: '盖伦4'
            },
            {
                id: 'hero_5',
                name: '赵信5'
            },
            {
                id: 'hero_2',
                name: '嘉文'
            },
            {
                id: 'hero_6',
                name: '易大师6'
            },
            {
                id: 'hero_7',
                name: '泰达米尔7'
            }
      ];
}
</code></pre>
<h2 id="5-ng-template">5. ng-template</h2>
<p><strong>是一个 Angular 元素,用来渲染 HTML。 它永远不会直接显示出来。 事实上,在渲染视图之前,Angular 会把 及其内容替换为一个注释。</strong></p>
<p>如果没有使用结构型指令,而仅仅把一些别的元素包装进 中,那些元素就是不可见的</p>
<pre><code class="language-html">&lt;p&gt;Hip!&lt;/p&gt;
&lt;ng-template&gt;
        &lt;!-- 不可见 --&gt;
    &lt;p&gt;Hip!&lt;/p&gt;
&lt;/ng-template&gt;
&lt;p&gt;Hooray!&lt;/p&gt;
</code></pre>
<h2 id="6-ng-container">6. ng-container</h2>
<p>Angular 的 是一个分组元素,但它不会污染样式或元素布局,<strong>因为 Angular 压根不会把它放进 DOM 中。</strong></p>
<pre><code class="language-html">&lt;p&gt;
I turned the corner
&lt;ng-container *ngIf="hero"&gt;
    and saw {{hero.name}}. I waved
&lt;/ng-container&gt;
and continued on my way.
&lt;/p&gt;
</code></pre>
<p><strong>是一个由 Angular 解析器负责识别处理的语法元素。 它不是一个指令、组件、类或接口,更像是 JavaScript 中 if 块中的花括号。</strong></p>
<pre><code class="language-ts">if (someCondition) {
statement1;
statement2;
statement3;
}
</code></pre>
<h2 id="7-自定义unless指令">7. 自定义unless指令</h2>
<pre><code class="language-js">import {Directive, Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef} from '@angular/core';
export class UnlessContext&lt;T = unknown&gt; {
$implicit: T = null;
appUnless: T = null;
attr: T = null;
}
@Directive({
selector: ''
})
export class UnlessDirective implements OnChanges {
@Input('appUnless') unless: boolean;
private hasView = false;
private context = new UnlessContext();
constructor(private templateRef: TemplateRef&lt;any&gt;, private viewContainer: ViewContainerRef) {
    // console.log(this.templateRef);
    // console.log(this.viewContainer);
}

ngOnChanges(changes: SimpleChanges): void {
    if (changes['unless']) {
    this.context.$implicit = this.context.appUnless = this.unless;
    this.context.attr = 'aaab';
      if (this.unless) {
      if (this.hasView) {
          this.viewContainer.clear();
          this.hasView = false;
      }
      } else {
      if (!this.hasView) {
          // 这里使用的构造提供的模版(this.templateRef)
          // 实战中可以通过一个input属性传入模版
          this.viewContainer.createEmbeddedView(this.templateRef, this.context);
          this.hasView = true;
      }
      }
    }
}
}
</code></pre>
<p>调用:</p>
<pre><code class="language-html">import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
   &lt;section&gt;
       &lt;h3&gt;unless&lt;/h3&gt;
       &lt;button class="btn btn-primary" (click)="showUnless = !showUnless"&gt;toggle unless {{ showUnless }}&lt;/button&gt;
       &lt;p *appUnless="showUnless"&gt;测试unless driective -- {{ showUnless }}&lt;/p&gt;
       &lt;p *appUnless="showUnless as un"&gt;测试unless driective alias un -- {{ un }}&lt;/p&gt;
       &lt;p *appUnless="showUnless; let un; let attr=attr;"&gt;测试unless driective alias let un -- {{ un }} attr: {{ attr }}&lt;/p&gt;
   &lt;/section&gt;
`,
})
export class AppComponent {
show = false;
}
</code></pre>
<h1 id="六管道">六、管道</h1>
<h1 id="七transfer组件">七、transfer组件</h1>
<ul>
<li>样式为bootstrap</li>
<li>组件展示</li>
</ul>
<p><img src="../media/image-20201027113706819.png" alt="image-20201027113706819" loading="lazy"></p>
<p>app.component.html</p>
<pre><code class="language-html">&lt;div class="demo-sec"&gt;
&lt;div class="panel"&gt;
    &lt;button class="btn btn-primary" (click)="setList()"&gt;按钮&lt;/button&gt;
    &lt;app-transfer-panel ="true" ="list"
                        (changed) = "onChanged($event)"&gt;&lt;/app-transfer-panel&gt;
&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>app.component.ts</p>
<pre><code class="language-javascript">import { Component } from '@angular/core';
import { TransferItem } from './components/transfer-panel/types';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
list: TransferItem[] = [];
constructor(){
    this.setList()
}
onChanged(selicteds:TransferItem[]){
console.log('onChanged',selicteds);
}
setList() {
this.list = [];
const prefix = 'item' + Date.now().toString().slice(-3);
for (let i = 0; i &lt; 20; i++) {
    this.list.push({
      key: prefix + '_' + i,
      value: `${prefix}${i + 1}`,
      checked: i % 6 === 0
    });
}
}
}
</code></pre>
<p>transfer-panel.component.html</p>
<pre><code class="language-html">&lt;div class="transfer-panel border rounded"&gt;
    &lt;div class="head pl-3"&gt;
      &lt;p&gt;
      &lt;span *ngIf="selecteds.length"&gt;{{selecteds.length}} /&lt;/span&gt; {{showList.length}}
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="search-box p-2" *ngIf="search"&gt;
      &lt;input (input)="onInput($event)"
             type="text" class="form-control" placeholder="请输入关键字" /&gt;
    &lt;/div&gt;
   
    &lt;ul class="list mb-0 overflow-auto pl-0"&gt;
      &lt;li *ngFor="let item of showList"
       = 'targetIndex(item.key) &gt; -1'
      (click) = "itemClick(item)"
      class="list-item text-truncate list-group-item-action"&gt;
      {{item.value}}
      &lt;/li&gt;
      
      &lt;!-- &lt;li
      *ngFor="let item of showList; trackBy: trackByItem"
      class="list-item text-truncate list-group-item-action"&gt;
      {{ item.value }}
      &lt;/li&gt; --&gt;
    &lt;/ul&gt;
&lt;/div&gt;
</code></pre>
<p>transfer-panel.component.ts</p>
<pre><code class="language-ts">import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { TransferItem } from './types';

@Component({
selector: 'app-transfer-panel',
templateUrl: './transfer-panel.component.html',
styleUrls: ['./transfer-panel.component.scss']
})
export class TransferPanelComponent implements OnInit,OnChanges {
@Input() list: TransferItem[]=[];
@Input() search = false;
@Output() changed = new EventEmitter&lt;TransferItem[]&gt;();
showList: TransferItem[] = [];
selecteds:TransferItem[] = [];
constructor() { }
ngOnChanges(changes: SimpleChanges): void {
    const { list } = changes;
    if(list){
      console.log('list:',list.currentValue)
      // this.selecteds = []
      this.showList = list.currentValue.slice();
      this.selecteds = this.list.filter(item=&gt;item.checked)
    }
}

ngOnInit(): void {}

onInput(event:Event){
    const {value} = (event.target as HTMLInputElement);
    console.log(value);
    this.showList = this.list.filter(item=&gt;item.value.includes(value))
}
itemClick(target:TransferItem){
    console.log(target);
    // const index = this.selecteds.findIndex(item =&gt;item.key === target.key);
    const index = this.targetIndex(target.key)
    if (index&gt;-1){
      this.selecteds.splice(index,1);
    }else{
      this.selecteds.push(target);
    }
    this.changed.emit(this.selecteds);
}
targetIndex(key:string):number{
    return this.selecteds.findIndex(item =&gt;item.key === key);
}
}
</code></pre><br><br>
来源:https://www.cnblogs.com/dingdc/p/14037396.html
頁: [1]
查看完整版本: Angular(1)