原生的Dom操作api设计的过于反人性, 所以我想自己重新封装一下
20.1 增加节点
-
创建节点:
create(string){ const container = document.createElement("template") container.innerHTML = string.trim(); return container.content.firstChild; }注意: 为什么使用template标签,而不是用常用的div标签呢? 因为div作为容器不能容纳td标签, 也就无法生成相应节点. 只有template能容纳所有标签,并且生成节点
-
添加节点:
//增加右节点 after(node, node2){ node.parentElement.insertBefore(node2, node.nextSibling) }, //增加左节点 before(node, node2){ node.parentElement.insertBefore(node2, node) }, //增加孩子节点 append(parent, child){ parent.appendChild(child) }, //用父节点进行包裹 wrap(node, parentNode){ dom.before(node, parentNode) dom.append(parentNode, node) },
20.2 删除节点
-
删除当前节点:
remove(node){ return node.parentElement.removeChild(node) }, -
清空所有孩子节点:
empty(parent) { const array = [] while (parent.firstChild){ array.push(parent.firstChild) parent.removeChild(parent.firstChild) } return array },
20.3 修改节点
-
修改节点属性
attr(node, name, value){ if(arguments.length === 3){ node.setAttribute(name, value) }else if(arguments.length === 2){ return node.getAttribute(name) } },注意:
if(arguments.length === 3)这个if语句是为了实现函数重载. 3个参数就是修改属性, 2个参数就是查询属性 -
修改节点文字
text(node, string){ if(arguments.length === 2){ if(`innerText` in node){ node.innerText = string }else{ node.textContent = string } }else if(arguments.length === 1){ if(`innerText` in node){ return node.innerText }else{ return node.textContent } } },注意:
if("innerText" in node)这个if语句是为了实现兼容所有浏览器,innerText是微软设计的,textContent是W3C标准 -
修改html元素
html(node, string){ if(arguments.length === 2){ node.innerHTML = string }else if(arguments.length === 1){ return node.innerHTML } }, -
修改style
style(node, name, value){ if(arguments.length === 3){ node.style[name] = value }else if(arguments.length === 2){ if(typeof name === `string`){ return node.style[name] }else if(name instanceof Object){ const object = name for(let key in object){ node.style[key] = object[key] } } } },**注意:**这里的
node.style[name]只能用中括号, 不能用.. 因为这里的name是一个变量, 而不是"name"字符串. 这里的
else if(name instanceof Object): 为了兼容一次性修改多个值, 所以传进来对象 -
修改属性class
class:{ add(node, className){ node.classList.add(className) }, remove(node, className){ node.classList.remove(className) }, has(node, className){ return node.classList.contains(className) } },
20.4 查找节点
-
设定范围查找节点
find(selector, scope){ return (scope || document).querySelectorAll(selector) }, -
查找自己的父节点.
parent(node){ return node.parentNode }, -
查找自己的孩子节点.
children(node){ return node.children }, -
查找自己同辈节点.
siblings(node){ return Array.from(node.parentNode.children).filter(n=>n!==node) }, -
查找自己的弟弟, 哥哥.
next(node){ let x = node.nextSibling while(x && x.nodeType === 3){ x = x.nextSibling } return x }, previous(node){ let x = node.previousSibling while(x && x.nodeType === 3){ x = x.previousSibling } return x },注意:
while(x && x.nodeType === 3)这个判断的原因: 因为要把类似于回车, 空格之类的文本元素过滤掉 -
查找索引:
//重写each函数 each(nodeList, fn){ for(let i=0;i<nodeList.length;i++){ fn.call(null, nodeList[i]) } }, index(node){ const list = dom.children(node.parentNode) let i for(i=0;i<list.length;i++){ if(list[i] === node){ break } } return i }
20.5 事件的增加和删除
on(node, eventName, fn){
node.addEventListener(eventName, fn)
},
of(node, eventName, fn){
node.removeEventListener(eventName, fn)
},