Angular中什麼是變更檢測?什麼情況下會引起變更檢測?

2022-12-13 22:00:41
中什麼是變更檢測?下面本篇文章帶大家瞭解一下變更檢測,並介紹一下什麼情況下會引起變更檢測,希望對大家有所幫助!

前端(vue)入門到精通課程,老師線上輔導:聯絡老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:

什麼是變更檢測?

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

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

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

如果不用Angular的話,用原生的JS開發,我們必須手動的去更新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>
登入後複製

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

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

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

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

場景一

元件初始化

當啟動 Angular 應用程式時,Angular 會載入引導元件並觸發 來呼叫變更檢測和檢視渲染。

場景二

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: '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';
    });
  }
}
登入後複製

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

再比如 Promise.then() 。其他非同步 API(比如 fetch)會返回 Promise 物件,因此 then() 回撥函數也可以更新資料。

@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() ,還有其他一些操作可以非同步更新資料。比如 WebSocket.onmessage()Canvas.toBlob()

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

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

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

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

更多程式設計相關知識,請存取:!!

以上就是Angular中什麼是變更檢測?什麼情況下會引起變更檢測?的詳細內容,更多請關注TW511.COM其它相關文章!