「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
获取DOM节点
常用的方法:
document.getElementById()
document.getElementsByClassName()
document.getElementsByName()
document.getElementsByTagName()
document.getElementsByTagNameNS()
方便但是一般不用的方法:
document.querySelector()
document.querySelectorAll()
因为下面这两个方法有两个缺点:
- 性能问题
- 他两个获取的只是一个DOM快照,不具备实时性,而我们平时开发DOM操作的实时性非常重要。
DOM节点和元素的关系
节点是包含元素的,元素只是指自身,节点指整个DOM结构。
常用的节点类型如下:
| 常用节点类型 | 类性值nodeType |
| 元素节点 | 1 |
| 属性节点 | 2 |
| 文本节点 | 3 |
| 注释节点 | 8 |
| document | 9 |
| DocumentFragment | 11 |
常用的DOM属性
获取DOM的属性
var oli = document.getElementsByTagName("li")[0];
console.log(oli.firstChild); // 获取第一个子节点
console.log(oli.lastChild); // 获取最后一个子节点
console.log(oli.childNodes); // 获取所有类型的子元素
console.log(oli.childElementCount); // 获取子元素节点的个数
console.log(oli.children); // 获取所有子元素节点
console.log(oli.children[0].nextSibling); // 获取下一个兄弟节点
console.log(oli.children[0].nextElementSibling); // 获取下一个元素节点的兄弟节点
console.log(oli.children[1].previousSibling); // 获取上一个兄弟节点
console.log(oli.children[1].previousElementSibling); // 获取上一个元素节点的兄弟节点
一些带有兼容问题的属性:
parentElement // 获取父元素 IE9及以下不支持
children // 获取所有子元素节点 IE7及以下不支持
childELementCount // 获取子元素节点的个数 IE9及以下不支持
firstElementChild lastElementChild // IE9及以下不支持
nextElementSibling previousElementSibling // IE9及以下不支持
获取DOM上的信息
odiv.attrbutes // 元素的属性集合 NameNodeMap
<a href="" data-url="plmxs" data-sort="pay">普罗米修斯</a>
this.dataset.sort // 用data-key做属性名,可以通过ele.dataset[key]获取
odiv.hasChildNodes() // 判断节点是否含有某一个元素 只要又一个空格都算是文本节点
| 节点类型/属性key | nodeName | nodeValue | nodeType |
| 文本节点 | #text | 内容 | 3 |
| 注释节点 | #comment | 内容 | 8 |
| 元素节点 | 大写的标签名 | null | 1 |
| document | #document | null | 9 |
| 属性节点 | 属性key | 属性值 | 2 |
用childNodes实现children的功能,做兼容
function elemChildren(node) {
var temp = {
length: 0,
push: Array.prototype.push,
splice: Array.prototype.splice,
},
children = node.childNodes;
for (let i = 0; i < children.length; i++) {
const childItem = children[i];
if (childItem.nodeType === 1) {
// (1)
temp[temp[length]] = childItem;
temp[length] += 1;
// (2)
// temp.push(childItem);
}
}
return temp;
}
console.log(elemChildren(odiv))
DOM集合
通过getElementsByClassName等方法获取到的是类数组集合,继承自HTMLCollection。
类数组:本身是对象,为了保存自身的方法并且具备有序的特性,衍生出的一种数据结构;有length属性可以通过索引获取,但是不可被迭代(没有迭代器)。转数组的常用方法:Array.from(target) Array.prototype.slice.call(target) ...target
DOM的原型链
<div class="box">
我是文本
<!-- 我是注释 -->
</div>
<script>
const oBox = document.getElementsByClassName("box");
console.log(oBox); // HTMLCollection -> Object
console.log(oBox[0].__proto__); // HTMLDivElement(不同的标签类型HTML+标签名+Element) -> HTMLElement -> Element -> Node -> EventTarget -> Object
console.log(oBox[0].childNodes[1].__proto__) // Comment -> CharacterData -> Node -> EventTarget -> Object
console.log(oBox[0].childNodes[0].__proto__) // Text -> CharacterData -> Node -> EventTarget -> Object
console.log(oBox[0].attributes) // NamedNodeMap -> Object
console.log(oBox[0].attributes[0].__proto__) // Attr -> Node -> EventTarget -> Object
console.log(document.__proto__) // HTMLDocument -> Document -> Node -> EventTarget -> Object
</script>
document和element
console.log(Document.prototype);
console.log(Element.prototype);
// 获取dom的api
// Document下的api
// getElementById
// getElementsByClassName
// getElementsByName
// getElementsByTagName
// getElementsByTagNameNS
// querySelector
// querySelectorAll
// Element的api
// getElementsByClassName
// getElementsByTagName
// getElementsByTagNameNS
// querySelector
// querySelectorAll;
总结:元素节点是不能用 getElementById getElementsByClassName getElementsByName
一些便捷的方法
// 获取body head title 有快捷方法
console.log(document.body); // body节点
console.log(document.head); // head节点
console.log(document.title); // title节点的内容
console.log(document.documentElement); // html节点
创建DOM的方法
// 创建dom
const obox = document.getElementsByClassName('box')[0];
const odiv = document.createElement('div');
odiv.innerText = '我是属性节点';
// 创建文本节点
const otext = document.createTextNode('我是文本节点');
// otext.textContent = '我是文本节点';
// 创建注释节点
const ocomment = document.createComment('我是注释节点')
obox.appendChild(odiv);
obox.appendChild(otext);
obox.appendChild(ocomment);
// document.body.appendChild也能用,所以**appendChild是在Node下**
操作DOM
obox1.innerText = "我是添加的div";
// 把obox1放在oh1前面
obox.insertBefore(obox1, oh1);
// 移除子dom(移除之后依然可以打印出oh1,因为reomveChild只是从dom结构中删除,本身还存在浏览器的内存中)
console.log(obox.removeChild(oh1));
// 返回undefined,用自己remove方法删除自己
console.log(obox1.remove());
// 替换dom replaceChild(new, origin)
obox.replaceChild(oh1, oh2);
// innerText 会过滤掉所有的标签,省下纯文本
console.log(obox.innerText);
// 设置属性setAttrbute
obox.setAttribute("id", "obox");
// 获取属性值
console.log(obox.getAttribute("class"));
所有滚动知识点
滚动条位置
window.pageXOffset/pageYOffset // 整个页面滚动条位置
window.body.scrollLeft/scrollTop // IE9及以下 某个dom内部滚动条位置
document.documentElement.scrollLeft/scrollTop //
window.scrollY/scrollX // 基本不用
操作滚动条
window.scroll(20, 20) window.scrollTo(20, 20) // 这两个效果一样,滚动到指定位置
window.scrollBy(20, 20) // 滚动指定的距离
盒子的几何面积
浏览器的标准模式(CSS1Compat)和怪异模式(BackCompat)
BackCompat 对应quirks mode
CSS1Compat 对应strict mode
在Standars mode中:
元素真正的宽度 = margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right;
在Quirks mode中:
width则是元素的实际宽度,内容宽度 = width - (margin-left + margin-right + padding-left + padding-right + border-left-width + border-right-width);
document.compatMode // 判断模式
元素位置
// 如果父元素有定位,则根据父元素位置,若无定位则一直向上找直到body
console.log(box2.offsetTop);