【硬核写DOM库】--简单封装DOM

26 篇文章 0 订阅
10 篇文章 0 订阅

封装DOM – 硬核写DOM库

目录

  • 前言
  • 什么是封装
  • 术语
  • 常用功能自己手写DOM封装
  • 封装DOM的总结
  • 附上自己封装DOM库的github仓库

一、前言

【正文】

记住一个事实:原生DOM]很难用!,如果你觉得DOM很傻,不要怀疑自己,相信自己的直觉!API的函数名和属性真的是长的不得了,本来我自己想简单写个原生DOM的博客,没想到就花了我好几个小时的时间去码字,真的是吐了,而且容易被这些函数名给绕晕!好了,废话就到这里了,接下来让我们进入正题吧!


二、什么是封装

  • 举例

    一个电脑就是CPU、内存、硬盘、主板、显卡等的封装,用户只需要接触显示器、键盘、鼠标、触控板等设备,即可操作复杂的计算机。

  • 接口

    被封装的东西需要暴露出一些功能给外部,这些功能就是接口,如USB接口,HDMI接口等。设备只要支持这些接口,即可与被封装的东西进行信息交换。比如键盘、鼠标支持USB接口,显示器支持HDMI接口。

  • 两张图的对比就能说明一切!
    电脑封装
    我的库封装

三、术语

  • 我们把提供给其他人用的工具代码叫做库,如jQuery,Underscore等。

  • API:Application Programming Interface

    库暴露出来的函数或属性叫做API(应用编程接口)

  • 框架

    当你的库变的很大,并且需要学习才能看懂,那么这个库就加框架,比如Vue/React等。


四、硬核写DOM库

  1. 首先准备一个全局变量dom,直接将它挂载到window上

     windom.dom = {
       /* 待写的封装函数 */
     }
    
  2. 程序员的宿命:增删改查

    dom.create('<div> hi </div>') | dom.create('div'); --> 创建带有内容的节点或者单个元素
    
    dom.after(node,node2); --> 用于将node2添加在node之后
    
    dom.before(node,node2); --> 用于将node2插入到node前面
    
    dom.append(parent,child); --> 用于新增儿子
    
    dom.wrap(newParent); --> 用于新增爸爸
    

    实现后的代码:template能容纳所有的标签,即里面可以加入任何标签

    windom.dom = {
     /* 增 */
      create(string) {
        if (!(string.trim()[0] === "<")) {
          return document.createElement(string);
        } 
        else {
          const contaier = document.createElement("template");
          contaier.innerHTML = string.trim();
          return contaier.content.firstChild;
        }
      },
    
      after(node1, node2) {
        node1.parentNode.insertBefore(node2, node1.nextSibling);
      },
    
      before(node1, node2) {
        node1.parentNode.insertBefore(node2, node1);
      },
      }
    

  • dom.remove() | 用于删除节点
     dom.empty() | 用于删除所有后代
    
    实现后的代码:
    remove(node) {
     node.parentNode.removeChild(node);
     return node;
    },
    
    empty(node) {
     const arr = [];
     let x = node.firstChild;
     while (x) {
       arr.push(dom.remove(node.firstChild));
       x = node.firstChild;
     }
     return arr;
    },
    

  •      dom.attr(node,'title',?) | 用于读写属性
    
         dom.text(node,?) | 用于读写内容
    
         dom.html(node,?) | 用于读写HTML内容
    
         dom.style(node,{color:"red"}) | 用于修改style
    
         dom.class.add(node,'blue') | 用于添加类名
    
         dom.class.remove(node,'blue') | 用于删除class
    
         dom.on(node,'click',fn) |用于添加事件监听
    
         dom.off(node,'click',fn) | 用于删除事件监听
    

    实现后的代码

       attr(node, name, value) {
        if (arguments.length === 3) {
          node.setAttribute("data-" + name, value);
        } else if (arguments.length === 2) {
          return node.getAttribute(name);
        }
       },
    
        text(node, string) {
          /* 兼容写法 */
          if (arguments.length === 2) {
            if ("innerText" in node) {
              node.innerText = strng;
            } else {
              node.textContent = string;
            }
          } else if (arguments.length === 1) {
            if ("innerText" in node) {
              return node.innerText;
            } else {
              return node.textContent;
            }
          }
       },
    
        html(node, string) {
          if (arguments.length === 2) {
            node.innerHTML = string;
          } else if (arguments.length === 1) {
            return node.innerHTML;
          }
        },
    
        style(node, name) {
          if (name instanceof Object) {
            const obj = name;
            for (let k in obj) {
              node.style[k] = obj[k];
            }
          } else if (typeof name === String) {
            return node.style[name];
          }
        },
    
        class: {
          add(node, className) {
            node.classList.add(className);
          },
          remoce(node, className) {
            node.classList.remove(className);
          },
          has(node, className) {
            return node.classList.contains(className);
          },
        },
    
        on(node, eventName, fn) {
          node.addEventListener(eventName, fn);
        },
    
        off(node, eventName, fn) {
          node.removeEventListener(eventName, fn);
        },
    
  •   dom.find('选择器') | 用于获取标签或标签们
    
       dom.parent(node) | 用于获取父元素
    
       dom.children(node) | 用于获取子元素
    
       dom.siblings(node) | 用于获取兄弟姐妹元素
    
       dom.next(node) | 用于获取下一个弟弟元素
    
       dom.previous(node) | 用于获取上一个哥哥元素
    
       dom.each(nodes,fn) | 用于遍历所有节点
    
       dom.index(node) | 用于获取排行老几
    

    实现后的代码

    find(string, scope) {
       return (scope || document).querySelectorAll(string);
     },
    
     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() {
       let x = node.previousSibling;
       while (x && x.nodeType === 3) {
         x = x.previousSibling;
       }
       return x;
     },
    
     each(nodeList, fn) {
       for (let i = 0; i < nodeList.length; i++) {
         fn.call(null, nodeList[i]);
       }
     },
    
     index(node) {
       console.log(node.parentNode);
       const list = dom.children(node.parentNode);
       for (let i = 0; i < list.length; i++) {
         if (list[i] === node) {
           return i + 1;
         }
       }
     },
    

五、总结

这是我第一次尝试去封装DOM,尝试将一些难用或者函数名很长的原生DOM封装成简单的、函数名短的简单API。从以上的函数封装来说。无疑是受益匪浅的,不仅能从中理清思维逻辑,还能进一步了解框架的一些封装技巧。下一次我将会总结一些关于jQuery的封装技巧,这些技巧让我重新认识到编程。

这是我的github链接–手写的DOM的源代码,欢迎讨论交流😁

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值