DOM进阶

DOM进阶

一.DOM 类型

  • Node:表示所有类型值的统一接口,IE 不支持
  • Document:表示文档类型
  • Element:表示元素节点类型
  • Text:表示文本节点类型
  • Comment:表示文档中的注释类型
  • CDATASection:表示 CDATA 区域类型
  • DocumentType:表示文档声明类型
  • DocumentFragment:表示文档片段类型
  • Attr:表示属性节点类型

二.DOM 扩展

1.呈现模式

从 IE6 开始开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE 为document 对象添加了一个名为 compatMode 属性,这个属性可以识别 IE 浏览器的文档处于什么模式如果是标准模式,则返回CSS1Compat,如果是混杂模式则返回BackCompat。

if (document.compatMode == 'CSS1Compat') {
  alert(document.documentElement.clientWidth);
} else {
  alert(document.body.clientWidth);
}
复制代码

PS:后来 Firefox、Opera 和 Chrome 都实现了这个属性。从 IE8 后,又引入 documentMode新属性,因为 IE8 有 3 种呈现模式分别为标准模式 8,仿真模式 7,混杂模式 5。所以如果想测试 IE8 的标准模式,就判断 document.documentMode > 7 即可。

2.滚动

DOM 提供了一些滚动页面的方法,如下:
document.getElementById('box').scrollIntoView();//设置指定可见

3.children 属性

由于子节点空白问题,IE 和其他浏览器解释不一致。虽然可以过滤掉,但如果只是想得到有效子节点,可以使用 children 属性,支持的浏览器为:IE5+Firefox3.5+、Safari2+、Opera8+和 Chrome,这个属性是非标准的。

var box = document.getElementById('box');
alert(box.children.length);//得到有效子节点数
复制代码

4.contains()方法

判断一个节点是不是另一个节点的后代,我们可以使用 contains()方法。这个方法是 IE率先使用的,开发人员无须遍历即可获取此信息。

var box = document.getElementById('box');
alert(box.contains(box.firstChild)); //true
复制代码

PS:早期的 Firefox 不支持这个方法,新版的支持了,其他浏览器也都支持,Safari2.x浏览器支持的有问题,无法使用。所以,必须做兼容。在 Firefox 的 DOM3 级实现中提供了一个替代的方法 compareDocumentPosition()方法。这个方法确定两个节点之间的关系。

var box = document.getElementById('box');
alert(box.compareDocumentPosition(box.firstChild));//20
复制代码

微信图片_20210706092505.png
PS:为什么会出现 20,那是因为满足了 4 和 16 两项,最后相加了。

三.DOM 操作内容

1.innerText 属性

document.getElementById('box').innerText;//获取文本内容(如有 html 直接过滤掉)
document.getElementById('box').innerText = 'Mr.Lee';//设置文本(如有 html 转义)
复制代码

PS:除了 Firefox 之外,其他浏览器均支持这个方法。但 Firefox 的 DOM3 级提供了另外一个类似的属性:textContent,做上兼容即可通用。

document.getElementById('box').textContent;//Firefox 支持

//兼容方案
function getInnerText(element) {
  return (typeof element.textContent == 'string') ?
  element.textContent : element.innerText;
}
function setInnerText(element, text) {
  if (typeof element.textContent == 'string') {
    element.textContent = text;
  } else {
    element.innerText = text;
  }
}
复制代码

2.innerHTML 属性

这个属性之前就已经研究过,不拒绝 HTML。

document.getElementById('box').innerHTML;//获取文本(不过滤 HTML)
document.getElementById('box').innerHTML = '<b>123</b>';//可解析 HTML
复制代码

虽然 innerHTML 可以插入 HTML,但本身还是有一定的限制,也就是所谓的作用域元素,离开这个作用域就无效了。

box.innerHTML = "<script>alert('Lee');</script>";//<script>元素不能被执行
box.innerHTML = "<style>background:red;</style>"; //<style>元素不能被执行
复制代码

3.outerText

outerText 在取值的时候和 innerText 一样,同时火狐不支持,而赋值方法相当危险,他不单替换了文本内容,还将元素直接抹去。

var box = document.getElementById('box');
box.outerText = '<b>123</b>';
alert(document.getElementById('box'));//null,建议不去使用
复制代码

4.outerHTML

outerHTML 属性在取值和 innerHTML 一致,但和 outerText 也一样,很危险,赋值的之后会将元素抹去。

var box = document.getElementById('box');
box.outerHTML = '123';
alert(document.getElementById('box'));//null,建议不去使用,火狐旧版未抹去
复制代码

PS:关于最常用的 innerHTML 属性和节点操作方法的比较,在插入大量 HTML 标记时使用 innerHTML 的效率明显要高很多。因为在设置 innerHTML 时,会创建一个 HTML 解析器。这个解析器是浏览器级别的(C++编写),因此执行 JavaScript 会快的多。但,创建和销毁 HTML 解析器也会带来性能损失。最好控制在最合理的范围内,如下:

for (var i = 0; i < 10; i ++) {
  ul.innerHTML = '<li>item</li>';//避免频繁
}

//改
for (var i = 0; i < 10; i ++) {
  a = '<li>item</li>';//临时保存
}
ul.innerHTML = a;
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享