前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DOM扩展

DOM扩展

作者头像
奋飛
发布2019-08-15 09:46:09
1.5K0
发布2019-08-15 09:46:09
举报
文章被收录于专栏:Super 前端Super 前端

下述内容主要讲述了《JavaScript高级程序设计(第3版)》第11章关于“DOM扩展”。

尽管DOM作为API已经非常完善了,但是为了实现更多的功能,仍然会有一些标准或专有的扩展。对DOM的两个主要扩展是Selectors API(选择符API)和HTML5。

一、选择符API

Selectors API是由W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询。其核心的两个方法:querySelector()querySelectorAll()

1. querySelector()方法

querySelector()接受一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素返回null。 示例

代码语言:javascript
复制
document.querySelector("body");
document.querySelector("#content");
document.querySelector(".bd");
2. querySelectorAll()方法

querySelectorAll()接受一个CSS选择符,返回与该模式匹配的NodeList实例,如果没有找到匹配的元素返回null。 示例

代码语言:javascript
复制
var lis = document.querySelectorAll("ul li");
// 获取第一个li
lis.item(0); // 等价于:lis[0];

注意:上述两个函数如果传入不支持的选择符,会抛出错误。

3. matchesSelector()方法

matchesSelector()方法大部分浏览器未实现,可使用matches()或者使用各个浏览器实验性的实现。

代码语言:javascript
复制
function matchesSelector(element, selec)

如果调用元素与该选择符匹配,返回true;否则,返回false。

代码语言:javascript
复制
function matchesSelector(element, selector){
    if (element.matchesSelector){
        return element.matchesSelector(selector);
    } else if (element.msMatchesSelector){
        return element.msMatchesSelector(selector);
    } else if (element.mozMatchesSelector){
        return element.mozMatchesSelector(selector);
    } else if (element.webkitMatchesSelector){
        return element.webkitMatchesSelector(selector);
    } else if(ele.matches){
        return ele.matches(selector);
    } else{
        throw new Error("Not supported.");
    }
}
matchesSelector(document.body, "body");     // true
matchesSelector(document.body, "body div"); // false
matches.png
matches.png

二、元素遍历

对于元素间的空格,各浏览器对于childNodes和firstChild等属性处理行为不一致,为了弥补差异,Element Traversal新定义了一组属性。 示例

代码语言:javascript
复制
<p>李刚</p>   
<ul>
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
    <li>item4</li>
    <li>item5</li>
</ul>
<p id="blog">http://blog.csdn.net/ligang2585116</p>

属性

说明

示例

childElementCount

子元素(不包含文本节点和注释)的个数

5

firstElementChild

指向第一个子元素,firstChild的元素版

<li>​Item 1​</li>

lastElementChild

指向最后一个子元素,lastChild的元素版

<li>​Item 5</li>​

previousElementSibling

指向前一个同辈元素,previousSibling的元素版

<p>李刚</p>

nextElementSibling

指向后一个同辈元素,nextSibling的元素版

<p id="blog">http://blog.csdn.net/ligang2585116</p>

代码语言:javascript
复制
var ul = document.querySelector("ul");
ul.firstChild;  // #text
ul.lastChild;   // <li>​Item 5​</li>​
ul.previousSibling; // #text
ul.nextSibling;     // #text

三、HTML5

1. 与类相关的扩充

(1)getElementsByClassName("包含一或多个类名的字符串")

代码语言:javascript
复制
document.getElementsByClassName("bj");      // 取得类中包含“bj”的元素
document.getElementsByClassName("bj bd");   // 取得类中同时包含“bj”和“bd”的元素

(2)classList属性 在操作类名时,需要通过className属性添加、删除和替换类型名。因为className中是一个字符串,所以即使只修改字符串的一部分,也必须每次都设置整个字符串的值。

代码语言:javascript
复制
<div class="bd user">ligang</div>

示例:className方式

代码语言:javascript
复制
var div = document.getElementsByClassName("bd")[0];
var classNames = div.className.split(/\s+/);
// 查找要删除的类名"user"
var index = classNames.indexOf("user");
// 删除类名"user"
classNames.splice(index, 1);
// 重新设置className
div.className = classNames;

示例:classList方式

代码语言:javascript
复制
var div = document.getElementsByClassName("bd")[0];
div.classList.remove("user");

classList属性是DOMTokenList的实例,其含有length属性。

属性

说明

add(value)

将给定的字符串添加到列表中。如果已存在,就不添加了

contains(value)

表示列表中是否存在给定的值

remove(value)

从列表中删除给定的字符串

toggle(value)

如果列表中已存在给定的值,删除它;如果不存在,添加它

有了classList属性,除非需要删除全部所有类名,或者完全重写元素的class属性,否则也就用不到className属性了。

2. 焦点管理

document.activeElement属性始终会引用DOM中当前获得了焦点的元素。 示例

代码语言:javascript
复制
var btn = document.getElementById("myBtn");
btn.focus();
console.log(btn.hasFocus());    // true
console.log(document.activeElement === btn); // true

默认情况下,文档刚刚加载完成时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement为null。 查询文档获知哪个元素获得了焦点,以及确定文档是否获得了焦点,这两个功能最重要的用途是提高Web应用的无障碍性。无障碍Web应用的一个重要标志就是恰当的焦点管理,而确切地知道哪个元素获得了焦点是一个极大的进步。

3. HTMLDocument的变化

(1)readyState属性

  • loading:正在加载文档;
  • complete:已经加载完文档。 使用document.readyState的最恰当方式,就是通过它来实现一个指示文档已经加载完成的指示器。

(2)兼容模式 document.compatMode告知开发人员浏览器采用了哪种渲染模式。

  • CSS1Compat:标准模式;
  • BackCompat:混杂模式。

(3)head属性 HTML5新增了document.head属性,引用文档的<head>元素。

代码语言:javascript
复制
var head = document.head || document.getElementsByTagName("head")[0];
4. 字符集属性
  • document.charset:文档中实际使用的字符集,也可以用来指定新字符集;
  • document.defaultCharset:表示根据浏览器及操作系统的设置,当前文档默认的字符集应该是什么,注意兼容性。
5. 自定义数据属性

HTML5规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。

代码语言:javascript
复制
<div id="div" data-status="1" data-appId="123" data-customName="ligang">哈哈</div>

添加了自定义属性后,可以通过元素的dataset属性来访问自定义属性的值。

代码语言:javascript
复制
var div = document.getElementById("div");
var dataset = div.dataset;
console.log(dataset.appid);     // 123
console.log(dataset.customname);    // "ligang" 注意,都是小写
6. 插入标记

DOM操作文档插入HTML标记非常复杂,因为其不仅要创建一系列DOM节点,而且还要小心地按照正确顺序进行连接。详见:DOM 示例:创建a标签并插入到body

代码语言:javascript
复制
var a = document.createElement("a");
a.href = "http://blog.csdn.net/ligang2585116";
a.text = "http://blog.csdn.net/ligang2585116";
document.body.appendChild(a);

使用插入标记的技术,直接插入HTML字符串不仅简单而且速度更快。

(1)innerHTML属性 读模式:返回调用元素的所有节点(包括元素、注释和文本节点)对应的HTML标记; 写模式:根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。 示例:创建a标签并插入到body

代码语言:javascript
复制
document.body.innerHTML += '<a href="http://blog.csdn.net/ligang2585116">http://blog.csdn.net/ligang2585116</a>'

注意:上述使用“+=”,因为写模式下,innerHTML的值会被解析为DOM子树,替换调用元素原来的所有子节点。 说明:使用innerHTML插入的字符串开头是一个无作用域的元素(<script>、<style>)时,IE会在解析这个字符串前先删除该元素。

代码语言:javascript
复制
div.innerHTML = "<script>console.logt('hi')</script>";  // 无效
div.innerHTML = "<div>&nbsp;</div><script>console.logt('hi')</script>"; // 有效
div.innerHTML = "<input type=\"hidden\"><script>console.logt('hi')</script>"; // 有效

(2)outerHTML属性 读模式:返回调用它的元素及所有节点(包括元素、注释和文本节点)对应的HTML标记; 写模式:根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素。 示例:

代码语言:javascript
复制
<div id="blog">
    <!-- blog address -->
    <a href="http://blog.csdn.net/ligang2585116">blog</a>
</div>
代码语言:javascript
复制
var div = document.getElementById("blog");
div.outerHTML;  // 整个innerHTML内容+div本身
div.outerHTML = "<a href=\"http://blog.csdn.net/ligang2585116\">blog</a>";  // 整个div会被a标签替换掉

// 等价于
var a = document.createElement("a");
a.href = "http://blog.csdn.net/ligang2585116";
a.text = "blog";
div.parentNode.replaceChild(a, div);

(3)内存与性能问题 使用上述节点方法可能会导致浏览器的内存占用问题。在删除带有事件处理程序或引用了其他JavaScript对象子树时,就会导致内存占用问题。在使用innerHTML、outerHTML等方法时,最好先删除要替换的元素的所有事件处理程序和JavaScript对象属性。

7. scrollIntoView()方法

如何滚动页面也是DOM规范没有解决的一个问题,HTML5最终选择了scrollIntoView作为标准。 scrollIntoView()可以在任何元素上调用。默认或传入true,窗口会滚动让调用元素与视口顶部尽可能齐平;传入false,调用元素尽可能会全部出现在窗口中。

代码语言:javascript
复制
document.forms[0].scrollIntoView();

当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。

四、专有扩展

1. children属性

children属性与childNodes没有什么区别。

2. contains()方法

判断某个节点是不是另一个节点的后代。

代码语言:javascript
复制
document.body.contains(div); // true

掩码

节点关系

1

无关(给定的节点不再当前文档中)

2

居前(给定的节点在DOM树中位于参考节点之前)

4

居后(给定的节点在DOM树中位于参考节点之后)

8

包含(给定的节点是参考节点的祖先)

16

被包含(给定的节点是参考节点的后代)

示例:通用的contains函数

代码语言:javascript
复制
function contains(refNode, otherNode){
    if (typeof refNode.contains == "function" && 
            (!client.engine.webkit || client.engine.webkit >= 522)){
        return refNode.contains(otherNode);
    } else if (typeof refNode.compareDocumentPosition == "function"){
        return !!(refNode.compareDocumentPosition(otherNode) & 16);
    } else {
        var node = otherNode.parentNode;
        do {
            if (node === refNode){
                return true;
            } else {
                node = node.parentNode;
            }
        } while (node !== null);
        return false;
    }
}
console.log(contains(document.documentElement, document.body)); // true
3. 插入文本

innerTextouterText并没有被纳入HTML5。 其对文本进行操作,使用方式类似于innerHTMouterHTML

4. 滚动

HTML5将scrollIntoView()方法纳入规范之后,仍还有其他几个专有方法可以在不同的浏览器中使用。 (1)scrollIntoViewIfNeeded(alignCenter):只在当前元素视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。true,尽量将元素在显示视口中部(垂直方向)。

scrollIntoViewIfNeeded兼容性
scrollIntoViewIfNeeded兼容性

(2)scrollByLines(lineCount):将元素的内容滚动指定的行高。 (3)scrollByPages(pageCount):将元素的内容滚动指定的页面高度,具体高度由元素的高度决定。 注意scrollIntoView()scrollIntoViewIfNeeded()的作用对象是元素的容器;scrollByLines()scrollByPages()影响的则是元素自身。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年11月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、选择符API
    • 1. querySelector()方法
      • 2. querySelectorAll()方法
        • 3. matchesSelector()方法
        • 二、元素遍历
        • 三、HTML5
          • 1. 与类相关的扩充
            • 2. 焦点管理
              • 3. HTMLDocument的变化
                • 4. 字符集属性
                  • 5. 自定义数据属性
                    • 6. 插入标记
                      • 7. scrollIntoView()方法
                      • 四、专有扩展
                        • 1. children属性
                          • 2. contains()方法
                            • 3. 插入文本
                              • 4. 滚动
                              相关产品与服务
                              容器服务
                              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档