JS全解(七)手动封装DOM库(对象风格)

301 阅读2分钟

重要知识点:每节博客都会重复🙉🙉🙉

口诀🤨:四基两空一对象,还有五个falsy值。

七种数据类型

  • number string bool symbol
  • null undefined
  • object

五个 falsy 值

  • null undefined
  • 0 NaN
  • '' (空字符串)

先了解一波专业术语:

我们把提供给其他人用的工具代码叫做库,比如 jQueryUnderscore

API

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

API (web 或 XML 页面) = DOM + JS (脚本语言)

框架

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

程界的术语大部分都很随便,没有固定的解释,所以意会即可~

那什么是DOM呢?

文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。

手写了一个基础的DOM库,涉及了基本的增删改查:

增 代码如下

window.dom = {
    // ****************** 增
    create(string) {
        const container = document.createElement("template")
        container.innerHTML = string.trim()
        return container.content.firstChild
    },
    after(node, node2) {
        node.parentNode.insertBefore(node2, node.nextSibling)
    },
    before(node, node2) {
        node.parentNode.insertBefore(node2, node)
    },
    append(parent, node) {
        parent.appendChild(node)
    },
    wrap(node, parent) {
        dom.before(node, parent)
        dom.append(parent, node)
    }
}

删 代码如下

window.dom = {
        // ****************** 删
    remove(node) {
        const { childNodes } = node
        const array = []
        for (let i = 0; i < childNodes.length; i++) {
            dom.remove(childNodes[i])
            array.push(childNodes[i])
        }
        return array
    },
    empty(node) {
        const array = []
        let x = node.firstChild
        while (x) {
            array.push(dom.remove(node.firstChild))
            x = node.firstChild
        }
        return array
    }
}

改 代码如下

window.dom = {
    // ****************** 改
        attr(node, name, value) { //重载
        if (arguments.length === 3) {
            node.setAttribute(name, value)
        } else if (arguments.length === 2) {
            return node.getAttribute(name)
        }
    },
    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
            }
        }
    },
    html(node, string) { //重载
        if (arguments.length === 2) {
            node.innerHTML = string
        }
        if (arguments.length === 1) {
            return node.innerHTML
        }
    },
    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'})
                const object = name
                for (let key in object) {
                    node.style[key] = object[key]
                }
            }
        }
    },
    class: {
        add(node, className) {
            node.classList.add(className)
        },
        remove(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)
    }
}

查 代码如下

window.dom = {
    // ****************** 查
        find(selector, scope) {
        return (scope || document).querySelectorAll(selector)
    },
    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(node){
    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) { //知道一个元素排行第几
        const list = dom.children(node.parentNode)
        let i
        for (i = 0; i < list.length; i++){
            if (list[i] === node) {
                break
            }
        }
        return i
    }
}

手写DOM库链接

由于本人水平有限,如有描述不准确的地方请给我留言,欢迎交流~