4-17 脏值检测(3)
那么有没有一种情况,就是真的需要在ngAfterViewChecked里面赋值?
我们需要导入ngZone。这是Zone.js这个第三方的类库提供的
Zone是浏览器的js运行时,我们会在浏览器中划分N个区域,每个区域运行自己的程序,彼此相互不干扰。这样的话,angular本身运行在一个angular的zone中,那么如果我们可以把这个值让angular这个zone不知道,也就是运行在angular的Zone之外。那么这个脏值监测就监测不到这个值的改变。那么我们就可以把脏值监测绕过去。
在angular之外运行title复制的这句话。当然光这么写还不行。
angular检查的是title这个属性,是一个同步操作。下面一旦改变了之后,还是会监测到。要让title这个属性返回的值是不变的
那么我们就需要异步的,异步的去改变这个值,
这样它同步的去找tilte()这个值,检查的时候其实这个值是不变的。因为下面是异步操作去改变它的值。同步检查是在前面,所以他检查两遍得到的值 都是同一个值。
这样浏览器上 异常就没了
那么什么具体的场景会触发这样一个需求呢?
比如说我们现在想做一个倒计时,比如我们这里做一个管道。
这样就会报错,因为每次检查,这个值都是不一样的。因为这个值我第一次检查的时候是一个值,第二次检查的时候,这个值就变了。
做一个变量time
缺一个触发的事件。添加触发脏值监测的方法
函数先什么都不做
点一下时间出来了。触发了脏值监测。
再点一次又触发
我们持续性的变化是在angular之外做的
倒计时
想让时间持续性的变化,这种情况下直接操作dom会效率高一些。因为绑定它不是没有代价的。代价就是脏值监测的形式监测值的改变。然后去更新这个html
用#来做一个引用。
用ViewChild去引用timeRef这个模块。它的类型是一个静态类型。没有在ngIf或者是ngFor当中。
类型是ElementRef
一直在变化。而且这样不会引发脏值监测。也不会有性能的一些损失。
这样直接的操作dom是有一定的问题的。再注入Render2
ts类里面使用管道
在angular6之上的版本
fformatDate函数其实就是管道的变化函数。
实时变化
下一节
在组件的装饰器里面,
这样设置以后,它就只看装饰器的属性,这些属性变了,就会隐藏脏值监测。这样就成了一个纯粹性的木偶组件,或者叫做笨组件。
这里也加上
这样这三个组件,只有在他们自己的input属性改变的时候 才会引发脏值监测。而且它引发的是他们这一个分支的,我们不会跑整个的树,只会跑这一个分支的树。所以它范围就会小很多。
以上几个配置改变后,对我们的程序并没有什么影响
如果我们也让他变成onPush的
先到男装,再切回来 ,切不回来了
路径参数的变化,在默认的路由策略之下,不会销毁这个组件,它是重用这个组件。
所以这个ngOnInit只走了一遍。
当然只走一遍,其实问题也并不大,因为在这里面,我们是订阅了这个参数的变化,在这里去赋值的。异步的方法去赋值的。
但是现在变成了 change on Push
由于这里并没有input类型的参数。
所以这个变化被忽略掉了,系统并没有监测到它
处理
那么这种情况下我们如何处理呢?需要一些手动的技巧。
注入
这个时候再切换就没有问题了。
这是一个常用的小技巧。
结束