DOM库封装

138 阅读2分钟

一. 增

1.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元素的子代写法
}

2.dom.after 函数,加弟弟

dom.after(test,span) 在一个标签后插入另一个标签

after(node, node2) {
    node.parentNode.insertBefore(node2, node.nextSibling);
}

3.dom.before ,加哥哥

dom.before(test,span) 在test前边插

before(node, node2) {
    node.parentNode.insertBefore(node2, node);
}

4.dom.append,加儿子

append(parent, new_node) {
    parent.appendChild(new_node);
}

5.dom.wrap,加爸爸

wrap(node, new_parent) {
    dom.before(node, new_parent);
    dom.append(new_parent, node);
}

二. 删

1.dom.remove,删除节点

remove(node) {
    node.parentNode.removeChild(node);
    return node;   //并且返回这个节点的引用
}

2.dom.empty,清空节点的所有孩子

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;
} //删掉一个节点的所有孩子

node.children 和node.childNodes,返回的数组长度会实时变化,所以不能用数组下标i的for循环来删除节点。

三. 改

1.dom.attr,读写一个节点的属性

attr(node, name, value) {  //函数重载
    if (arguments.length === 3) {  //如果传三个实参,写属性
      node.setAttribute(name, value);
    } else if (arguments.length === 2) {  //传前两个实参,读属性值
      return node.getAttribute(name);
    }
}

根据参数的个数,实现不同的效果,叫重载

2.dom.text,读,写文本内容

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;
          }
    }
}

innerText是ie的,textContent是firefox/chrome的,大部分浏览器两者都支持,少数旧的ie只支持innerText。所以可以做一下判断。这种函数的写法叫适配。

3.dom.html,读,写html内容

html(node, string) {   //重载
    if (arguments.length === 2) {
      node.innerHTML = string;
    } else if (arguments.length === 1) {
      return node.innerHTML;
    }
}

4.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];
        }
      }
    }
}

5.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);
    }
}

6.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);

四. 查

1.dom.find,获取标签或者标签们

find(selector, scale) {
    return (scale || document).querySelectorAll(selector);
}

dom.find('#test')传一个选择器作为参数,会返回所有的标签,以数组形式。所以要想获取这个标签本身dom.find('#test')[0] dom.find('.red',div1)传两个参数,如果我想找的.red标签同时存在在两个不同的标签中,我只要div1里的那个.red

2.dom.siblings,找兄弟姐妹(排除自己)

siblings(node) {
    return Array.from(node.parentNode.children).filter(n => n !== node);
}               //children是伪数组

3.dom.travel,遍历所有孩子

travel(childrenList, fn) {
    for (let i = 0; i < childrenList.length; i++) {
      fn(childrenList[i]);
    }
}

4.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;
}