• 技术文章 >web前端 >js教程

    Angular中什么是变更检测?什么情况下会引起变更检测?

    青灯夜游青灯夜游2022-12-13 20:06:00转载83
    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 = '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中什么是变更检测?什么情况下会引起变更检测?的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:Angular 变更检测
    上一篇:聊聊如何选择一个最好的Node.js Docker镜像? 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 如何在Angular service中使用TemplateRef• 聊聊Angular中懒加载模块并动态显示它的组件• 手把手带你了解Angular中的依赖注入• 深入了解Angular(新手入门指南)• Angular学习之详解样式绑定(ngClass和ngStyle)的使用
    1/1

    PHP中文网