This is a paragraph with a list following it.
- Item 1
- Item 2
- Item 3
摘要:对的两个主要拓展是选择和。以下插入标记的拓展已经纳入了规范。在写模式下,会根据指定的字符串创建新的子树,然后用这个子树完全替换调用元素。在删除带有时间处理程序或引用了其他对象子树时,就有可能导致内存占用问题。
尽管DOM作为API已经非常完善了,但为了实现更多功能,仍然会有一些标准或专有的拓展。2008年之前,浏览器中几乎所有的拓展都是专有的,此后W3C着手将一些已经成为事实标准的专有拓展标准化,并写入规范中。
对DOM的两个主要拓展是Selectors API (选择API)和HTML5。这两个拓展都源自开发社区,而将某些常见做啊及API标准化,一直是众望所归。
选择符APIjQuery的核心就是通过CSS选择符查询DOM文档取得元素的引用,从而抛开了getElementById() 和 gettElementByTagName()。
Selectors API 是又W3C发起制定的一个标准,致力于让浏览器原生支持CSS查询。所有实现这一功能的JavaScript库都会写一个基础的CSS解析器,然后再使用已有的DOM方法查询文档并找到匹配的节点。而把这个功能变成原生API之后,解析和树查询操作可以在浏览器内部通过编译后的代码完成,极大改善了性能。
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 selected = document.querySelector("img.button");
如果传入了不支持的选择符,会抛出错误。
querySelectorAll()方法和上面类似,但返回的不仅仅是匹配的第一个元素,而是一个NodeList的实例,如果没有匹配,NodeList就是空的。
// 取得某div中所有em元素 var ems = document.getElementById("myDiv").querySelectorAll("em"); // 取得类为“selected”的所有元素 var selected = document.querySelectorAll(".selected"); // 取得所有p元素中的所有strong元素 var strongs = document.querySelectorAll("p strong");
取得返回NodeList中的每一个元素,可以使用item()方法,也可以使用方括号语法。
matchesSelector()方法Selector API Level2 规范为Element类型新增了一个matchesSelector()方法。接收一个参数,即CSS选择符,如果调用元素与该选择符匹配返回true,否则返回false。
截止2011年年中,还没有浏览器支持该方法,不过有一些实验性的实现。因此如果你想使用这个方法,最好编写一个包装函数:
function matchesSelector(element, selector) { if (element.matchesSelecotr) { return element.matchesSelecotr(selector) } else if (element.msMatchesSelecotr) { return element.msMatchesSelecotr(selector) } else if (element.mozMatchesSelecotr) { return element.mozMatchesSelecotr(selector) } else if (element.webkitMatchesSelecotr) { return element.webkitMatchesSelecotr(selector) } else { throw new Error("Not supported."); } }元素遍历
对于元素间的空格,IE9及之前版本不会返回文本节点,而其他所有浏览器都会返回文本节点。为了弥补这一差异,而又同时保持DOM规范不变,Element Traversal 规范新定义了一组属性。
childElementCount: 返回子元素(不包括文本节点和注释)的个数
firstElementChild: 指向第一个子元素;firstChild的元素版
lastElementChild: 指向最后一个子元素;lastChild的元素版
previousElementSibling: 指向前一个同辈元素;previousSibling的元素版
nextElementSibling: 指向前一个同辈元素;nextSibling的元素版
// 跨浏览器遍历某元素的所有子元素 // 老版的兼容性代码 var i, len, child = element.firstChild; while(child != element.lastChild) { // 检查是不是元素 if (child.nodeType == 1) { processChild(child); } child = child.nextSibling; } // 使用新版的方法 var i, len, child = element.firstChild; while(child != element.lastElementChild) { processChild(child); child = child.nextElementSibling; }
支持Element Traversal 规范的浏览器有 IE9+ Firefox3.5+ Safari4+ Chrome Opera10+
HTML5HTML5所有之前的版本对JavaScript接口的描述不过三言两语,主要篇幅都用于定义标记,与JavaScript相关的内容一概交由DOM规范去定义。
HTML5规范则围绕如何使用新增标记定义了大量JavaScript API。其中一些API与DOM重叠,定义了浏览器应该支持的DOM拓展。
由于HTML5涉及的面非常广,本节只讨论与DOM节点相关的内容。
与类(class)相关的扩充HTML5 新增了很多API,致力于简化CSS类的用法。
getElementsByClassName()方法// 取得所有类中包含"username"和"current"的元素 // 类名的先后顺序无所谓 var allCurrentUsernames = docment.getElementsByClassName("username current"); // 取得ID为"myDiv"的元素中带有类名"selected"的所有元素 var selected = document.getElementById("myDiv").getElemenstByClassName("selected");
支持getElementsByClassName()方法的浏览器 IE9+ Firefox3+ Safari3.1+ Chrome Opera9.5+
classList属性在操作类名时,需要通过className属性添加、删除和替换类名。因为className中是一个字符串,所以即使只是修改字符串一部分,也必须每次都设置整个字符串的值。
HTML5 新增了一种操作类名的方式,可以让操作更简单也更安全,那就是为所有元素添加了classList属性。
classList属性是新集合类型 DOMTokenList的实例。与其他DOM集合类似,DOMTokenList 有一个表示自己包含多少元素的length属性,而要去的每个元素可以使用item()方法,或者方括号语法。此外,这个新类型还定义如下方法:
add(value): 将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
contains(value): 表示列表中是否存在给定的值,如果存在返回true,反之false。
remove(value): 从列表中删除给定的字符串。
toggle(value): 如果列表中已经存在给定的值,删除它;如果没有,添加它。
有了classList属性,除非你需要删除所有类名,或者完全重写元素的class属性,否则就用不到className属性了。
支持classList的浏览器 Firefox3.6+ Chrome
焦点管理HTML5添加了辅助DOM焦点的功能。
document.activeElement属性,始终会引用DOM中当前获得了焦点的元素。元素获得焦点的方式有页面加载、用户输入(通常是通过Tab键)和在代码中调用focus()方法。
var button = document.getElementById("myButton"); button.focus(); console.log(document.activeElement === button); // true
默认情况下,文档刚刚加载完成时,document.activeElement中保存的是document.body元素的引用。文档加载期间,document.activeElement的值为null
document.hasFocus()方法,这个方法用于确定文档是否获得了焦点。
var button = document.getElementById("myButton"); button.focus(); console.log(document.hasFocus()); // true
支持的浏览器 IE4+ Firefox3+ Safari4+ Chrome Opera8+
HTMLDocument的变化 readyState属性
Document.readyState属性有两个可能的值:
loading正在加载文档
complete已经加载完文档
支持的浏览器 IE4+ Firefox3.6+ Safari Chrome Opera9+
if (document.readyState == "complete") { ... }兼容模式
自从IE6开始区分渲染页面的模式是标准的还是混杂的,检测页面的兼容性就成为浏览器的必要功能。IE为此给document添加了一个名为compatMode的属性,告诉开发人员浏览器采用了哪种渲染模式。
document.compatMode标准模式下等于"CSS1Compat",混杂模式下等于"BackCompat"。
最终HTML5将这个属性纳入标准
支持的浏览器 IE Firefox Safari3.1 Chrome Opera
if (document.compatMode == "CSS1Compat") { console.log("Standards mode"); } else { console.log("Quirks mode"); }head属性
HTML5新增了document.head属性,与docuemnt.body对应
支持的浏览器 Chrome Safari 5+
var head = document.head || document.getElementsByTagName("head")[0];字符集属性
HTML5新增了几个与文档字符集有关的属性
charset属性表示文档中实际使用的字符集,也可以用来指定新字符集。默认值是"UTF-16",可以通过元素、响应头部或直接设置charset属性修改这个值。
支持的浏览器 IE Safari Opera Chrome 。 Firefox 支持 document.Characterset。
console.log(document.charset); // "UTF-16" document.charset = "UTF-8";
defaultCharset表示根据默认浏览器及操作系统的设置,当前文档默认的字符集应该是什么。如果文档没有使用默认的字符集,那charset和defaultCharset属性值可能会不一样。
if (document.charset != document.defaultCharset) { console.log("Custom character set being used."); }
支持的浏览器 IE Safari Chrome 。
自定义数据属性HTML5 规定可以为元素添加非标准的属性,但要添加前缀data- ,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加、随便明明,只要以data-开头即可。
添加了自定义属性之后,可以通过元素的dataset属性来访问自定义属性的值。dataset属性的值时DOMStringMap的实例,也就是一个名值对的映射。在这个映射中,每个data-name形式的属性都会有一个对应的属性,只不过属性没有data-前缀。
var div = document.getElementById("myDiv"); // 取得自定义属性的值 var appId = div.dataset.appId; var myName = div.dataset.myname; // 设置值 div.dataset.appId = 2345; div.dataset.myname = "Michael"; // 有没有"myname"值呢? if (div.dataset.myname) { console.log("Hello, " + div.dataset.myname); }插入标记
虽然DOM为操作节点提供了细致入微的控制手段,但在需要给文档插入大量HTML标记的情况下,通过DOM操作仍然非常麻烦,因为不仅要创建一系列DOM节点,还要小心按照正确的顺序把它们连接起来。
相对而言,直接插入HTML字符串不仅更简单,速度也更快。以下插入标记的DOM拓展已经纳入了HTML5规范。
innerHTML属性在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML标记。
在写模式下,innerHTML会根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。
This is a paragraph with a list following it.
- Item 1
- Item 2
- Item 3
This is a paragraph with a list following it.
不同浏览器返回的文本格式不会有所不同。IE和Opera会将所有标签转换为大小写形式,而Safari、Chrome、Firefox则会原原本本的按照原先文档中(或指定这些标签时)的格式返回HTML,包括空格和缩进。
在写模式下,传入innerHTML的值都会按照浏览器处理HTML的标注方式转换为元素(同样因浏览器而异)。如果设置的值仅是纯文本而没有HTML标签,那么结果就是设置纯文本。
div.innerHTML = "Hello world!"; div.innerHTML = "Hello & welcom, "reader"!"; // 以上操作得到:Hello & welcome, "reader"!
使用innerHTML属性也有一些限制,大多数浏览器中通过innerHTML插入元素并不会执行其中的脚本。IE8及更早的版本是唯一能够在这种情况下执行脚本的浏览器,但必须满足2个条件:
元素指定defer属性
元素必须位于(微软所谓的)“有作用域的元素”(scoped element)之后。元素被认为是“无作用域的元素”(NoScoped element),也就是在页面中看不到的元素,与元素或注释类似。
没有(不支持)innerHTML属性的元素有:
IE8及更早版本 Firefox在内容类型为application/xhtml+xml的XHTML文档中设置innerHTML有严格的限制。在XHTML文档中使用innerHTML时,XHTML代码必须完全符合要求。 在读模式下,outerHTML返回调用它的元素及所有子节点的HTML标签。 在写模式下,outerHTML会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。 在元素上调用outerHTML会返回相同的代码,包括元素本身。由于浏览器解析和解释HTML标记的不同,结果可能会有所不同。 This is a paragraph with a list following it. This is a paragraph with a list following it. 使用outerHTML属性,会替换调用的元素本身 This is a paragraph. 支持的浏览器 IE4+ Safari4+ Chrome Opera8+ Firefox8+
insertAdjacentHTML()接收两个参数:插入位置和要插入的HTML文本。
第一个参数必须是下列之一: "beforebegin" 在当前元素之前插入一个紧邻的同辈元素 "afterbegin" 在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素 "beforeend" 在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素 "afterend" 在当前元素之后插入一个紧邻的同辈元素 第二个参数是HTML字符串,如果浏览器无法解析该字符串,就会抛出错误。 Hello world! Hello world! Hello world! Hello world! 支持的浏览器 IE Firefox8+ Safari Opera Chrome 使用本节介绍的方法替换子节点可能会导致浏览器的内存占用问题,尤其是IE,问题更加明显。 在删除带有时间处理程序或引用了其他JavaScript对象子树时,就有可能导致内存占用问题。假设某个元素有一个时间处理程序(或者引用了一个JavaScript对象作为属性),在使用前述某个属性将该元素从文档树删除后,元素与事件处理程序(或JavaScript对象)之间的绑定关系在内存中并没有一并删除。如果这种情况频繁出现,页面占用的内存数量就会明显增加。 因此,在使用innerHTML outerHTML insertAdjacentHTML() 时,最好先手工删除要被替换的元素的所有事件处理程序和JavaScript对象属性(第13章将进一步讨论事件处理程序)。 不过使用这几个属性,特别是innerHTML仍然还是可以为我们提供很多遍历的。插入大量HTML标记时,设置innerHTML或outerHTML时就会创建一个HTML解析器,这个解析器是在浏览器级别的代码(通常是C++编写的)基础上运行的,因此比执行JavaScript快的多。 创建和销毁HTML解析器也会带来性能损失,所以最好能够将设置innerHTML或outerHTML的次数控制在合理的范围内。 如何滚动页面也是DOM规范没有解决的一个问题。HTML5最终选择了scrollIntoView()作为标准方法。
scrollIntoView()可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。 如果传入true作为参数,或者不传任何参数,那么窗口滚动之后会让调用元素的顶部与视口顶部尽可能的平齐。 如果传入false作为参数,调用元素会尽可能全部出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐)不过顶部不一定平齐。 当页面发生变化时,一般会用这个方法来吸引用户的注意力。实际上,为某个元素设置焦点也会导致浏览器滚动并显示出获得焦点的元素。 支持的浏览器 IE Firefox8+ Safari Opera 虽然所有浏览器开发商都知晓坚持标准的重要性,但在发现某项功能缺失时,这些开发商都会一如既往的向DOM中添加专有拓展,以弥补功能上的不足。 表面上看不太友好,但实际上专有拓展为Web开发领域提供了很多重要的功能,这些功能最终都在HTML5规范中得以标准化。 即便如此,仍然还有大量专有的DOM拓展没有成为标准。编写本书时,它们还是专有功能,而且只得到了少数浏览器的支持
IE8引入了一个新的概念叫“文档模式”(document mode)。页面的文档模式决定了可以使用什么功能。换言之,文档模式决定了你可以使用哪个级别的CSS,可以在JavaScript中使用哪些API,以及如何对待文档类型(doctype)。到了IE9总有有以下4种文档模式: IE5: 以混杂模式渲染页面(IE5的默认模式就是混杂模式)。IE8及更高版本中的新功能都无法使用。 IE7: 以IE7标准模式渲染页面。IE8及更高版本中的新功能都无法使用 IE8: 以IE8标准模式渲染页面。IE8新功能都能用,包括 Selectors API 、更多CSS2级选择符和某些CSS3功能,还有一些HTML5功能。不能使用IE9中的新功能。 IE9: 以IE9标准模式渲染页面。IE9新功能都能用,包括 ECMAScript 5 、完整的CSS3级,更多HTML5功能。 要强制浏览器以某种模式渲染页面,可以使用HTTP头部信息X-UA-Compatible或等价的标签来设置。
这里的IE版本(IEVersion)有以下不同的值,不一定与上述4中文档模式对应。
Edge: 始终以最新的文档模式来渲染页面。忽略文档类型声明。
EmulateIE9: 如果有文档类型声明,则以IE9标准模式渲染,否则将文档模式设置为IE5。
EmulateIE8: 如果有文档类型声明,则以IE8标准模式渲染,否则将文档模式设置为IE5。
EmulateIE7: 如果有文档类型声明,则以IE7标准模式渲染,否则将文档模式设置为IE5。
9: 强制以IE9标准模式渲染页面,忽略文档类型声明
8: 强制以IE8标准模式渲染页面,忽略文档类型声明
7: 强制以IE7标准模式渲染页面,忽略文档类型声明
5: 强制将文档模式设置为IE5,忽略文档类型声明
document.documentMode 属性可以知晓给定页面使用的是什么文档模式,它会返回文档模式的版本号(在IE9中,可能返回的版本号为5、7、8、9) IE9之前的版本处理空白符与其他浏览器有差异,因此出现了children属性。这个属性是HTMLCollection的实例,只包含元素中同样还是元素的子节点。除此之外,children 与 childNodes没有区别。 IE8及更早版本的children属性中也会包含注释节点,但IE9之后的版本只返回元素节点。 支持的浏览器 IE5 Firefox 3.5 Safari2(有bug) Safari3 Opera8 和Chrome
contains() 祖先节点调用这个方法,接收一个参数是要检查的后代节点。如果祖先节点包含传入的后代节点返回true,否则false。 支持的浏览器 IE9+ Firefox Safari Opera Chrome 使用DOM Level 3 compareDocumentPosition()也能够确定节点间的关系。 这个方法确定两个节点间的关系,返回表示该关系的位掩码(bitmask) 支持的浏览器 IE9+ Firefox Safari Opera9.5 Chrome 为模仿contains()方法,应该关注的是掩码16.可以对compareDocumentPosition()的结果执行按位与。 执行上面的代码后,结果会变成20(表示“居后”的4加上表示“被包含”的16)。对掩码16执行安慰操作会返回一个非零数值,而两个逻辑非操作符会将该数值转换成布尔值。 注意: 回值可以是值的组合。例如,返回 20 意味着在 p2 在 p1 内部(16),并且 p1 在 p2 之前(4)。 使用一些浏览器及能力检测,就可以写出如下所示的一个通用的contains函数:
IE原来有innerHTML和outerHTML已被HTML5纳入规范。但另外两个插入文本的专有属性则没有这么好的运气。 innerText outerText
scrollIntoView()纳入规范后,仍有几个专有方法可以在不同浏览器中使用。下列都是对HTMLElement类型的扩展,因此在所有元素中都可以调用:
scrollIntoViewIfNeeded(alignCenter): 只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素可见,这个方法什么都不会做。如果将可选的alignCenter参数设置为true,则表示尽量将元素显示在视口中部(垂直方向)。Safari和Chrome实现了这个方法
scrollByLines(lineCount): 将元素的内容滚动到指定的行高,lineCount可以是正值也可以是负值。Safari和Chrome实现了这个方法
scrollByPages(lineCount): 将元素的内容滚动到指定的页面高度,具体高度由元素的高度决定。Safari和Chrome实现了这个方法 需要注意的是,scrollIntoView()和scrollIntoViewIfNeeded()的作用对象是元素的容器,而scrollByLines()和scrollByPages()影响的是元素自身
scrollIntoView()是唯一一个所有浏览器都支持的方法,因此最常用。 文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。 转载请注明本文地址:https://www.ucloud.cn/yun/109699.html 摘要:表示应该立即下载脚本,但不应妨碍页面中的其他操作可选。表示通过属性指定的代码的字符集。表示脚本可以延迟到文档完全被解析和显示之后再执行。实际上,服务器在传送文件时使用的类型通常是,但在中设置这个值却可能导致脚本被忽略。
第1章 JavaScript 简介
虽然JavaScript和ECMAScript通常被人们用来表达相同的含义,但JavaScript的含义比ECMA-262要多得多... 摘要:用户代理检测用户代理检测是争议最大的客户端检测技术。第二个要检测是。由于实际的版本号可能会包含数字小数点和字母,所以捕获组中使用了表示非空格的特殊字符。版本号不在后面,而是在后面。除了知道设备,最好还能知道的版本号。
检测Web客户端的手段很多,各有利弊,但不到万不得已就不要使用客户端检测。只要能找到更通用的方法,就应该优先采用更通用的方法。一言蔽之,先设计最通用的方案,然后再使用特定... 摘要:年月级规范成为的推荐标准,为基本的文档结构及查询提供了接口。这意味着中的对象与原生对象的行为或活动特点并不一致。结果第一条注释就会成为中的第一个子节点。由于跨域安全限制,来自不同子域的页面无法通过通信。
DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。DOM脱胎于Netsc... 摘要:技术的核心是对象即。收到响应后,响应的数据会自动填充对象的属性,相关的属性有作为响应主体被返回的文本。收到响应后,一般来说,会先判断是否为,这是此次请求成功的标志。中的版本会将设置为,而中原生的则会将规范化为。会在取得时报告的值为。
Ajax(Asynchronous Javascript + XML)技术的核心是XMLHttpRequest对象,即: XHR。虽然名字中包含XML,但... 阅读 775·2023-04-25 19:49 阅读 3716·2021-09-30 09:47 阅读 2719·2021-09-13 10:21 阅读 2643·2021-08-24 10:04 阅读 3149·2019-08-30 15:55 阅读 2201·2019-08-30 15:55 阅读 2371·2019-08-30 15:54 阅读 3447·2019-08-30 13:53
div.outerHTML = "
// 作为前一个同辈元素插入
element.insertAdjacentHTML("beforebegin", "
document.documentElement.contains(document.body); // true
掩码
节点关系
1
无关(给定的节点不在当前文档中)
2
居前(给定的节点在DOM树中位于参考节点之前)
4
居后(给定的节点在DOM树中位于参考节点之后)
8
包含(给定的节点是参考节点的祖先)
16
包含(给定的节点是参考节点的后代)
var result = document.documentElement.compareDocumentPosition(document.body);
console.log(!!(result & 16));
function contains(refNode, otherNode) {
if (typeof refNode.contains == "function" &&
(!client.engine.webkit || client.engine.webkit >= 522)) {
// 浏览器支持contains方法直接使用
return refNode.contains(otherNode);
} else if (typeof refNode.compareDocumentPosition == "function") {
// 浏览器支持compareDocumentPosition方法
// 用返回结果和16进行按位与,再转换成布尔值返回
return !!(refNode.compareDocumentPosition(otherNode) & 16);
} else {
// 针对Safari设计的验证方法
// 在文档树中向上递归验证是否有refNode
// 到达文档树顶端,parentNode 的值为null,循环结束
var node = otherNode.parentNode;
do {
if (node === refNode) {
return true;
} else {
node = node.parentNode;
}
} while (node !== null);
return false;
}
}
插入文本
// 将页面主体滚动5行
document.body.scrollByLines(5);
// 在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();
// 将页面主体往回滚动1页
document.body.scrollByPages(-1);
相关文章
《JavaScript高级程序设计》(第3版)读书笔记 第1~2章
《JavaScript高级程序设计》(第3版)读书笔记 第9章 客户端检测
《JavaScript高级程序设计》(第3版)读书笔记 第10章 DOM
Ajax与Comet-JavaScript高级程序设计第21章读书笔记(1)
发表评论
0条评论
luck
男|高级讲师
TA的文章
阅读更多
pycharm配置tensorflow
STM32 硬件IIC OLED
数脉科技:9月中秋特惠优惠促销,全场首月5折,阿里云华为云10MbpsCN2,首月165元,自营CN
SoftShellWeb:圣何塞/台湾/荷兰VPS促销,$3.00/月起,KVM虚拟化,自带DDOS
前端开发API及规范
在微信小程序中创建属于自己的个性弹框
视窗单位-vw/vh/vmin/vmax
C3的坑之inline-block