【Angular】HostBinding和HostListener兩個裝飾器的理解和使用場景

我的疑惑

不知道各位小伙伴在自學(xué)angular的時候有沒有遇到過這兩個裝飾器——HostBindingHostListener。這兩個裝飾器我在看官網(wǎng)的api說明的時候,真是百思不得其解,明明每個字我都能看懂,但是連在一起我就是看不懂了。而且官網(wǎng)上面給出的示例也很迷,讓我搞不明白這倆api的使用場景到底是啥。

官網(wǎng)說明

先看看這兩個api在官網(wǎng)上面的說明吧:

HostBinding官網(wǎng)鏈接):

用于把一個 DOM 屬性標(biāo)記為綁定到宿主的屬性,并提供配置元數(shù)據(jù)。 Angular 在變更檢測期間會自動檢查宿主屬性綁定,如果這個綁定變化了,它就會更新該指令所在的宿主元素。

HostListener官網(wǎng)鏈接):

用于聲明要監(jiān)聽的 DOM 事件,并提供在該事件發(fā)生時要運行的處理器方法。

是不是看完之后也不知道這倆兄弟的使用場景到底是啥?在我看來,這倆裝飾器的作用是為了方便我們將復(fù)雜的DOM操作可以抽取成一個指令,以此來精簡代碼。廢話不多說,上代碼,一看就懂。

代碼示例

假設(shè)此時有一個業(yè)務(wù)場景,有一個輸入框input,我們每次輸入的時候,字的顏色和邊框的顏色就會變化一下,我們?nèi)∶小安屎巛斎肟颉薄?/p>

如果我們不使用組件封裝的方式的話,直接在組件中寫相關(guān)的DOM操作,代碼如下:

@Component({
  selector: 'app-rainbow-input-demo',
  template: `
    <h3>這是一個彩虹輸入框,每輸入一次都會改變顏色</h3>
    <input [class]="'my-input'"
           type="text"
           [style]="inputStyleObj"
           (keydown)="onKeyDown()"
    />
  `,
  styles:[
    `.my-input {
        border:none;
        outline: none;
        border: 2px solid #333333;
        border-radius: 5px;
      }`
  ]
})
export class RainbowInputDemoComponent {
  //默認的顏色樣式
  public inputStyleObj = {
    color:null,
    borderColor:null,
  };
  //顏色庫
  public possibleColors = [
    'darksalmon', 'hotpink', 'lightskyblue',
    'goldenrod', 'peachpuff', 'mediumspringgreen',
    'cornflowerblue', 'blanchedalmond', 'lightslategrey'
  ];
  //鍵盤落下事件
  onKeyDown(){
    const index = Math.floor(Math.random() * this.possibleColors.length);
    //如果我們直接使用this.inputStyleObj.color = this.possibleColors[index]的話,
    //this.inputStyleObj雖然內(nèi)容變了,由于它是引用類型,其地址值沒有變。所以不會觸發(fā)視圖的重新渲染
    //在angular中,和react似的,我們直接修改引用類型不會觸發(fā)重新渲染,只能覆蓋它或者合并它,使其地址值發(fā)生改變,才會觸發(fā)重新渲染
    //如果覺得麻煩的話,完全可以在模板中使用[style.color]和[style.borderColor]
    this.inputStyleObj = {
      color:this.possibleColors[index],
      borderColor:this.possibleColors[index],
    }
  }
}

效果如圖:


彩虹輸入框

就這樣,我們實現(xiàn)了這個功能,那么現(xiàn)在有個問題。假如這種rainbowInput我們還需要在其他組件用到怎么辦,難道每次使用的時候我們都把這些代碼復(fù)制粘貼一遍嗎?很明顯這不符合組件封裝的原則,如果你真的這么做,技術(shù)經(jīng)理或者項目經(jīng)理也會打爆你的狗頭、

那么我們就需要將其封裝成一個組件或者一個指令。在這篇文章中我們先把它封裝成一個指令,至于原因后面再說。代碼如下:

@Directive({
  selector: '[appRainbow]'
})
export class RainbowInputDirective {
  public possibleColors = [
    'darksalmon', 'hotpink', 'lightskyblue',
    'goldenrod', 'peachpuff', 'mediumspringgreen',
    'cornflowerblue', 'blanchedalmond', 'lightslategrey'
  ];
  //字體顏色
  @HostBinding('style.color') color: string;
  //邊框顏色
  @HostBinding('style.borderColor') borderColor: string;
  //監(jiān)聽鍵盤落下的事件
  @HostListener('keydown') onKeyDown() {
    //獲取一個隨機的顏色
    const index = Math.floor(Math.random() * this.possibleColors.length);
    this.color = this.borderColor = this.possibleColors[index];
  }
}

@Component({
  selector: 'app-rainbow-input-demo',
  template: `
    <h3>這是一個彩虹輸入框,每輸入一次都會改變顏色</h3>
    <input [class]="'my-input'" type="text" appRainbow />
  `,
  styles:[
    //省略,和上面相同
  ]
})
export class RainbowInputDemoComponent {}

就像上面代碼寫的那樣,我們將重復(fù)的邏輯抽取了出來,使代碼的維護性和美觀度都有了很大的提升。

結(jié)論

在代碼中我們可以看到@HostBinding的作用其實就是將某個屬性綁定到了宿主元素上,但是這個屬性不是隨隨便便的屬性。這個屬性指的是angular模板中支持的屬性,其實@HostBinding就相當(dāng)于模板中的[]或者bind-。同理@HostListener就相當(dāng)于模板中的()或者on-。使我們可以在指令當(dāng)中就可以將屬性和方法綁定到宿主元素上,實現(xiàn)的效果和我們第一種直接將(keydow)[style]直接寫在模板上是一樣的。所以說,這倆裝飾器里面的字符串那可不能隨便寫。

關(guān)于指令和組件

但是,其實在angular當(dāng)中,組件和指令其實區(qū)別不是特別大,因為angular中的組件裝飾器@Component就是繼承自@Directive的。

其實我們將這個DOM操作封裝成一個組件也不是不可以,代碼如下

@Component({
  selector:'input[appRainbow]'
})

但是和指令寫法:

@Directive({
  selector: '[appRainbow]'
})

真的差別不大。

總結(jié)

@HostBinding相當(dāng)于模板上的[]或者bind-;

@HostListener相當(dāng)于模板上的()或者on-;

就是angular為了不希望我們直接操作DOM,提供的指令中的數(shù)據(jù)和方法綁定。

參考資料

Angular @HostBinding()和@HostListener()用法

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

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

  • 裝飾器的作用就是在添加裝飾器的地方在不改動原有代碼的情況下增加額外的功能。Angular框架中裝飾器是一個函...
    tuacy閱讀 2,562評論 0 2
  • 單向從數(shù)據(jù)源到視圖 單向從視圖到數(shù)據(jù)源 雙向 DOM property 的值可以改變;HTML attribute...
    chrisghb閱讀 1,001評論 1 1
  • 初涉angular之自定義指令 1.自定義指令 在app.module聲明指令,在app.module的decla...
    前端小慵卿閱讀 484評論 0 0
  • Angular 創(chuàng)建一個Angular項目 前提準(zhǔn)備 安裝node、npm 安裝Angular CLI 創(chuàng)建新項目...
    涙_閱讀 267評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,831評論 28 54

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