JavaScript DOM扩展

一、选择符API扩展

querySelector()

该方法接受一个CSS选择符,返回与该模式匹配的第一个元素。没有匹配的元素则返回null。在Document类型调用该方法会在文档元素的范围内查找匹配元素,在Element类型调用该方法会在该元素的后代范围内查找匹配元素。传入非法的选择符时会抛出错误。

var div = document.querySelector("div");
var myDiv = document.querySelector("#myDiv");
var bth = myDiv.querySelector(".btn");

querySelectorAll()

该方法参数与querySelector()方法一样,但返回的是一个NodeList实例,包含所有匹配的元素。如果没有匹配的元素,则返回一个空的NodeList。返回的NodeList带有属性方法,其底层实现类似于一组元素的快照,而非不断对文档进行搜索的动态查询,从而避免了使用NodeList通常会引起的大多数性能问题。

var div = document.querySelectorAll("div");
var .btn = document.querySelectorAll(".btn");
var firstDiv = div.item(0); // 或者div[0]

matchesSelector()

该方法接受一个CSS选择符,如果调用元素与该选择符匹配则返回true,否则返回false。

var div = document.querySelector("div.aha");
console.log(div.matchesSelector(".aha")); // true

二、元素遍历扩展

Element Traversal API为DOM元素添加了以下5个属性:

  • childElementCount: 返回子元素(不包括文本节点和注释)的个数
  • firstElementChild: 指向第一个子元素;firstChild的Element版
  • lastElementChild: 指向最后一个子元素;lastChild的Element版
  • previousElementSibling: 指向前一个同辈元素;previousSibling的Element版
  • nextElementSibling: 指向后一个同辈元素;nextSibling的Element版

过去,要跨浏览器遍历某元素的所有子元素,需要像下面的示例1一样去写代码,childNodes列表中包含元素节点、文本节点、注释节点等信息,因此需要检测元素节点。而有了上面5个拓展属性之后就可使得代码更加简洁,而且循环次数更少,如示例2。

// 示例1
var child = element.firstChild;
while (child != element.lastChild) {
  if (child.nodeType == 1) { // 需要检查是否为元素节点
    processChild(child);
  }
  child = child.nextSibling;
}

// 示例2
child = element.firstElementChild;
while (child != element.lastElementChild) {
  processChild(child);
  child = child.nextElementSibling;
}

三、HTML5扩展

与类相关的扩充

getElementsByClassName(): 该方法接受一个参数,即包含一个或多个类型的字符串,返回一个NodeList,包含所有带有指定类型的元素。

classList属性: 在操作类名时,需要通过className属性添加、删除和替换类名,由于className的值是一个字符串,所以每次修改都需要替换整个字符串的值,如果元素有多个类名,仅修改其中一个类名都需要写不少代码,非常麻烦。classList的出现解决了这些麻烦,使得操作类名更简单更安全。classList属性是新集合类型DOMTokenList的实例,有length属性表示包含的元素数量,通过item()方法或方括号语法可以取得每个元素。DOMTokenList还有以下方法:

  • add(value): 将给定的字符串添加到列表中
  • contains(value): 如果列表中存在给定的值,返回true,否则返回false
  • remove(value): 从列表中删除给定字符串
  • toggle(value): 如果列表中存在给定值,删除它,否则添加它

下面给出代码示例,示例1展示了使用className修改类名的过程,示例2则是使用classList的过程。

// 示例1,删除"xxx"类
var classNames = div.className.split(/\s+/);
var pos = -1;
for (var i = 0; i < classNames.length; ++i) {
  if (className[i] == "xxx") {
    pos = i;
    break;
  }
}
classNames.splice(i, 1);
div.className = classNames.join(" ");

// 示例2
div.classList.remove("xxx"); // 删除"xxx"类
div.classList.add("yyy"); // 添加"yyy"类

焦点管理

document.activeElement: 引用DOM中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入和代码中调用focus()方法。默认情况下,文档刚刚加载完时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement的值是null。

document.hasFocus(): 该方法用于确定文档是否获取了焦点,便于检测用户是否正在与页面交互。

var btn = document.getElementById("#btn");
btn.focus();
console.log(document.activeElement == btn); // true
console.log(document.hasFocus()); // true

HTMLDocument

document.readyState: Document的readyState属性有两个可能值,”loading”表示正在加载文档,”complete”表示已经加载完文档。document.readyState的基本用法如下:

if (document.readyState == "complete") {
  // do something
}

document.compatMode: 该属性用于告诉开发人员浏览器采用了哪种渲染模式,标准模式下其值为”CSS1Compat”,混杂模式下其值为”BackCompat”。

document.head: 包含对< head>元素的引用。

字符集属性

document.charset: 表示文档中使用的字符集。基本用法如下:

console.log(document.charset);
document.charset = "utf-8";

document.defaultCharset: 表示根据默认浏览器及操作系统的设置,当前文档的默认字符集应该是什么。

自定义数据属性

HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息或者语义信息。这些属性可以任意添加、随便命名,但必须以data-开头。添加自定义属性之后在JS中可以通过元素的dataset属性来访问。dataset是一个键值对,每个data-name形式的属性都会有一个对应的属性,属性名会去掉data-前缀。

// <div id="myDiv" data-name="xxx" data-phone="123" data-email="yyy"></div>
var div = document.getElementById("myDiv");
console.log(div.dataset.name); // "xxx"
console.log(div.dataset.phone); // "123"
console.log(div.dataset.email); // "yyy"

插入标记

innerHTML属性:在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释、文本)对应的HTML标记。在写模式下,会根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。

<div id="myDiv">
  <p>some content</p>
  <p>another content</p>
</div>
var div = document.getElementById("myDiv");
console.log(div.innerHTML); // 输出"<p>some content</p>\n<p>another content</p>"
div.innerHTML = "haha~"; // div的内容变成<div id="myDiv">haha~</div>

outerHTML属性:读模式下,outerHTML返回调用它的元素以及所有子节点的HTML标签。在写模式下会根据指定的HTML字符串创建新的DOM子树,然后用这个子树完全替换调用元素。

<div id="div-1">
  <div id="div-2">
    <p>some content</p>
    <p>another content</p>
  </div>
</div>
var div2 = document.getElementById("div-2");
console.log(div2.outerHTML); // 输出"<div id="div-2"><p>some content</p><p>another content</p></div>"
div2.outerHTML = "haha~"; // div的内容变成<div id="div-1">haha~</div>

insertAdjacentHTML()方法:该方法接受两个参数,要插入的位置和要插入的HTML文本。第一个参数必须是下列值之一:

  • “beforebegin”: 在当前元素之前插入一个紧邻的同辈元素
  • “afterbegin”: 在当前元素下插入一个新的子元素,新元素放在原有的第一个子元素之前
  • “beforeend”: 在当前元素的最后一个子元素后面插入新的子元素
  • “afterend”: 在当前元素后面插入一个紧邻的同辈元素

下面是代码示例:

element.insertAdjacentHTML("beforebegin", "<p>haha~</p>");
element.insertAdjacentHTML("afterbegin", "<p>haha~</p>");
element.insertAdjacentHTML("beforeend", "<p>haha~</p>");
element.insertAdjacentHTML("afterend", "<p>haha~</p>");

内存与性能问题:

  1. 假设某个元素有一个事件处理程序(或者引用了一个JS对象作为属性),在使用上述的某个属性将该元素从文档树中删除后,元素与事件处理程序(或JS对象)之间的绑定关系在内存中并没有一并删除。如果这种情况频繁出现,页面占用的内存数量就会明显增加。因此,在使用innerHTML、outerHTML和insertAdjacentHTML()时最好先手动删除要被替换元素的所有事件处理程序和JS对象属性。

  2. 使用innerHTML属性与通过多次DOM操作先创建节点再指定它们之间的关系相比,效率要高很多。这是因为在设置innerHTML或outerHTML时,就会创建一个HTML解析器,这个解析器是在浏览器级别的代码(通常是C++)基础上运行,比执行JS要快得多。此外,创建和销毁这个HTML解析器也会带来性能损失,所以最好将设置innerHTML和outerHTML的次数控制在合理的范围之内。

scrollIntoView()方法

该方法可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值