ionic3應(yīng)該善用組件和指令

ionic3開(kāi)發(fā)框架是angular4,所以了解一下angular4的一些基礎(chǔ)知識(shí),能讓你更好的開(kāi)發(fā)應(yīng)用。

angular4提供了很多功能強(qiáng)大的內(nèi)置指令,但在現(xiàn)實(shí)情況中,這些內(nèi)置指令可能還不能完全滿足實(shí)際要求,這時(shí)我們就需要編寫(xiě)自定義指令來(lái)實(shí)現(xiàn)特定要求。

其實(shí)ionic3(angualr4)和ionic2(angular2)差不多,但和ionic1(angular1)就差別非常大了,可以說(shuō)基本是推倒了重來(lái)。在angular1時(shí)代,組件和指令是一回事,即嚴(yán)格來(lái)說(shuō),沒(méi)有組件這概念,只有指令,而到了angular2時(shí)代,雖說(shuō)組件仍是一種特殊的指令,但已經(jīng)有一定目的明顯區(qū)分開(kāi)來(lái),分別用Directive和Component來(lái)標(biāo)識(shí),用cli生成命令就如下所示:

ionic g directive 指令名
ionic g component 組件名

要說(shuō)指令和組件的區(qū)別,簡(jiǎn)單說(shuō)是不帶視圖和帶視圖的區(qū)別,直觀效果是:一個(gè)為原有標(biāo)簽動(dòng)態(tài)添加功能,另一個(gè)為新建自定義功能標(biāo)簽,詳細(xì)上有不少細(xì)節(jié)上的不同。

往往很多人會(huì)封裝組件,但不會(huì)去封裝指令,而選擇用Provider或者Pipe(管道,相當(dāng)于angular1時(shí)的過(guò)濾器filter),甚至樣式來(lái)實(shí)現(xiàn),雖說(shuō)這也能解決部分問(wèn)題,但不是最優(yōu)的,Directive、Componet、Provider、Pipe都有其專(zhuān)業(yè)適用場(chǎng)景,如結(jié)構(gòu)性指令(下面會(huì)說(shuō)),就不好用Provider和Pipe來(lái)處理。

Directive——指令

三種分類(lèi):

  1. 屬性指令
    屬性指令指的是以屬性形式使用的指令,如ngModel、ngClass、ngStyle等。

  2. 結(jié)構(gòu)指令
    結(jié)構(gòu)指令,用于修改DOM結(jié)構(gòu)。其實(shí)就是模版指令,如ngIf,當(dāng)條件為true時(shí),該元素會(huì)被添加到DOM中。其主要依賴(lài)TemplateRef和ViewContainerRef來(lái)完成操作。TemplateRef用來(lái)訪問(wèn)組件的模板,而ViewContainerRef可作為視圖內(nèi)容渲染器,將模板內(nèi)容插入至DOM中。

  3. 組件
    這個(gè)不必說(shuō)了,我們用得最多的便是組件。與其他指令不同,它描述的是一個(gè)視圖,是用戶可以直接看到的東西。

自定義屬性指令

實(shí)例:創(chuàng)建一個(gè)bgColor屬性指令,支持傳入顏色名參數(shù),設(shè)置目標(biāo)標(biāo)簽的背景色

1)創(chuàng)建指令。cli使用如下命令創(chuàng)建基本指令,會(huì)生成bg-color.ts文件:

ionic g directive bgColor

2)修改指令。在構(gòu)造函數(shù)constructor加上一句,賦值默認(rèn)顏色:

import { Directive, Input, ElementRef  } from '@angular/core';

@Directive({
  selector: '[bg-color]' // Attribute selector
})
export class BgColorDirective {
  constructor(private el: ElementRef) {
     this.el.nativeElement.style.backgroundColor = 'red';
  }
}

基于安全性考慮,angualr2的文檔是建議用Renderer來(lái)代替ElementRef使用,有興趣的可以自行了解下Renderer

3)使用指令
如果調(diào)用的頁(yè)面用了懶加載,在調(diào)用指令的頁(yè)面module.ts里導(dǎo)入指令并聲明,反之,在app.module.ts里導(dǎo)入指令并聲明,這樣調(diào)用的組件就能識(shí)別該指令了:

import { BgColorDirective } from '../../directives/bg-color/bg-color';

@NgModule({
  declarations: [
    ContactPage,
    BgColorDirective
  ],
  ...
})

在ContactPage.html里這樣使用即可查看效果:

<button ion-button bg-color>
   test
 </button>
指令效果.png

4)指令擴(kuò)展,支持輸入?yún)?shù)。
上述指令是一個(gè)很簡(jiǎn)單的指令,且很不靈活,因?yàn)轭伾珜?xiě)死為red了,實(shí)際上我們使用場(chǎng)景應(yīng)該支持多種顏色。那我們這樣修改:

import { Directive, Input, ElementRef  } from '@angular/core';

@Directive({
  selector: '[bg-color]' // Attribute selector
})
export class BgColorDirective {

  defaultColor: string = 'red';   //默認(rèn)顏色

  @Input('bg-color')
  set backgroundColor(color:string) {
    this.setStyle(color);
  };

  constructor(private el: ElementRef) {
    this.setStyle(this.defaultColor);
  }

  private setStyle(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

改動(dòng)的只是用@Input裝飾器修飾,然后用set方法觸發(fā)獲得值后的操作。

我們?cè)诮M件html里就可以這樣調(diào)用了:

  <button ion-button bg-color="green">
    test
  </button>
指令效果.png

5)指令擴(kuò)展,支持事件操作
我們?cè)黾右粋€(gè)點(diǎn)擊事件響應(yīng)操作,點(diǎn)擊時(shí),循環(huán)切換背景色。為實(shí)現(xiàn)該功能,我們需要在事件處理函數(shù)上添加@HostListener裝飾器,代碼改動(dòng)如下:

import { Directive, Input, ElementRef, HostListener  } from '@angular/core';

@Directive({
  selector: '[bg-color]' // Attribute selector
})
export class BgColorDirective {

  defaultColor: string = 'red';   //默認(rèn)顏色
  bgColor: string;    //背景顏色
  @Input('bg-color')
  set backgroundColor(color:string) {
    this.setStyle(color);
    this.bgColor = color;
  };

  constructor(private el: ElementRef) {
    this.setStyle(this.defaultColor);
  }

  private setStyle(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }

  @HostListener('click')
  onClick() {
    let color: string = this.el.nativeElement.style.backgroundColor == this.defaultColor ? this.bgColor :  this.defaultColor;
    this.setStyle(color);
  }
}

效果圖為:我懶得做gif,你想象一個(gè)點(diǎn)擊循環(huán)切換背景色的按鈕吧。

自定義結(jié)構(gòu)指令

實(shí)例:山寨一個(gè)*ngIf的的收縮顯示指令,僅為了起到拋磚引玉效果。

為實(shí)現(xiàn)該指令,要借用TemplateRef和ViewContainerRef,TemplateRef用來(lái)訪問(wèn)組件的模板,而ViewContainerRef可作為視圖內(nèi)容渲染器,將模板內(nèi)容插入至DOM中。

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[expand]' // Attribute selector
})
export class ExpandDirective {

  @Input('expand')
  set condition(newCondition:boolean) {
    if(!newCondition) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }
  constructor(private templateRef: TemplateRef<any>, private viewContainer:ViewContainerRef) {
}
}

同樣別忘了在module里引入后,再在html里使用:

  <div *expand="isExpand">
    <button ion-button>test</button>
  </div>
  <div *expand="!isExpand">
     一段文字
  </div>

效果圖不上了,留待你們?cè)囼?yàn),哇咔咔。

Component——組件

ionic g component ContentEmpty

關(guān)于component,太多文章講了,這里我不詳細(xì)說(shuō)明,主要就兩個(gè)裝飾器:@Input、@Output,分別用于屬性和事件綁定。對(duì)于事件,使用EventEmitter發(fā)送參數(shù)即可。直接上代碼:

組件ts部分:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'content-empty',
  templateUrl: 'content-empty.html'
})
export class ContentEmptyComponent {

  @Input() btnWorkText: string = '';    //加載成功后按鈕文字
  @Output() doWork: EventEmitter<any> = new EventEmitter();
  constructor() {
}

  onDoWork($event){
    this.doWork.emit($event);
  }
}

組件html部分:

    <button ion-button *ngIf="btnWorkText" color="blue" round outline small (click)="onDoWork($event)" >
        {{btnWorkText}}
    </button>

同樣在module里引入后,在html如下調(diào)用即可:

<content-empty [btnWorkText]="數(shù)據(jù)加載中" (doWork)="方法()"></content-empty>

總結(jié):可以看出來(lái),自定義指令和組件不算復(fù)雜,只是大家都沒(méi)有要去封裝的概念。如果幾乎不需要復(fù)用的東西,直接用內(nèi)置指令實(shí)現(xiàn)就好了,否則就要考慮自定指令了,能讓你的項(xiàng)目結(jié)構(gòu)更清晰化,至于選擇哪種,自己靜下心來(lái)想一下就好了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容