首頁  >  文章  >  web前端  >  Angular中什麼是變更檢測?什麼情況下會造成變更檢測?

Angular中什麼是變更檢測?什麼情況下會造成變更檢測?

青灯夜游
青灯夜游轉載
2022-12-13 20:06:002040瀏覽

Angular中什麼是變更偵測?以下這篇文章帶大家了解變更檢測,並介紹一下什麼情況下會引起變更檢測,希望對大家有幫助!

Angular中什麼是變更檢測?什麼情況下會造成變更檢測?

什麼是變更偵測?

簡單來說,變更偵測就是Angular用來偵測視圖與模型之間綁定的值是否發生了改變,當偵測到模型中的值發生改變時,則同步到視圖上,反之,當偵測到視圖上的值發生變化時,則回調對應的綁定函數。 【相關教學推薦:《angular教學》】

#也就是,把模型的變化和視圖保持一致的機制,這個機制,我們稱為變更偵測。

在Angular裡,開發者無需把精力放到具體的DOM更新上,關注與業務就可以了,因為這部分工作Angular幫我們做了。

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

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

    function renderHTML() {
      document.getElementById(&#39;dataDiv&#39;).innerText = value;
    }

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

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

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

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

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

    // Example 5: some other asynchronous APIs
    document.getElementById(&#39;canvas&#39;).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>

在上面的範例中,我們更新資料後,需要呼叫detectChange() 來檢查資料是否已更改。如果資料已經更改,則渲染HTML以反應更新的資料。當然,在Angular中,開發者不需要關心這些步驟,只需要更新你的資料就可以了,DOM會自動更新。這就是變更檢測。

什麼情況下會造成變更偵測

變更偵測的關鍵在於如何最小粒度地偵測到綁定的值是否發生了改變,那麼在什麼情況下會導致這些綁定的值改變呢?

結合日常開發,來看幾個場景。

場景一

元件初始化

#當啟動Angular 應用程式時,Angular 會載入引導元件並觸發ApplicationRef.tick() 來呼叫變更偵測和視圖渲染。

場景二

DOM與BOM事件

DOM 事件BOM事件偵聽器可以更新Angular 元件中的數據,也可以觸發變更偵測,如下例所示。

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

  constructor() {}

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

我們在視圖上透過插值表達式綁定了counter中的count屬性,當點擊按鈕時,改變了count屬性的值,這時就導致了綁定的值發生了變化。

場景三

HTTP資料請求

@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這個元件裡向服務端發送了一個Ajax請求,當請求傳回結果時,會改變視圖中綁定的todos的值。

場景四

其他巨集任務和微任務

例如setTimeout() 或setInterval()。你也可以在 setTimeout() macroTask 的回呼函數中更新資料。

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

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

實際開發中可能會在某一個函數裡呼叫定時器去改變一個綁定的值。

再例如 Promise.then() 。其他非同步 API(例如 fetch)會傳回 Promise 對象,因此 then() 回呼函數也可以更新資料。

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

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

場景五

#其他非同步運算

除了addEventListener() ,setTimeout() 和Promise.then() ,還有其他一些操作可以非同步更新資料。如 WebSocket.onmessage()Canvas.toBlob()

不難發現,上述幾種情況都有一個共同點,就是導致綁定值發生改變的事件都是 非同步事件只要發生了非同步操作,Angular就會認為有狀態可能發生了變化,然後進行變更偵測

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

這些包含了應用程式可能會在其中更改資料的最常見的場景。只要Angular偵測到資料可能已更改,就會進行變更偵測,變更偵測的結果是根據這些新資料DOM被更新。 Angular 會以不同的方式檢測變化。對於元件初始化,Angular 呼叫明確變更偵測。對於非同步操作,Angular 會使用 Zone 在資料可能被修改的地方偵測變化,並自動執行變更偵測。

那要如何訂閱這些非同步事件呢?請期待下一篇。

更多程式相關知識,請造訪:程式設計教學! !

以上是Angular中什麼是變更檢測?什麼情況下會造成變更檢測?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除