DOM封装记录

137 阅读3分钟

做一个简单的笔记 把思路写下来 未来忘了可以回来看看

目录

怎么封装

一、怎么封装

什么是封装

  • 把复杂的DOM代码,装到函数里,调用的时候用简单的代码就能实现其功能

f94be11f055dd61d1ea6abb27856cc1.png

什么是接口

  • 被封装的函数,暴露出来的功能给外部

bcd9b06b1395883bd8c07e5eceec084.png

什么是库

  • 把提供给他人用的工具代码叫做库

什么叫API

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

什么是框架

  • 当库变得很大,并且需要系统的学习才能看懂时,那么这个库就叫框架,比如Vue/react

怎么封装

  • 用命名空间的风格进行封装

  • window.dom是我们提供的全局对象

二、增

1、 dom.create(`<div>hi</div>`) 用于创建节点

dom.create = function (string) { //新建标签元素
    // return document.createElement(tagName); //这样不太复合使用要求
    const container = document.createElement('template') // 新HTML标签 可以容纳任何元素
    container.innerHTML = string.trim(); // trim函数 去掉字符串两边的空格 
    return container.content.firstChild; // 如果要显示td等元素 必须要这样拿才拿得到
};

2、 dom.after(node,node2) 用于新增弟弟元素

dom.after = function (node, node2) { //新增一个弟弟
    node.parentNode.insertBefore(node2, node.nextSibling) //在下一个元素的前面新增一个元素 因为DOM没有这个API,所以反人类式写法
}

3、dom.before(node,node2) 用于新增哥哥元素

dom.before = function (node, node2) { // 新增一个哥哥
    node.parentNode.insertBefore(node2, node) // 在node前面新增一个node2元素
}

4、dom.append(parent,child) 用于新增子元素

dom.append = function (parent, node) { // 新增一个儿子
    parent.appendChild(node) //给parent元素新增一个儿子
}

5、dom.wrap(`<div></div>`) 用于新增父元素

dom.wrap = function (node, parent) { // 给node元素新增一个父亲
    dom.before(node, parent) //先在node前面新增一个哥哥
    dom.append(parent, node) //把node元素移动到哥哥里面变成它的儿子
}

三、删

1、dom.remove(node) 用于删除节点

dom.remove = function (node) { // 删除这个元素
    node.parentNode.removeChild(node) // 选中node的父亲删除node
    return node //返回被删除的node
}

2、dom.empty(parent) 用于删除所有后代

dom.empty = function (node) { // 删除node的所有儿子
    // const childNodes = node.childNodes 简写成下面
    const {
        childNodes
    } = node //把node先装进一个变量,因为要遍历
    const array = []; // 声明一个空数组因为要返回
    /*for (let i = 0; i < childNodes.length; i++) { childNodes.length实时变换要用while循环
        dom.remove(childNodes[i]) 删除每一个遍历到的元素
        array.push(childNodes[i]) 把每个遍历到的元素添加到空数组里
    }*/
    let x = node.firstChild
    while (x) {
        array.push(dom.remove(node.firstChild)) // 删掉第一个儿子,然后把删除的结果添加到空数组
        x = node.firstChild // 删完后 第二个儿子变第一个儿子 我们把x再指向第一个儿子
    }
    return array //返回这个数组
}

四、改

1、dom.attr(node,'title',?) 用于读写属性

dom.attr = function (node, name, value) { //改或者读属性值 {重载}
    if (arguments.length === 3) {
        node.setAttribute(name, value) // arguments长度等于3 就代表想改
    } else if (arguments.length === 2) {
        return node.getAttribute(name) // arguments长度等于2 就代表想读,返回这个值就行
    }
}

2、dom.text(node,?) 用于读写文本内容

dom.text = function (node, string) { //改或查看文本内容 {适配}
    if (arguments.length === 2) {
        if ('innerText' in node) {
            node.innerText = string // ie 
        } else {
            node.textContent = string // firefox chrome
        }
    } else if (arguments.length === 1) {
        if ('innerText' in node) {
            return node.innerText
        } else {
            return node.textContent
        }
    }
}

3、dom.html(node,?) 用于读写HTML的内容

dom.html = function (node, string) { //改或查看HTML标签
    if (arguments.length === 2) {
        node.innerHTML = string
    } else if (arguments.length === 1) {
        return node.innerHTML
    }
}

4、dom.style(node,{color:'red'}) 修改标签的style

dom.style = function (node, name, value) { //添加或查看style属性
    if (arguments.length === 3) {
        // dom.style(div,'color','red')
        node.style[name] = value //把value赋值给name
    } 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,{name: 'value'})
            const object = name
            for (let key in object) { //遍历这个对象  
                // key:border / color
                // node.style.border = ...
                // node.style.color = ...
                node.style[key] = object[key] //把参数的属性值添加进去
            }
        }
    }
}

5、dom.class 对标签的class进行操作

dom.class = { // 添加删除查看类名
    add(node, className) { //add属性 添加类名
        node.classList.add(className)
    },
    remove(node, className) { // remove属性 删除类名
        node.classList.remove(className)
    },
    has(node, className) { // has属性 查看类名
        return node.classList.contains(className) // 记住要有返回值 不然就看了个寂寞
    }
}

6、dom.on(node,'click',fn) 用于添加事件监听

dom.on = function (node, eventName, fn) { //添加事件监听
    node.addEventListener(eventName, fn)
}

7、dom.off(node,'click',fn) 用于删除事件监听

dom.off = function (node, evertName, fn) { //删除事件监听
    node.removeEventListener(evertName, fn)
}

五、查

1、dom.find(选择器,范围) 用于获取标签,或标签们

dom.find = function (selector, scope) { //在一个范围通过选择器找它的儿子 
    return (scope || document).querySelectorAll(selector)
}

2、dom.parent(node) 用于获取标签的父元素

dom.parent = function (node) {
    return node.parentNode
}

3、dom.children(node) 用于获取子元素

dom.children = function (node) {
    return node.children
}

4、dom.sibling(node) 用于获取兄弟元素

dom.siblings = function (node) { // 获取兄弟元素
    return Array.from(node.parentNode.children).filter(n => n !== node) // 把获取到的父元素的子元素转化为真数组
    // 然后调用数组的filter属性筛选出不等于n的其他元素
}

5、dom.next(node) 用于获取弟弟元素

dom.next = function (node) { // 获取下一个兄弟元素
    let x = node.nextSibling
    while (x && x.nodeType === 3) { // 节点类型等于3 就是文本节点,如果x为文本节点就继续向下寻找直到找到下一个元素节点
        x = x.nextSibling
    }
    return x
}

6、dom.previous(node) 用于获取哥哥

dom.previous = function (node) { // 获取上一个哥哥元素
    let x = node.previousSibling
    while (x && x.nodeType === 3) { // 思路同上
        x = x.previousSibling
    }
    return x
}

7、dom.each(node,fn) 用于遍历所有节点

dom.each = function (nodeList, fn) { // 遍历一个元素的所有子元素
    for (let i = 0; i < nodeList.length; i++) { // for循环遍历
        fn.call(null, nodeList[i]) // 手写forEach 遍历每一个nodeList元素
    }
}

8、dom.index(node) 用于获取元素在父级元素中的排行

dom.index = function (node) { // 获取node在父元素中排行第几
    const list = dom.children(node.parentNode) // 因为直接用node父亲的所有儿子会导致不包含node 所以要用它父元素的所有儿子
    let i // 要把let写在for循环外面才能拿到i的值
    for (i = 0; i < list.length; i++) { // 遍历node元素的所有儿子
        if (list[i] === node) { // 找到自己就退出循环
            break
        }
    }
    return i // 
}