一、对象风格
也叫命名空间风格
window.dom 全局对象
第一行代码就是 window.dom = {};
增:
创建节点dom.create('<div>hi</div>')
基础代码

简化一下,window可以删掉
window.dom = {};
dom.create = function() {};
create也可以直接写在window里
window.dom = {
create : function() {}
};
还可以再简化,直接把function也省略

window.dom = {};里面包着
功能实现

create函数接受一个tagName(标签名)参数,然后返回创建节点

main.js里试着创建一个div,然后获取到这个div

在index.html里引入运行

增加点难度,同时创建一个div里有个span

-
这里上面的方法太繁琐,要让下面这种写法实现

-

实现原理:
"<div><span>1</span></div>"这一串其实就是HTML,要让它在HTML里,自动生效成HTML标签
在dom.js里首先创建一个div容器,然后通过innerHTML使用string替换掉div
优化
我们创建的容器是一个div容器,有些元素不能直接放到div里,可以使用一个新的标签<template>,可以容纳任意标签
,不会在页面中显示,一个专门用来容纳的标签
template不能通过children直接获取要使用
template.content.firstChild
最后的代码:
window.dom = {
create(string) {
const container = document.createElement("template")
container.innerHTML = string.trim();
return container.content.firstChild
}
}
trim可以把字符串两边的空格给去掉,直接显示标签


新增弟弟dom.after(node,node2)
after(node, node2) {
console.log(node.nextSibling)
node.parentNode.insertBefore(node2, node.nextSibling);
}
要给当前node之后放一个它的弟弟node2,就找到他的父亲,然后插入在它下一个儿子之前
Node.insertBefore()方法在参考节点之前插入一个拥有指定父节点的子节点。


新增哥哥dom.before(node,node2)
before(node, node2) {
node.parentNode.insertBefore(node2, node);
}
新增儿子dom.append(parent,child)
append(parent, node) {
parent.appendChild(node);
}
直接调用appendChild
新增爸爸dom.wrap('<div></div>')
就是在当前标签之外再加一层div
wrap(node, parent) {
dom.before(node, parent);
dom.append(parent, node);
}
先把parent放在当前node的前面,当这个node的兄弟,然后用append把node加到parent里面,append不能让一个节点同时出现在两个地方,所以原来当parent兄弟的那个node在变成它儿子的时候已经从原来的地方消失了
这好像是一段绕口令,应该是看不懂的吧。。。。。
删:
删除节点dom.remove(node)
删除当前整个节点
remove(node) {
node.parentNode.removeChild(node)
return node //保留当前节点的引用
}
删除孩子dom.empty(parent)
删除当前节点的所有孩子,保留自己
最简单的方法就是直接获取到这个节点,然后innerHTML为''(空字符串)
empty(node) {
node.innerHTML = ''
}
如果想要获取到删除节点的引用,
empty(node) {
const { childNodes } = node
//直接从node获取到它的childNodes,等价于const childNods = node.childNodes
const array = []
for (let i = 0; i < childNodes.length; i++) {
dom.remove(childNodes[i])
array.push(childNodes[i])
}
return array
}
获取到这个节点的childNodes,然后遍历,删除一个往数组里push一个,最后返回这个数组就是我们删掉的所有节点
<div id="empty">
<div id="e1"></div>
<div id="e2"></div>
<div id="e3"></div>
</div>
const nodes = dom.empty(window.empty)
console.log(nodes)
运行一下

最后有一个undefined!!!!!!!!
childNodes.length是实时变化的,每删掉一个节点,length就会减一,所以i不能++,换成while循环试试
empty(node) {
const { childNodes } = node
const array = []
let x = node.firstChild
while (x) {
array.push(dom.remove(node.firstChild))
//之前的remove有返回值,所以这里可以直接引用
x = node.firstChild
}
return array
}
先找到第一个儿子,用x表示
当x存在,就删掉第一个childNodes并push到array里,再把x指向firstChild,当firstChild移出之后,x指向的是第二个儿子,所以要重新指向一下
最后返回array,看一下运行结果

改:
读写属性dom.attr(node,'title',?)
attr(node, name, value) {
node.setAttribute(name, value)
}
dom.attr(test, 'title', 'hi')运行一下

js的一个函数是可以接受多种参数的



读写文本内容dom.text(node,?)
text(node, string) { //适配
if ('innerText' in node) { //ie
node.innerText = string
} else {
node.textContent = string //Firefox/Chrome
}
}
读:



读写HTML内容dom.html(node,?)
html(node, string) {
if (arguments.length === 2) {
node.innerHTML = string
} else if (arguments.length === 1) {
return node.innerHTML
}
}
修改styledom.style(node,{color:'red'})

dom.style(test, { border: '1px solid red', color: 'blue' })
使dom.style(test,'border')是读出test的border属性
或者dom.style(test,'color','red')三个参数来修改


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) {
const object = name
for (let key in object) {
node.style[key] = object[key] //key是个变量
}
}
}
}
修改class
- 增加
dom.class.add(node,'blue') - 删除class
dom.class.remove(node,'blue') - 查看是否存在
dom.class.has(node,'blue')

事件监听
- 添加事件监听
dom.on(node,'click',fn)
on(node, eventName, fn) {
node.addEventListener(eventName, fn)
}
- 删除事件监听
dom.off(node,'click',fn)
off(node, eventName, fn) {
node.removeEventListener(eventName, fn)
}
查:
获取标签 dom.find('选择器')
find(selector, scope) {
return (scope || document).querySelectorAll(selector)
}
有scope从scope范围内找,没有就在document找


- find返回的是数组,使用find方法一定要加下标
获取父元素 dom.parent(node)
parent(node) {
return node.parentNode
}
获取子元素 dom.children(node)
children(node) {
return node.children
}
获取兄弟姐妹元素 dom.siblings(node)
siblings(node) {
return Array.from(node.parentNode.children).filter(n => n !== node)
}
这个要先找到他的爸爸,再找到他爸爸的所有儿子,使用Array.from把伪数组变成真数组,组成新的数组return回来
filter()方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。
获取弟弟 dom.next(node)
next(node) {
let x = node.nextSibling
while (x && x.nodeType === 3) {
x = x.nextSibling
}
return x
}
下一个节点很可能是回车或者空格等文本节点,使用while循环一直找到不是文本节点的下一个节点
获取哥哥 dom.previous(node)
previous(node) {
let x = node.previousSibling
while (x && x.nodeType === 3) {
x = x.previousSibling
}
return x
}
遍历所有节点 dom.each(node,fn)
each(nodeList, fn) {
for (let i = 0; i < nodeList.length; i++) {
fn.call(null, nodeList[i])
}
}



获取排行老几 dom.index(node)
index(node) {
const list = dom.children(node.parentNode)
let i
for (i = 0; i < list.length; i++) {
if (list[i] === node) {
break
}
}
return i
}

