一. 增
-
dom.create 函数,创建节点
dom.create('<div><span>1</span></div>')在字符串里直接写一段html内容,怎么实现?window.dom={ create(string){ const container=document.createElement('div')//自己创建一个div容器 container.innerHTML=string //往容器标签里插入HTML内容 return container.children[0] } }有一个bug,如果
dom.create('<tr><td>1</td></tr>'),得到结果是undefined,因为我在函数里创建的是div容器,tr标签只能在table里。解决办法:把div换成template标签,template可以容纳任何元素。
create(string){ const container=document.createElement('template') container.innerHTML=string.trim() //把字符串两边的空格删掉 return container.content.firstChild //template元素的子代写法 } -
dom.after 函数,加弟弟
dom.after(test,span)在一个标签后插入另一个标签after(node, node2) { node.parentNode.insertBefore(node2, node.nextSibling); } -
dom.before ,加哥哥
dom.before(test,span)在test前边插before(node, node2) { node.parentNode.insertBefore(node2, node); } -
dom.append,加儿子
append(parent, new_node) { parent.appendChild(new_node); } -
dom.wrap,加爸爸
wrap(node, new_parent) { dom.before(node, new_parent); dom.append(new_parent, node); }
二. 删
- dom.remove,删除节点
remove(node) { node.parentNode.removeChild(node); return node; //并且返回这个节点的引用 } - dom.empty,清空节点的所有孩子
node.children 和node.childNodes,返回的数组长度会实时变化,所以不能用数组下标i的for循环来删除节点。empty(node) { //const children = node.childNodes; //const { childNodes } = node; const array = []; let x = node.firstChild; while (x) { array.push(dom.remove(x)); x = node.firstChild; } return array; } //删掉一个节点的所有孩子
三. 改
- dom.attr,读写一个节点的属性
根据参数的个数,实现不同的效果,叫重载。attr(node, name, value) { //函数重载 if (arguments.length === 3) { //如果传三个实参,写属性 node.setAttribute(name, value); } else if (arguments.length === 2) { //传前两个实参,读属性值 return node.getAttribute(name); } } - dom.text,读,写文本内容
innerText是ie的,textContent是firefox/chrome的,大部分浏览器两者都支持,少数旧的ie只支持innerText。所以可以做一下判断。这种函数的写法叫适配。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; } } } - dom.html,读,写html内容
html(node, string) { //重载 if (arguments.length === 2) { node.innerHTML = string; } else if (arguments.length === 1) { return node.innerHTML; } } - dom.style,修改/读样式
style(node, name, value) { if (arguments.length === 3) { //dom.style(div,'color','red')传三个参数的写样式 node.style[name] = value; } else if (arguments.length === 2) { if (typeof name === "string") { //dom.style(div,'color')传两个参数的读样式 return node.style[name]; } else if (name instanceof Object) { //dom.style(div,{color:'red',border:''})传对象的写样式 for (let key in name) { node.style[key] = name[key]; } } } } - dom.class.add/remove/has,增加/删除类,判断某元素是否有有个类
class: { add(node, className) { node.classList.add(className); }, remove(node, className) { node.classList.remove(className); }, has(node, className) { return node.classList.contains(className); } } - dom.on/off,添加/删除一个事件监听
on(node, eventName, fn) { node.addEventListener(eventName, fn); }, off(node, eventName, fn) { node.removeEventListener(eventName, fn); }let fn = () => { console.log("我点击了"); }; dom.on(test, "click", fn); dom.off(test, "click", fn);
四. 查
-
dom.find,获取标签或者标签们
find(selector, scale) { return (scale || document).querySelectorAll(selector); }dom.find('#test')传一个选择器作为参数,会返回所有的标签,以数组形式。所以要想获取这个标签本身dom.find('#test')[0]dom.find('.red',div1)传两个参数,如果我想找的.red标签同时存在在两个不同的标签中,我只要div1里的那个.red -
dom.siblings,找兄弟姐妹(排除自己)
siblings(node) { return Array.from(node.parentNode.children).filter(n => n !== node); } //children是伪数组 -
dom.travel,遍历所有孩子
travel(childrenList, fn) { for (let i = 0; i < childrenList.length; i++) { fn(childrenList[i]); } } -
dom.index,返回节点排行老几
index(node) { let list = node.parentNode.children; //找爸爸,让爸爸找所有孩子 let i = 0; for (i = 0; i < list.length; i++) { if (list[i] === node) { break; } } return i; }