iView的Select组件的性能优化本公司的组件库是在iView早期版本的基础上修改而成,仅供内部使用,所以在使用过程中会用到有一些问题。接下来,本文将对比Select组件的性能优化。Debounce函数我们先回顾一下debounce函数的使用场景:在前端页面,我们会遇到一些频繁触发的事件;比如鼠标移动的mousemove事件;窗口对象的调整大小和滚动事件;按键、按键事件;实际使用过程中,这种情况下,我们可能不需要每次触发事件都响应,我们往往需要在用户停止操作几毫秒后才响应事件。这时候我们就需要用到debounce功能了。下面是一个去抖函数exportfunctiondebounce(fn){letwaiting;返回函数(){如果(等待)返回;等待=真;constcontext=this,args=参数;constlater=function(){waiting=false;fn.apply(上下文,参数);};这个.$nextTick(稍后);};}这段代码的意思是在DOM更新时响应这个事件,DOM更新后只会执行一次。有了这些知识准备,我们就来说说使用这个组件遇到的性能问题。低版本iviewSelect组件遇到的问题在使用低版本组件的过程中,当数据量较大时,比如一个select选择器中有500条以上的数据,模糊搜索可能会卡死页面并且关闭页面有延迟。出现这个问题的原因在Select组件的mountedhook中有三个监听,分别是组件的添加、删除和选中时的事件监听。在监听事件中,会遍历Select中的所有子组件,做出相应的改变。//监听子组件的移除this.$on('remove',()=>{if(!this.remote){this.modelToQuery();this.$nextTick(()=>this.broadcastQuery(''));}else{this.findChild((child)=>{child.updateSearchLabel();//#1865child.selected=this.multiple?this.model.indexOf(child.value)>-1:this.model===child.value;});}this.slotChange();this.updateOptions(true);})找到这个监听器的通知对象,发现是Select的子组件通知父组件的时候它被销毁或创建相应地进行更改。//组件销毁时通知父组件beforeDestroy(){this.dispatch('iSelect','remove');this.$off('on-select-close',this.onSelectClose);this.$off('on-query-change',this.onQueryChange);}那么问题就出在这里了。当子组件数量较多时,将每个组件移除,需要遍历一次父组件。这会拖累性能。解决方案既然前面提到了debounce功能,大家应该想到怎么解决了。使用debounce功能可以解决这个问题,我们只需要在所有子组件销毁时通知一次父组件即可。引入debounce功能后,我测试基本解决了卡顿卡顿的问题。代码如下。//在select组件的mounted函数中,监听append和remove事件this.$on('append',this.debouncedAppendRemove());this.$on('remove',this.debouncedAppendRemove());//引入去抖函数debouncedAppendRemove(){returndebounce(function(){if(!this.remote){this.modelToQuery();this.$nextTick(()=>this.broadcastQuery(''));}else{this.findChild((child)=>{child.updateSearchLabel();//#1865child.selected=this.multiple?this.model.indexOf(child.value)>-1:this.model===child.value;});}this.slotChange();this.updateOptions(true);});}其他细节子组件的监听事件低版本没有去掉,高版本去掉了。mounted(){this.$on('on-select-close',this.onSelectClose);this.$on('on-query-change',this.onQueryChange);}beforeDestroy(){this.$off('on-select-close',this.onSelectClose);this.$off('on-query-change',this.onQueryChange);}
