DOM编程
目录
前置知识
网页就是一棵DOM树
JS如何操作这棵树
DOM元素
节点的增删改查
DOM操作是跨线程的
Property VS Attribute
一、前置知识
- 理解简单的JS语法
- JS的七种数据类型:
number、string、bool、symbol、undefined、null、Object
- JS五个falsy值:
''、undefined、null、0、NaN
- 简单的CSS布局
二、网页是一棵DOM树
- 代码+图解
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>DOM树</title> </head> <body> <header> <h1>文字1</h1> </header> <main> <h2>文字2</h2> <p>文字3<span>文字4</span>文字5</p> </main> </body> </html>
三、JS如何操作这棵树?
使用document操作网页
这就是DOM(Document Object Model)文档对象模型
四、DOM元素
- 获取元素(标签)
document.getElementById('xxx'); . document.getElementsByTagName('div')[0]; . document.getElementsByClassName('red')[0]; . document.querySelector(''); | 需要遵守选择器的样式书写 如:'#id_1'、'.class_1'、 . document.querySelectorALL(); |同上
- 获取特定元素
1、获取html元素 document.documentElement 2、获取head元素 document.head 3、获取body元素 document.body 4、获取窗口 |窗口不是元素 window 5、获取所有元素 document.all
window.all: 是第6个falsy值
原因:因为window.all最早是IE发明的,早期的前端为了区分IE和其他浏览器,就一般如下设置。为了区分是IE还是非IE浏览器。if(window.all){ console.log("这些代码只能在IE里面运行"); } else{ console.log("这些代码只能在非IE里面运行"); }
- 问题来了:获取到的元素到底是个啥?
显然获取到的元素是个对象
抓一只div对象来看看都有啥
console.dir(div);
div的6层原型链
-
节点?元素?傻傻分不清楚
使用
nodeType
方法可以打印出节点的值1表示元素ELement,也叫标签Tag
3表示文本Text
8表示注释Comment
9表示文档Document
- 更多节点值
五、节点的增删改查
1、增
- 创建一个标签节点
let div1=document.createElement('div'); document.createElement('style'); document.createElement('script'); document.createElement('li');
- 创建一个文本节点
text1=document.createTextNode('你好');
- 插入创建的节点:
坑1:一个元素不能同时出现在(插入)两个地方,除非复制一份。
div1.appendChild(text1); | 在div1标签里面插入文本节点text1 document.body.appendChild(div1); | 在body里面插入div1标签 document.head.appendChild(div1); | 在head里面插入div1标签
2、删
- 删除节点:
坑2:删除之后的节点被移除DOM树,但还在内存中,依然可以调用它再将其添加回来
旧方法 | parentNode.removeChild('待删除的儿子节点') 新方法 | 待删除的节点.remove();
3、改
- 写标准属性:
注意:js中不识别'-'这个字符,所以遇到'-'就将'-'后面第一个字母大写,如:background-color --> backgroundColor
改class | div.style.className='red blue'; --> 全覆盖 改class | div.classList.add('red'); 改style | div.style='width:100px;color:blue'; --> 全覆盖 改style | div.style.width='200px'; --> 推荐 改data-*属性 | div.dataset.x='frank';
- 读标准属性:
下面两种方法都可以读属性,但某些情况下的值可能会不同。
默认方法 | div.classList/a.href getter/setter方法 | div.getAttribute('class')/a.getAttribute('href');
- 改文本内容
div.innerText='你好,世界!'; div.textContent='你好,世界!';
- 改HTML内容
div.innerHTML='<strong>重要的内容</strong>';
- 改标签
div.innerHTML=''; | 先清空内容 div.appendChild(div2); | 再添加内容
- 改父元素?
newParent.appendChild(div); | div的父元素变成newParent,并且从原来的地方消失。
4、查
- 查爸爸
node.parentNode | node.parentElement
- 查爷爷
node.parentNode.parentNode
- 查子代:
坑1:当子代变化时,两者也会实时变化,例如遍历的数组长度length
node.childNodes | node.children
- 查兄弟姐妹
node.parentNode.childNode | 注意要排除自己 node.parentNode.children | 注意要排除自己
- 查看老大、老幺
node.firstChild node.lastChild
- 查看上一个节点元素
node.previousSibling
- 查看下一个节点元素
node.nextSibling
- 遍历一个div里面的所有元素
travel = (node,fn)=>{ fn(node); if(node.children){ for(let i=0;i<node.children.length;i++){ travel(node.children[i],fn); } } } travel(div,(node)=>{ console.log(node); })
六、DOM操作是跨线程的
-
跨线程操作
JS引擎不能操作页面,只能操作JS
渲染引擎不能操作JS,只能操作页面
例如执行如示代码:document.body.appendChild(div1) JS 是如何改变页面的?
-
跨线程通信
当浏览器发现JS在body里面加了一个div对象
浏览器就会通知渲染引擎在页面里也新增一个div元素
-
插入新标签的完整过程
在div1放入页面之前
对div1进行的所有操作都是在JS线程中进行的
在div1放入页面之时
浏览器发现了JS的意图,通知渲染线程在页面中渲染div1对应的元素
把div1放入页面之后
当你想对div1再次进行操作时,都会有可能触发重新渲染
-
属性同步
标准属性:如id,className,title等
data-*属性
非标准属性:除开1,2两点的其他自定义属性
自动属性同步
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="test" x="test" data-x="test"> <p>id 一开始为 test,后来改为 frank <p>你会发现页面中 id 变为 frank <p>data-x 属性一开始为 test,后来改为 frank <p>你会发现页面中的 data-x 变成了 frank <p>x 属性一开始为 test,后来改为 frank <p>你会发现页面中的 x 还是 test </div> <script> let div1 = document.querySelector('#test') div1.id = 'frank' // 同步过去了 div1.dataset.x = 'frank' // 同步过去了 div1.x = 'frank' // 没有同步过去 div1.style.border = '1px solid red' </script> </body> </html>
七、Property VS Attribute
-
property属性
JS 中div1的所有属性,叫做div1的property
-
attribute属性
渲染引擎中div1对应标签的属性,叫做attribute
-
二者的区别
大部分时候,同名的property和attriubte值相等。
但如果不是标准属性,两者的值只会在一开始的时候相等
attribute: 只支持字符串类型