javascript--第11章--DOM扩展

原文链接:https://www.cnblogs.com/xiaoxiaoyihan/p/5692133.html

DOM1级主要定义了文档的底层结构,并提供了基本的查询操作的API,总体而言这些API已经比较完善,我们可以通过这些API完成大部分的DOM操作。然而,为了扩展DOM API的功能,同时进一步提高DOM操作的效率,DOM扩展也不断被提出和采纳。对DOM的扩展主要有两部分:Selectors API和HTML5,另外还有一个Element Traversal规范,主要用于元素遍历,另外还有一些专有扩展。


Selectors API

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

querySelector()方法

querySelector()方法接收一个CSS选择符,返回与该模式匹配的第一个元素;如果没有匹配元素,返回null。

// 获取body元素
var body = document.querySelector("body");

// 获取ID为“myDiv”的元素
var myDiv = document.querySelector("#myDiv");

// 获取类为“selected”的第一个元素
var selected = document.querySelector(".selected");

// 取得类为“button”的第一个图像元素
var img = document.body.querySelector("img.button");

querySelectorAll()方法

querySelectorAll()同样接收一个CSS选择符,返回的是所有匹配的元素,是一个NodeList实例。

// 取得某<div>中所有<em>元素
var ems = document.getElementById("myDiv").querySelectorAll("em");

// 获取类为selected的所有元素
var selecteds = document.querySelectorAll(".selected");

// 取得所有<p>元素中的所有<strong>元素
var strongs = document.querySelectorAll("p strong");

// 遍历NodeList
var i, len, strong;
for (i = 0, len = strongs.length; i < len; i++) {
    strong = strongs[i];// strong = strongs.item(i);
    strong.className = "important";
}

matchesSelector()方法

Selectors API Level2新增了matchesSelector(),它接收一个CSS选择符,如果调用元素与该选择符匹配,返回true,否则返回false。

if (document.body.matchesSelector("body.page1")) {
    // true
}

元素遍历

以往遍历元素的方式:

var i,
    len,
    child = element.firstChild;
while (child != element.lastChild) {
    if (child.nodeType == 1) {  // 检查是否元素
        processChild(child);
    }
    child = child.nextSibling;
}

使用Element Traversal新增的元素:

var i,
    len,
    child = element.firstElementChild;
while (child != element.lastElementChild) {
    processChild(child);
    child = child.nextElementSibling;
}

HTML5

getElementsByClassName()方法

getElementsByClassName()接收一个参数,即一个包含一或多个类名的字符串,返回带有指定类的所有元素的NodeList。

// 取得所有类中包含“username”和“current”元素+
var allCurrentUsernames = document.getElementsByClassName("username current");

// 获取ID为“myDiv”的元素中带有类名“selected”的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");

classList属性

HTML5新增了一种操作类名的方式:

// 删除“disabled”类
div.classList.remove("disabled");

// 添加“current”类
div.classList.add("current");

// 切换“user”类
div.classList.toggle("user");

// 确定元素中是否包含既定的类名
if (div.classList.contains("bd") && !div.classList.contains("disabled")) {
    // 执行操作
}

焦点管理

HTML5添加了管理DOM焦点的功能。document.activeElement属性始终会引用DOM中当前获得了焦点的元素。focus()获取焦点,hasFocus()判断是否获取焦点

var button = document.getElementById("myButton");

// 获取焦点
button.focus();

alert(document.activeElement === button);   // true
alert(button.hasFocus());   // true

HTMLDocument的变化

readyState属性

Document的readyState属性有两个可能的值:

  • loading:正在载入文档
  • complete:已经加载完文档

document.readyState属性基本用法:

if (document.readyState == "complete") {
    // ...
}
兼容模式

检测页面的兼容模式是浏览器必要的功能。在标准模式下,document.compatMode的值等于“CSS1Compat”,而混杂模式下,document.compatMode的值等于“BackCompat”。

if (document.compatMode == "CSS1Compat") {
    alert("Standards mode");
} else {
    alert("Quirks mode");
}
head属性和字符集属性

HTML5新增了document.head元素,引用文档的<head>元素

var head = document.head;
var head = document.getElementsByTagName("head")[0];

HTML5新增了document.charset元素,表示文档中实际使用的字符集。可以通过<meta>元素、响应头或直接设置charset属性修改。

alert(document.charset);     
document.charset = "UTF-8";

另一个属性defaultCharset,表示根据默认浏览器及曹组系统的设置。如果文档中没有使用默认的字符集,那charset和defaultCharset可能不一致。

if (document.charset != document.defaultCharset) {
    // ...
}

innerHTML属性

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

<div id="content">
    <p>This is a <strong>para.</strong> with a list following it.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

对于上面的<div>元素而言,它的innerHTML属性会返回如下字符串

<p>This is a <strong>para.</strong> with a list following it.</p>
<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>

写模式下,innerHTML的值会被解析为DOM字数,替换调用元素原来的所有子节点。

div.innerHTML = "Hello javascript";

为innerHTML设置的包含HTML的字符串值与解析后innerHTML的值不相同。

div.innerHTML = "Hello & welcome, <b>\"reader\"!</b>";

结果如下:

<div id="content">Hello &amp; welcome, <b>&quot;reader&quot;!</b></div>

原因在于返回的字符串是根据原始HTML字符串创建的DOM树经过序列化之后的结果。

在大多数浏览器中,innerHTML插入<script>元素并不会执行其中的脚本。

div.innerHTML = "<script defer>alert('hello');</script>";// 无效

如果需要插入这段脚本,必须在前面添加一个“有作用域的元素”。例如:

div.innerHTML = "<input type=\"hidden\"><script defer>alert('hello');</script>";

outerHTML属性

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

<div id="content">
    <p>This is a <strong>para.</strong> with a list following it.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

如果在<div>元素上调用outerHTML,会返回上面相同的代码。

使用outerHTML属性设置值:

div.outerHTML = "<p>This is a paragraph.</p>";

这行代码与下面的操作一样:

var p = document.createElement("p");
p.appendChild(document.createTextNode("This is a para."));
div.parentNode.replaceChild(p, div);

insertAdjacentHTML()方法

// 作为第一个同辈元素插入
element.insertAdjacentHTML("beforebegin", "<p>Hello javascript</p>");

// 作为第一个子元素插入
element.insertAdjacentHTML("afterbegin", "<p>Hello javascript</p>");

// 作为最后一个子元素插入
element.insertAdjacentHTML("beforeend", "<p>Hello javascript</p>");

// 作为后一个同辈元素插入
element.insertAdjacentHTML("afterend", "<p>Hello javascript</p>");

如何滚动页面也是DOM 规范没有解决的一个问题。为了解决这个问题,浏览器实现了一些方法,
以方便开发人员更好地控制页面滚动。在各种专有方法中,HTML5 最终选择了scrollIntoView()作
为标准方法。
scrollIntoView()可以在所有HTML 元素上调用,通过滚动浏览器窗口或某个容器元素,调用
元素就可以出现在视口中。如果给这个方法传入true 作为参数,或者不传入任何参数,那么窗口滚动
之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入false 作为参数,调用元素会尽可能全部

出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐。)不过顶部不一定平齐,例如:

[javascript]  view plain  copy
  1. //让元素可见  
  2. document.forms[0].scrollIntoView();  
当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导
致浏览器滚动并显示出获得焦点的元素。
支持scrollIntoView()方法的浏览器有IE、Firefox、Safari 和Opera。

文档模式

页面的文档模式是由IE8引入的,文档模式决定了可以使用的CSS级别、JS中的API以及如何对待文档类型(doctype);在IE9,提供了4中文档模式:

  • IE5:混杂模式;

  • IE7:IE7标准模式渲染页面;

  • IE8:IE8标准模式渲染页面,可以使用Selectors API、更多CSS2级选择符和某些CSS3功能、HTML5的一些功能;

  • IE9:IE9标准模式渲染页面,这个文档模式是最高级的模式;

要强制浏览器以某种模式渲染页面,可以使用HTTP头部信息X-UA-Compatible,或通过等价的meta标签来设置:

<meta http-equiv="X-UA-Compatible" content="IE-IEVersion">

其中IEVersion有以下取值:

  • Edge:始终以最新的文档模式来渲染页面;

  • EmulateIE9:如果有文档类型声明,以IE9标准模式渲染页面,否则将文档模式设置为IE5;

  • EmulateIE8:如果有文档类型声明,以IE8标准模式渲染页面,否则将文档模式设置为IE5;

  • EmulateIE7:如果有文档类型声明,以IE7标准模式渲染页面,否则将文档模式设置为IE5;

  • 9:强制以IE9标准模式渲染页面,忽略文档类型声明;

  • 8:强制以IE8标准模式渲染页面,忽略文档类型声明;

  • 7:强制以IE7标准模式渲染页面,忽略文档类型声明;

  • 5:强制以IE5标准模式渲染页面,忽略文档类型声明;

如:

<meta http-equiv="X-UA-Compatible" content="IE-EmulateIE7">

或直接使用IE7模式:

<meta http-equiv="X-UA-Compatible" content="IE-7">

通过document.documentMode属性可以知道给定页面使用的是什么文档模式。
children属性

该属性只包含元素中同样还是元素的子节点,除此之外,该属性与childNodes没区别;

console.log(document.body.children.length);

IE<9的浏览器有bug;

contains()方法和compareDocumentPosition()方法

前者调用的应该是祖先节点,接收一个参数即要检测的后代节点;后者则是DOM Level 3中的,会返回如下掩码:

  • Bits Number Meaning

  • 000000 0 元素一致

  • 000001 1 节点在不同的文档(或者一个在文档之外)

  • 000010 2 节点 B 在节点 A 之前

  • 000100 4 节点 A 在节点 B 之前

  • 001000 8 节点 B 包含节点 A

  • 010000 16 节点 A 包含节点 B

  • 100000 32 浏览器的私有使用

对于contains()方法,如下:

console.log(document.documentElement.contains(document.body)); //true

对于compareDocumentPosition()方法则:

var result = document.getElementById("divId").compareDocumentPosition(document.getElementById("pId"));
//4,给定的节点pId在参考的节点divId的后面,居后
var result = document.getElementById("pId").compareDocumentPosition(document.getElementById("divId"));
//2,给定的divId在参考的pId的前面,居前
var result = document.documentElement.compareDocumentPosition(document.body);
//20(16+4),给定的body被包含于参考的html中并且位于其之后
var result = document.body.compareDocumentPosition(document.documentElement);
//10(8+2),给定的html是参考的body的祖先并且位于其前
var result = document.body.compareDocumentPosition(document.body);
//0 元素一致;

插入文本

innerText属性

该属性可以操作元素中包含的所有文本内容;以下面代码示例:

<div id="content">
    <p>This is a <strong>paragraph</strong> with a list following it.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
    </ul>
</div>

其innerText属性会返回如下字符串:

This is a paragraph with a list following it.

Item 1
Item 2
Item 3

如果设置其innerText,则会变成这样:

document.getElementById("content").innerText = "hello there";

console.log(document.body.outerHTML);
// <body>
//     <div id="content">hello there</div>
//     <script src="testingjs.js"></script>
// </body>

如果在其中加入了html标签,则会变成这样:

document.getElementById("content").innerText = "<p>hello there</p>";

console.log(document.body.outerHTML);
// <body>
//     <div id="content">&lt;p&gt;hello there&lt;/p&gt;</div>
//     <script src="testingjs.js"></script>
// </body>

利用这一点可以用这个属性去掉所有的html标签,如下:

document.getElementById("content").innerText = document.getElementById("content").innerText;

console.log(document.body.outerHTML);
// <body>
//     <div id="content">This is a paragraph with a list following it.<br><br>Item 1<br>Item 2<br>Item 3</div>
//     <script src="testingjs.js"></script>
// </body>

值得注意的是Firefox虽然不支持innerText,但支持textContent属性。为了兼容性,应采用下面的代码:

function getInnerText(element) {
    if (typeof element.textContent == "string") {
        return element.textContent;
    } else {
        return element.innerText;
    }
}
function setInnerText(element, text) {
    if (typeof element.textContent == "string") {
        element.textContent = text;
    } else {
        element.innerText = text;
    }
}

outerText属性(尽量不要用)

innerText属性的区别:

var div = document.getElementById("content");
div.innerText = "hello there";
console.log(document.body.innerHTML); //<div id="content">hello there</div>

var div = document.getElementById("content");
div.outerText = "hello there";
console.log(document.body.innerHTML); //hello there

因为这个属性会导致调用它的元素不存在,因此这个属性并不常用

滚动

主要有以下几个方法:

  • scrollIntoView():true的话尽量显示在顶端,false的话则是底部;

  • scrollIntoViewIfNeeded(alignCenter):如果为true,则表示尽量将元素显示在视口中部;

  • scrollBy(xnum,ynum):xnum 必需,把文档向右滚动的像素数;ynum必需,把文档向下滚动的像素数。

另外,scrollByLinew(lineCount)以及scrollByPages(pageCount)这两个方法,在chrome测试了一下,并无反应。不知是否兼容问题。

下面是document获得焦点的时候,自动以每10毫秒的速度往下滚屏:

var x = setTimeout(focus, 10);
function focus() {
    if (document.hasFocus()) {
        window.scrollBy(0,1);
    }
var y = setTimeout(focus, 10);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值