原生JS事件委托的应用
大晚上,等方案,年底了,顺便传一篇总结,主要是第三部分,事件委托的应用。
一、fragment的使用
- 元素增加或者刷新后,能否被原addeventLister监听到--> 不能;
appengChild只能添加Dom元素,不能是文本形式的Dom;fragment不能直接通过innerHtml添加内容;
var body = document.getElementById('body');
var fragment = document.createDocumentFragment();
for (var i = 0; i < 100; i++) {
var btn = document.createElement('button');
btn.id = i;
btn.className = 'btn';
btn.type = 'button';
btn.innerText = '按钮'
fragment.appendChild(btn);
}
body.appendChild(fragment);
二、事件委托提升性能或者优化代码结构
- 给body或者Ul等父元素绑定click事件,实现事件的委托 ,比为每一个button绑定点击事件性能更加提升,也为新增元素后的,不再需要额外绑定监听事件,注意需要配合matches等api使用更佳。nice!
var date2 = new Date();
body.addEventListener('click', function(e) {
var element = e.target;
if (element.className == 'btn') {
console.log(element.id);
}
})
var date3 = new Date();
三、具体应用
一、场景
- 因为最近在做web的客服项目中,对话列表会不断接入新的客户,如果每接入一个客户就生成一个li,进行一个新的监听,代码结构就特别不好,所以通过事件委托,来抽离函数工作,极大的优化了代码结构;
- 需要在对话列表里边的每一个Li元素里边的一些小div做一些功能,需要用到对话列表上的特定数据,不如将这些数据全部绑定到li元素上,每次内部div的交互动作,都冒泡到父元素Li上,来获取所需要的数据;
二、简单的函数封装
/**
* @description: 事件委托
* @parentFeature 父节点内监听
* @currentFeature 目标节点的特征
* @path e.paht
* @return: boolean
*/
function delegation(parentFeature, targetFeature, path) {
for (var i = 0, length = path.length; i < length; i++) {
var item = path[i];
if (!item.nodeName) {
// 当节点为document或者window的时候,nodeName为undefined
return false
}
if (item.matches(targetFeature)) {
// 当paht链上节点符合目标特征
console.log(item)
return true
}
if (item.matches(parentFeature)) {
// 往上找到了监听的父节点
return false
}
}
}
/**
* @description: 获取元素上的状态消息
* @infoTargetFeature: 所要获取消息上的元素
* @infoName: 所需要获取的父元素的属性名
* @return: 状态信息
*/
// 事件委托成功,并且继续寻找,获取li元素上的数据
function getLiInfo(parentFeature, targetFeature, path, infoTargetFeature, infoName) {
for (var i = 0, length = path.length; i < length; i++) {
var item = path[i];
if (!item.nodeName || item.nodeName=="#document") {
// 当节点为document或者window的时候,nodeName为undefined
return false
}
// console.log(JSON.stringify(item)) //{} 空对象
if (item.matches(targetFeature)) {
// 当path链上节点符合目标特征
var maxLength = 10;
var parentEle = item.parentNode;
var info = true
for (var i = 0; i < maxLength; i++) {
// 当往上寻找父元素,直到找到设定父元素的所需要的状态信息,并返回
if (parentEle.matches(infoTargetFeature)) {
console.log(parentEle.dataset)
info = parentEle.dataset[infoName];
console.log(info)
return info
}
parentEle = parentEle.parentNode
}
return true
}
if (item.matches(parentFeature)) {
// 往上找到了监听的父节点
return false
}
}
}