您好,登錄后才能下訂單哦!
本篇內容介紹了“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 = '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 會加載引導組件并觸發 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: '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變更檢測是怎么引起的”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。