前端探索 | DOM封装(对象风格)

HTML

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>DOM 1</title>
    <style>
        .red{
            background: red;
        }
    </style>
</head>
<body>
示例
<div>
    <div id="test">test</div>
</div>
<div id="empty">
    <div id="e1"></div>
    <div id="e2"></div>
    <div id="e3"></div>
</div>
<div id="travel">
    <div id="t1"></div>
    <div id="t2"></div>
    <div id="t3"></div>
</div>
<script src="dom.js"></script>
<script src="main.js"></script>

</body>
</html>

DOM.js

window.dom = {
    create(string) { //用来创建新节点
        const container = document.createElement("template")
        container.innerHTML = string.trim()//trim用来防止空格,导致抓取的children是text
        return container.content.firstChild//template的元素要这样拿到
    },
    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)  //再将节点变成新增节点的儿子
    },
    remove(node) {  //用来删除节点
        node.parentNode.removeChild(node)//IE兼容,node.remove() IE可能不支持
        return node
    },
    empty(node) {  //删除父级的所有子节点,node.innerHTML='',但是为了保留引用,以下
        //const {childNodes} = node  //const childNodes = node.childNodes
        const array = []
        let x = node.firstChild
        while (x) {
            array.push(dom.remove(node.firstChild))  //等同于下面的缩写
            x = node.firstChild
        }
        //for (let i = 0; i < childNodes.length; i++) { 由于childNodes.length一直在改变所以不可
        //dom.remove(childNodes[i])
        //array.push(childNodes[i])
    },
    //attr(node,name,value){  //改title
    //node.setAttribute(name,value)
    //}
    attr(node, name, value) {  //用重载,读写title
        if (arguments.length === 3) {
            node.setAttribute(name, value)
        } else if (arguments.length === 2) {
            return node.getAttribute(name)
        }
    },
    //text(node, string) {  //用于读写文本内容
    //node.innerText = string //用于IE
    //}
    text(node, string) {  //用重载和适配,读写文本内容
        if (arguments.length === 2) {
            if ('innerText' in node) {
                node.innerText = string
            } else {
                node.textContent = string
            }
        } else if (arguments === 1) {
            if ('innerText' in node) {
                return node.innerText
            } else {
                return node.textContent
            }
        }
    },
    html(node, string) {  //读写html
        if (arguments.length === 2) {
            node.innerHTML = string
        } else if (arguments.length === 1) {
            return node.innerHTML
        }
    },
    //style(node, object) {  //修改style
    //for (let key in object) {
    //node.style[key] = object[key]
    //}
    //}
    style(node, name, value) {  //读写style
        if (arguments.length === 3) {
            //可能的形式dom.style(div, 'color', 'red')是为修改style
            node.style[name] = value
        } else if (arguments.length === 2) {
            //dom.style(div, 'color')是为查询
            if (typeof name === 'string') {
                return node.style[name]
            } else if (name instanceof Object) {
                //dom.style(div, {color: 'red'})
                for (let key in name) {
                    node.style[key] = name[key]
                }
            }
        }
    },
    class: {  //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)
    },
    find(selector, scope) {  //获取标签(们)
        return (scope || document).querySelectorAll(selector)
    },
    parent(node) {  //用于获取父元素
        return node.parentNode
    },
    children(node) {  //获取子元素
        return node.children
    },
    siblings(node) {  //查找兄弟姐妹,不包括自己
        Array.from(node.parentNode.children).filter(n => n !== node)//需要变成数组才能filter
    },
    next(node) {  //找到弟弟
        let x = node.nextSibling
        while (x && x.nodeType === 3) {  //由于会找到text所以要跳过
            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
    }


};

main.js

const div = dom.create("<div>newDiv</div>")
console.log(div)
dom.after(test, div)

const div3 = dom.create('<div id="parent"></div>')
dom.wrap(test, div3)

const nodes = dom.empty(window.empty)
console.log(nodes)

//dom.attr(test, 'title', 'Hi, I am YDZ') //改写title

const title = dom.attr(test, 'title')  //用来读title
console.log(`title: ${title}`)

dom.text(test, 'hello, this is the new content')//修改文本内容
dom.text(test)//读取文本

dom.style(test, {border: '1px solid red', color: 'blue'})//添加样式
dom.style(test, 'border')
dom.style(test, 'border', '1px solid red')

dom.class.add(test, 'red')

dom.on(test, 'click', () => {
    console.log('点击了')
})

const testDiv = dom.find('#test')[0]
console.log(testDiv)

console.log(dom.parent(test))

const t= dom.find('#travel')[0]
dom.each(dom.children(t),(n)=>dom.style(n,'color','red'))//遍历并且加颜色
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容