《封装DOM库》

384 阅读3分钟

一. 增

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