溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Angular變更檢測是怎么引起的

發(fā)布時間:2022-12-14 09:39:36 來源:億速云 閱讀:95 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“Angular變更檢測是怎么引起的”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

什么是變更檢測?

簡單來說,變更檢測就是Angular用來檢測視圖與模型之間綁定的值是否發(fā)生了改變,當(dāng)檢測到模型中的值發(fā)生改變時,則同步到視圖上,反之,當(dāng)檢測到視圖上的值發(fā)生改變時,則回調(diào)對應(yīng)的綁定函數(shù)。

也就是,把模型的變化和視圖保持一致的機(jī)制,這種機(jī)制,我們稱為變更檢測。

Angular變更檢測是怎么引起的

在Angular里,開發(fā)者無需把精力放到具體的DOM更新上,關(guān)注與業(yè)務(wù)就可以了,因?yàn)檫@部分工作Angular幫我們做了。

如果不用Angular的話,用原生的JS開發(fā),我們必須手動的去更新DOM,先來看一個例子。

<html>
  <div id="dataDiv"></div>
  <button id="btn">updateData</button>
  <canvas id="canvas"></canvas>
  <script>
    let value = 'initialValue';
    // initial rendering
    detectChange();

    function renderHTML() {
      document.getElementById('dataDiv').innerText = value;
    }

    function detectChange() {
      const currentValue = document.getElementById('dataDiv').innerText;
      if (currentValue !== value) {
        renderHTML();
      }
    }

    // Example 1: update data inside button click event handler
    document.getElementById('btn').addEventListener('click', () => {
      // update value
      value = 'button update value';
      // call detectChange manually
      detectChange();
    });

    // Example 2: HTTP Request
    const xhr = new XMLHttpRequest();
    xhr.addEventListener('load', function() {
      // get response from server
      value = this.responseText;
      // call detectChange manually
      detectChange();
    });
    xhr.open('GET', serverUrl);
    xhr.send();

    // Example 3: setTimeout
    setTimeout(() => {
      // update value inside setTimeout callback
      value = 'timeout update value';
      // call detectChange manually
      detectChange();
    }, 100);

    // Example 4: Promise.then
    Promise.resolve('promise resolved a value').then(v => {
      // update value inside Promise thenCallback
      value = v;
      // call detectChange manually
      detectChange();
    }, 100);

    // Example 5: some other asynchronous APIs
    document.getElementById('canvas').toBlob(blob => {
      // update value when blob data is created from the canvas
      value = `value updated by canvas, size is ${blob.size}`;
      // call detectChange manually
      detectChange();
    });
  </script>
</html>

在上面的例子中,我們更新數(shù)據(jù)后,需要調(diào)用detectChange() 來檢查數(shù)據(jù)是否已更改。如果數(shù)據(jù)已經(jīng)更改,則渲染HTML以反應(yīng)更新的數(shù)據(jù)。當(dāng)然,在Angular中,開發(fā)者無需關(guān)心這些步驟,只需要更新你的數(shù)據(jù)就可以了,DOM會自動更新。這就是變更檢測。

什么情況下會引起變更檢測

變更檢測的關(guān)鍵在于如何最小粒度地檢測到綁定的值是否發(fā)生了改變,那么在什么情況下會導(dǎo)致這些綁定的值發(fā)生變化呢?

結(jié)合日常開發(fā),來看幾種場景。

場景一

組件初始化

當(dāng)啟動 Angular 應(yīng)用程序時,Angular 會加載引導(dǎo)組件并觸發(fā) ApplicationRef.tick() 來調(diào)用變更檢測和視圖渲染。

場景二

DOM和BOM事件

DOM 事件BOM事件偵聽器可以更新 Angular 組件中的數(shù)據(jù),還可以觸發(fā)變更檢測,如下例所示。

@Component({
  selector: "counter",
  template: `
    Count:{{ count }}
    <br />
    <button (click)="add()">Add</button>
  `,
})
export class CounterComponent {
  count = 0;

  constructor() {}

  add() {
    this.count = this.count + 1;
  }
}

我們在視圖上通過插值表達(dá)式綁定了counter中的count屬性,當(dāng)點(diǎn)擊按鈕時,改變了count屬性的值,這時就導(dǎo)致了綁定的值發(fā)生了變化。

場景三

HTTP數(shù)據(jù)請求

@Component({
    selector: "todos",
    template: ` <li *ngFor="let item of todos">{{ item.titme }}</li> `,
  })
  export class TodosComponent implements OnInit {
    public todos: TodoItem[] = [];

    constructor(private http: HttpClient) {}

    ngOnInit() {
      this.http.get<TodoItem[]>("/api/todos").subscribe((todos: TodoItem[]) => {
        this.todos = todos;
      });
    }
  }

我們在todos這個組件里向服務(wù)端發(fā)送了一個Ajax請求,當(dāng)請求返回結(jié)果時,會改變視圖中綁定的todos的值。

場景四

其他宏任務(wù)和微任務(wù)

比如 setTimeout() 或 setInterval()。你還可以在 setTimeout() macroTask 的回調(diào)函數(shù)中更新數(shù)據(jù)。

@Component({
  selector: 'app-root',
  template: '<div>{{data}}</div>';
})
export class AppComponent implements OnInit {
  data = 'initial value';

  ngOnInit() {
    setTimeout(() => {
      // user does not need to trigger change detection manually
      this.data = 'value updated';
    });
  }
}

實(shí)際開發(fā)中可能會在某一個函數(shù)里調(diào)用定時器去改變一個綁定的值。

再比如 Promise.then() 。其他異步 API(比如 fetch)會返回 Promise 對象,因此 then() 回調(diào)函數(shù)也可以更新數(shù)據(jù)。

@Component({
  selector: 'app-root',
  template: '<div>{{data}}</div>';
})
export class AppComponent implements OnInit {
  data = 'initial value';

  ngOnInit() {
    Promise.resolve(1).then(v => {
      // user does not need to trigger change detection manually
      this.data = v;
    });
  }
}

場景五

其他異步操作

除了 addEventListener(),setTimeout() 和 Promise.then() ,還有其他一些操作可以異步更新數(shù)據(jù)。比如 WebSocket.onmessage()Canvas.toBlob() 。

不難發(fā)現(xiàn),上述幾種情況都有一個共同點(diǎn),就是導(dǎo)致綁定值發(fā)生改變的事件都是 異步事件。只要發(fā)生了異步操作,Angular就會認(rèn)為有狀態(tài)可能發(fā)生了變化,然后進(jìn)行變更檢測。

思考:還有哪些是異步事件啊?

這些包含了應(yīng)用程序可能會在其中更改數(shù)據(jù)的最常見的場景。只要Angular檢測到數(shù)據(jù)可能已更改,就會進(jìn)行變更檢測,變更檢測的結(jié)果是根據(jù)這些新數(shù)據(jù)DOM被更新。Angular 會以不同的方式檢測變化。對于組件初始化,Angular 調(diào)用顯式變更檢測。對于異步操作,Angular 會使用 Zone 在數(shù)據(jù)可能被修改的地方檢測變化,并自動運(yùn)行變更檢測。

“Angular變更檢測是怎么引起的”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI