微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一窥angular自动更新dom的秘密——zone.js

在使用angular框架时,变量会和视图模版绑定,一旦修改了变量,视图也随之改变   背后进行的是一种被称作“脏检查”的机制,所谓“脏检查”,其实就是新旧值的对比   改变的值可以看作“脏值”,angular会寻找所有绑定了“脏值”的组件,修改视图   这里不得不提的是angular1.0时,数据并非单向流动   所以有可能形成环形结构,触发多次“脏检查”,一直到变动的值稳定下来   有时甚至需要一些“黑魔法”,这也是1.0时性能被诟病的原因   但在2.0之后的版本,angular借鉴了react的单向数据流架构,不会再出现触发多次“脏值检测”的情况   那么,为什么我只是改动了数据,并没有调用类似change_detection之类的函数,angular就会自动触发“脏检查”呢   奥秘就在于zone.js这个类库   它是angular团队受Dart语言启发所开发的用于对异步操作进行包裹并暴露一些“钩子函数”的库   没错,正是因为zone.js对浏览器所有异步进行了包裹,才使得angular有机会把change_detection操作注入进去   这样只需要修改和视图绑定的变量,无需手动去声明要进行change_detection操作,angular就会自动进行“脏检查”   接下来不妨探究一下zone.js是怎么对异步包裹的   其实,它是采用“猴子补丁”的方式暴力对浏览器的所有异步进行了包裹   浏览器中的异步一般就是网络请求,事件,定时器这三类   以setTimeout为例,先把它保存起来  
let temp = window.setTimeout;
然后去接管它  
window.setTimeout = function(fn, time) {
    temp(function() {
        console.log('额外操作:定时器函数执行之前');
        fn();
        console.log('额外操作:定时器函数执行之后');
    }, time);
};
为了避免污染全局变量,可以放到自执行匿名函数中  
;(function(_setTimeout) {
    window.setTimeout = function(fn, time) {
        _setTimeout(function() {
            console.log('额外操作:定时器函数执行之前');
            fn();
            console.log('额外操作:定时器函数执行之后');
        }, time);
    };
})(window.setTimeout);
setTimeout包裹完成,可以像往常一样调用它试试  
setTimeout(() => {
    console.log('我将在1.5s后执行');
}, 1500);
这时setTimeout指向的并非是浏览器提供的认setTimeout函数,而是我们的自定义函数   zone.js正是通过这种方式对所有异步进行了包裹,并暴露出一些“钩子函数”,使原生API可以被注入一些自定义行为   对angular来说,它可以在这些“钩子函数”中,去进行新旧值的对比并对视图做出对应的改动   zone.js对日常开发带来的意义在于,它让浏览器中的异步变得可定制   当然,千万不要在angular中去对异步进行二次包裹(除非你非常清楚自己在做什么并且认为有必要这样做),   这极可能会覆盖angular本身对异步的第一次包裹,使程序产生不可预料的行为   最后,zone.js是一个独立的库,并非依赖于angular,你可以很轻松的使你的angular应用不依赖它   在项目文件的最外层,找到main.ts文件,改写配置  
platformbrowserDynamic().bootstrapModule(AppModule, {ngzone: 'noop'})
.catch(err => console.error(err));
此时你的项目再运行看看,尽管数据更改了,但视图没有发生任何改变   如果想要视图更改的话,需要引入ApplicationRef,然后在构造函数中注入,接着在所有数据发生改变的地方调用tick方法触发“脏值检查”  
import { Component, ApplicationRef } from '@angular/core';
constructor(private app: ApplicationRef) { }
this.app.tick();

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐