angular - 从一次手动添加markforcheck引发的思考

问题背景:点击地图标签时,不能一次性弹出详情框,通常要在第二次点击时才会弹出

 

 

 

解决方式:在地图点击singleclick回调事件中添加markForCheck(),触发手动变更

 

原因探究

通常在angular代码中,遇到数据不能立即刷新到ui得场景,我们会在代码中添加手动变更,使其强制刷新,但你是否真的了解其中得奥秘?

 

之前在性能优化的时候,我们给map组件设置了onpush的变更策略,这样可以大大减少map组件及其子组件的检测频率,在标签数很多的时候优化效果很明显;

需要说明的是:

如果一个组件设置了onpush,那么触发该组件能参与变更检测的情况有如下几种:

1、组件的输入引用发生改变(注意是输入属性的子属性改变是不会触发的)

2、组件内部有事件触发(click, change 等)(从zone.js源码看也是通过markForCheck来触发变更的

3、在组件及子组件代码中手动触发变更(markForCheck)

 

在上面的解决方案中,我们采用了第三种(markforcheck),但是你是否有疑惑,ol-map的singleclick事件貌似也是事件的一种,也属于组件内部有事件触发,也能让map组件参与到变更检测中。但结果却是为什么没有变更检测?

 

在这里,我们深挖一下ol-map的singleclick方法是如何触发的:

 

可以看到,当在地图上点击标签时(同时也触发了click事件,会向上冒泡调用所有的click注册方法),会延时250ms,采用dispatchEvent的方式(dispatchEvent也是ol自己实现的)触发名为singleclick的自定义事件(如果采用原生的dispatchEvent触发原生或自定义事件<zone.js定义了一套事件列表>,还是能够触发事件所在组件的检测的),然后再执行singleclick的回调;而ol自己实现了dispatchEvent,和原生的事件注册不是一套东西,所以就没有触发该组件变更检测;

 

所以,我们需要在singleclick的回调里加上markForCheck,这样本次的点击才能把数据刷新到ui上

posted @ 2024-10-29 10:58  天下无双之盛世奇观  阅读(31)  评论(0)    收藏  举报