37-【js编程接口】自己封装DOM库

这是自己封装的一个简单的DOM操作API,具有以下功能:

调用时,请采用dom.option来进行操作,如:dom.create(‘div’)

  • 封装DOM:像笔记本这样把功能封装起来用户通过接口便可操作
  • 接口API:被封装的东西要暴露一些功能、属性、或者函数与外部,就是接口
  • 封装自己的库:呈现create,get接口,支持直接调用函数
  • 库:提供给别人的工具代码,里面主要是一些函数
  • 框架:一些特别大的库 需要学习

封装前的准备:demo-1,index.html、main.js、dom.js

window.dom{}提供全局对象

用于创造节点 dom.create('<div>hi</div>')
用于新增弟弟 dom.after(node,node2)
用于新增哥哥 dom.before(node,node2)
用于新增儿子 dom.append(parent,child)
用于新增爸爸 dom.wrap(node,parent)
1.创建div

向dom里添加函数create(){} ,在main.js里dom.create()调用

window.dom = {
    create(tagName) {
        return document.createElement(tagName);
    }
}

let div = dom.create('div');
console.log(div);

创建div里包含span

设置内容为string,返回孩子的第一个

但是不能创建tr、td,由于容器也是div,td只能在thead、tbody里

create(string) {
        const container = document.createElement('div')
        container.innerHTML = string
        return container.children[0]
}
    
let div = dom.create('<div><span>2</span></div>');
console.log(div);

template

  • 是可以放任意元素不出错的
  • string.trim()把字符串两边空格去掉,防止返回的firstchild为空格文本
  • container.content.firstChild返回值
    create(string) {
        const container = document.createElement('template')
        container.innerHTML = string.trim();
        return container.content.firstChild;
    }

let div = dom.create('<tr><td>2</td></tr>');
console.log(div);
2.新增弟弟 after(node, node2)
after(node, node2) {
    //把node2插入到node的下一个节点的前面
        node.parentNode.insertBefore(node2, node.nextSibling);
    }


let div = dom.create('<div>newDIV</div>');
console.log(div);
dom.after(test, div)

当test没有下一个节点,无空格无回车,Format on save,打出下一个节点为空

<div><div id="test">哈哈</div></div>
    
after(node, node2) {
    console.log(node.nextSibling)
    node.parentNode.insertBefore(node2, node.nextSibling);
}

<div>newDIV</div>
null
3.新增哥哥 before(node, node2)
before(node, node2) {
    node.parentNode.insertBefore(node2, node);
}

let div = dom.create('<div>newDIV</div>');
console.log(div);
dom.before(test, div)
4.新增孩子 append(parent, node)
append(parent, node) {
    parent.appendChild(node);
}

let div = dom.create('<div>newDIV</div>');
console.log(div);
dom.append(test, div)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Il3VFEcr-1588503183644)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200502221105530.png)]

5.新增父亲 wrap(node, parent)
//用parent包住node
wrap(node, parent) {
    //把parent放在node上面,即哥哥
    dom.before(node, parent)
    //把node添加到添加到parent的下面
    dom.append(parent, node)
}

let div = dom.create('<div>newDIV</div>');
console.log(div);
dom.wrap(test, div)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PMjM6gg-1588503183649)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200502221742888.png)]

6.删除节点 dom.remove(node)

return node 返回方便引用

remove(node) {
    node.parentNode.removeChild(node);
    return node
}

dom.remove(test)
7.删除全部子节点 要遍历 dom.empty(node)

包括空格文本子节点

//错误,由于在遍历时length在变化 
    empty(node) {
        //node.innerHTML = ''
        const {childNodes} = node
        const arr = []
        for (let i = 0; i < childNodes.length; i++) {
            dom.remove(childNodes[i])
            arr.push(childNodes[i])
        }
        //有时需要返回
        return arr
    }

const childNodes=node.childNodes等价于const { childNodes } = node

正确方法:while循环

    empty(node) {
        //node.innerHTML = ''
        //const childNodes=node.childNodes
        const {
            childNodes
        } = node
        const arr = []
        let x = node.firstChild
        while (node.firstChild) {
            arr.push(dom.remove(x))
            x = node.firstChild
        }
        return arr
    }
    
  dom.empty(empty)  
  
<div id=empty>
    <div>1</div>
    <div>2</div>
    <div>3</div>
</div>

8.读写属性 dom.attr(node,‘title’,?)
<div id="test" title="I am Frank">哈哈</div>

attr(node, name, value) {
    node.setAttribute(name, value)
}

dom.attr(test, 'title', 'I am Frank')

当长度为3时,用setAttribute写属性,长度为2时,用getAttribute读属性值

attr(node, name, value) { //重载
    if (arguments.length === 3) {
        node.setAttribute(name, value)
    } else if (arguments.length === 2) {
        return node.getAttribute(name)
    }
}

dom.attr(test, 'title', 'I am Frank')
const title = dom.attr(test, 'title')
console.log(title)//读出title值
9.读写文本内容 dom.text(node,string)

用适配 长度为2是写,1是读

    text(node, string) { //适配
        if (arguments.length === 2) {
            if ('innerHTML' in node) {
                node.innerText = string //IE的
            } else {
                node.testContent = string //firefox、chrome
            }
        } else if (arguments.length === 1) {
            if ('innerHTML' in node) {
                return node.innerText //IE的
            } else {
                return node.testContent //firefox、chrome
            }
        }
    }

dom.text(test, '这是新的文本内容')
10.读写标签内容 dom.html(node,string)
html(node, string) {
    if (arguments.length === 2) {
        node.innerHTML = string
    } else if (arguments.length === 1) {
        return node.innerHTML
    }
}

console.log(dom.html(test))//读
11.改style dom.style(node, Object)
  • 用for循环遍历对象key,for (let key in Object)
  • 把对象属性值赋给style node.style[key] = Object[key]
style(node, Object) {
    for (let key in Object) {
        //key:color,border
        //node.style.color
        //node.style.border
        node.style[key] = Object[key]
    }
}

dom.style(test, {
    color: 'red',
    border: '1px solid red'
})
  • 由于有三种情况,长度为3时写样式,长度为2时字符串是读,是对象就是写入多个
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) {
                //key:color,border
                //node.style.color
                //node.style.border
                node.style[key] = object[key]
            }
        }
    }
}

//加样式
dom.style(test, {
    color: 'red',
    border: '1px solid red'
})
//查找属性值
console.log(dom.style(test, 'color'))
12.增class dom.class.add(node,‘blue’)
13.删class dom.class.remove(node,‘blue’)
14.查看class在不在 dom.class.contains(test, ‘blue’) 返回true/false
class: {
    add(node, className) {
        node.classList.add(className)
    },
    remove(node, className) {
        node.classList.remove(className)
    },
    contains(node, className) {
//return值
        return node.classList.contains(className)
    },
}

dom.class.add(test, 'red')
dom.class.add(test, 'blue')
dom.class.remove(test, 'red')
dom.class.contains(test, 'blue')
console.log(dom.class.contains(test, 'blue'))

<div id="test" class="red blue">哈哈</div>
15.添加事件监听 dom.on(node, ‘click’, fn)
16.删除事件监听 dom.off(node, ‘click’, fn)
on(node, eventName, fn) {
    node.addEventListener(eventName, fn)
},
off(node, eventName, fn) {
    node.removeEventListener(eventName, fn)
},

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

console.log(dom.parent(test2))
console.log(dom.children(x))
console.log(dom.siblings(test2))
console.log(dom.siblings(test))
console.log(dom.siblings(test
17.获取标签和标签们 dom.find(‘选择器’)

find是返回数组

  • 当find里一个值时,获取标签
find(selector) {
    return document.querySelectorALL(selector)
}ALL

const testDiv = dom.find('#test')[0]
console.log(testDiv)
  • 当find里两个值时,在指定便签里获取

  • (scope || document) 是document为保底值

find(selector, scope) {
    return (scope || document).querySelectorAll(selector);
}

const test2 = dom.find('#test2')[0]
console.log(dom.find('.red', test2)[0])

得到<p class="red">红色</p>
18.获取父元素 dom.parent(node)
parent(node) {
    return node.parentNode
},
19.获取子元素 dom.children(node)
children(node) {
    return node.children
},
20.获取兄弟姐妹 dom.siblings(node)
  • return Array.from(node.parentNode.children).filter(n => n !== node) 排出掉自己.filter
siblings(node) {
    return Array.from(node.parentNode.children).filter(n => n !== node)
}
21.获取弟弟 dom.next(node)

需要先判断下一个是否为空格文本或者空 :while (x && x.nodeType === 3)

next(node) {
    let x = node.nextSibling
    //判断下一个存在且是否为文本
    while (x && x.nodeType === 3) {
        x = x.nextSibling
    }
    return x
}
22.获取哥哥 dom.previous(node)
  • 判断下一个存在且为文本时查找下一个值
(node) {
        let x = node.nextSibling
        //判断下一个存在且是否为文本
        while (x && x.nodeType === 3) {
            x = x.nextSibling
        }
        return x
    },
23.遍历所有节点
  • 先找到节点节点,查到所有所有子节点,执行箭头函数
each(nodeList, fn) {
    for (let i = 0; i < nodeList.length; i++) {
        fn.call(null, node.List[i])
    }
}

const t = dom.find('#travel')[0]
dom.each(dom.children(t), (n) => dom.style(n, 'color', 'red'))
24.判断节点排名老几
  • 先获取父节点的所有孩子,为数组,再遍历数组,判断数组元素和node关系,返回需要的值,从0开始
index(node) {
    let arr = dom.children(node.parentNode)
    let i;
    for (i = 0; i < arr.length; i++) {
        if (arr[i] === node) {
            break
        }
    }
    return i
}

console.log(dom.index(test2))
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值