这周用vue+vue-router+vuex+axios+video.js做了一个与文档和视频素材有关的一个项目,其中很多内容以列表形式呈现,如果列表中每个单元都单独绑定事件,会浪费性能;作为一个完美主义者是不能容忍的,我想用事件委托来进行优化.
事件委托是利用冒泡的原理,委托外层父元素对子元素进行事件托管,但是有个问题,怎么区分谁是大毛谁是二毛呢?如果结构层次较多,又怎么区分谁是大毛的儿子大大毛,谁是小毛的儿子小小毛呢?首先我想到data-*属性,不过兼容性不大好,在IE上表现惨不忍睹.其次想到name属性,但name属性并不是所有元素都具有的,这个方案也不行.我又想到第三种方案,就是利用class对子元素进行区分和传参.不啰嗦了,上代码.
<div @click="doSomething" class="parent"> <div :key="'child'+index" v-for="(item,index) in list" class="child" :class="[aindex==index?'active':'',' '+index]"> <div :key="'gchild'+index" v-for="(item,index) in item" class="grandchild" :class="[bindex==index?'active':'','aclass'+item.class,'bclass'+index]>{{item.name}}</div> </div> </div> </div>doSomething(e){ let paths=e.srcElement.path||util.eventPath(e); for (let i=0;i<paths.length;i++){ let item=paths[i]; if(/child/.test(item.className)){ ... break; }else if(/gchild/.test(item.className)){ ... break; } } }eventPath方法是为了兼容IE9封装的冒泡路径,代码也贴上.
eventPath: function (evt) { const path = (evt.composedPath && evt.composedPath()) || evt.path, target = evt.target; if (path != null) { return (path.indexOf(window) < 0) ? path.concat(window) : path; } if (target === window) { return [window]; } function getParents(node, memo) { memo = memo || []; const parentNode = node.parentNode; if (!parentNode) { return memo; } else { return getParents(parentNode, memo.concat(parentNode)); } } return [target].concat(getParents(target), window); }接下来截取参数的任务就交给正则了.