封装DOM,DOM是JS里面最常用的一个接口,单独使用比较麻烦,故封装起来使用,需要时调用
对象风格
也叫命名空间风格
window.dom 是我们提供的全局对象
然后在dom上挂很多的函数
增删改查
注意:
- 在index.html链接顺序中,dom.js要放在main.js文件上方才能优先访问到,封装的dom库在main.js文件中调用
- 获取到的是否为伪数组,是否需要转换为数组,是否需要获取索引下标才能访问
- 重点记忆需要变通的函数
- each遍历
- 获取元素
- 修改style等 ```javascript window.dom = {
//增
create(string) { //用于创建新节点
const container = document.createElement("template");
container.innerHTML = string.trim();
return container.content.firstChild;
},
after(node, node2) { //在node后面新增node2弟弟(变通式,利用现有insertBefore)
node.parentNode.insertBefore(node2, node.nextSibling);
},
before(node, node2) { //在node前面新增node2哥哥(现有API)
node.parentNode.insertBefore(node2, node)
},
append(parent, node) { //在parent内新增node儿子
parent.appendChild(node)
},
wrap(node, parent) { //在node外新增parent爸爸(变通式)(会覆盖旧爸爸)
dom.before(node, parent); //先让node成为parent的哥哥
dom.append(parent, node); //再让node成为parent的儿子
},
//删
remove(node) { //删除父亲指定下的儿子
node.parentNode.removeChild(node)
},
empty(node) { //删除父亲名下所有儿子
const array = [];
let x = node.firstChild;
while (x) {
array.push(dom.remove(node.firstChild));
x = node.firstChild //由于childNode元素会实时变化,因为儿子会发生替位关系,故针对每个大儿子删除,使用while循环不添加计数器
}
return array
},
//改
attr(node, name, value) { //读&写 属性
if (arguments.length === 3) { //重载(根据参数的不同写不同的代码)
node.setAttribute(name, value) //现有API ,修改属性
} else if (arguments.length === 2) {
return node.getAttribute(name) //现有API , 获取属性
}
},
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) { //读&写 html内容
if (arguments === 2) {
node.innerHTML = string;
} else if (arguments.length === 1) {
return node.innerHTML
}
},
style(node, name, value) { //读&写 style
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) { //instanceof判断name是否为Object的实例,返回值为布尔值
// dom.style(div,{color:'red'})
const object = name;
for (let key in object) { //遍历object,把object中所有未知的key声明且读到
node.style[key] = object[key] //将object中所有 [key变量下的值] 存入node的style中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) //记得return返回值得确认
}
},
//改DOM事件
on(node, eventName, fn) {
node.addEventListener(eventName, fn)
},
off(node, eventName, fn) {
node.removeEventListener(eventName, fn)
},
//查,用于获取元素(以上均用全局id)
find(selector, scope) { //通过选择器和指定范围查找
return (scope || document).querySelectorAll(selector) //存在第二个参数scope则在第二个参数的范围里查找,若无则在document中查找
},
parent(node) { //传入节点,返回节点的爸爸
return node.parentNode
},
children(node) { //传入节点,返回节点的儿子
return node.children
},
siblings(node) { //传入节点,返回兄弟姐妹元素
return Array.from(node.parentNode.children).filter(n => n !== node) //得到的伪数组需要转换为数组才能使用filter接口,过滤其他元素,将这些元素存入数组并返回
},
next(node) { //传入节点,返回弟弟妹妹,排除文本节点
let x = node.nextSibling
while (x && x.nodeType === 3) { //x存在且x的节点类型为文本节点(同时也需排除x节点不存在的前提)
x = x.nextSibling //若该节点属于文本节点,则遍历下个节点,直到元素节点再返回
}
return x
},
previous(node) { //传入节点,返回哥哥姐姐,排除文本节点
let x = node.previousSibling
while (x && x.nodeType === 3) {
x = x.previousSibling
}
return x
},
each(nodeList, fn) { //对节点列表中的每一个节点遍历调用fn函数
for (let i = 0; i < nodeList.length; i++) {
fn.call(null, nodeList[i])
}
},
index(node) { //传入节点,获取节点的索引
const list = dom.children(node.parentNode) //遍历其父亲的所有孩子,纳入一个列表
let i //注意此处i声明在函数外,以便return
for (i = 0; i < list.length; i++) {
if (list[i] === node) {
break
}
}
return i
}
} ```