From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../html_in_xmlhttprequest/index.html | 194 +++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest/index.html (limited to 'files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest') diff --git a/files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest/index.html b/files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest/index.html new file mode 100644 index 0000000000..74e8cac761 --- /dev/null +++ b/files/zh-cn/web/api/xmlhttprequest/html_in_xmlhttprequest/index.html @@ -0,0 +1,194 @@ +--- +title: HTML in XMLHttpRequest +slug: Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest +translation_of: Web/API/XMLHttpRequest/HTML_in_XMLHttpRequest +--- +

W3C {{domxref("XMLHttpRequest")}} 规范为 XMLHttpRequest添加HTML语法解析功能, 此前仅支持XML语法解析。该功能允许Web应用程序使用XMLHttpRequest作为解析的DOM。

+ +

局限

+ +

为了阻止同步使用XMLHttpRequest,HTML在同步模式下不支持使用。并且,只有当responseType属性设置为'document'的情况下,HTML支持才可用。这种限制避免了浪费时间解析HTML,而传统代码在默认模式下使用XMLHttpRequest来检索text/html资源的responseText. 此外,该限制避免了遗留代码的问题,该代码假定Http错误页面(通常具有text/html响应正文)的responseXML为空。

+ +

用法

+ +

使用XMLHttpRequest将HTML资源恢复为DOM就像使用XMLHttpRequest将XML资源恢复为DOM一样,除了您不能使用同步模式,您必须通过将字符串“document”分配给responseType属性来显式请求文档调用open()之后调用send()之前的XMLHttpRequest对象。

+ +

 

+ +
var xhr = new XMLHttpRequest();
+xhr.onload = function() {
+  console.log(this.responseXML.title);
+}
+xhr.open("GET", "file.html");
+xhr.responseType = "document";
+xhr.send();
+
+ +

功能检测

+ +

方法1

+ +

该方法依赖于功能的“强制异步”性质。当你尝试设置一个以“sync”方式打开的XMLHttpRequest对象后,尝试将设置responseType会在实现该功能的浏览器上引发错误,其他浏览器则运行良好。

+ +
+
function HTMLinXHR() {
+  if (!window.XMLHttpRequest)
+    return false;
+  var req = new window.XMLHttpRequest();
+  req.open('GET', window.location.href, false);
+  try {
+    req.responseType = 'document';
+  } catch(e) {
+    return true;
+  }
+  return false;
+}
+
+
+ +

在JSFiddle中查看

+ +

This method is synchronous, does not rely on external assets though it may not be as reliable as method 2 described below since it does not check the actual feature but an indication of that feature.

+ +

方法2

+ +

 

+ +

检测浏览器是否支持XMLHttpRequest中的HTML解析有两个挑战。首先,检测结果是异步获取的,因为HTML支持仅在异步模式下可用。Second, you have to actually fetch a test document over HTTP, because testing with a data: URL would end up testing data:URL support at the same time.

+ +

因此,为了检测HTML支持,服务器上需要一个测试HTML文件。这个测试文件很小,格式不是很完整:

+ +
<title>&amp;&<</title>
+ +

如果文件名为detect.html,以下功能可用于检测HTML解析支持:

+ +
function detectHtmlInXhr(callback) {
+  if (!window.XMLHttpRequest) {
+    window.setTimeout(function() { callback(false); }, 0);
+    return;
+  }
+  var done = false;
+  var xhr = new window.XMLHttpRequest();
+  xhr.onreadystatechange = function() {
+    if (this.readyState == 4 && !done) {
+      done = true;
+      callback(!!(this.responseXML && this.responseXML.title && this.responseXML.title == "&&<"));
+    }
+  }
+  xhr.onabort = xhr.onerror = function() {
+    if (!done) {
+      done = true;
+      callback(false);
+    }
+  }
+  try {
+    xhr.open("GET", "detect.html");
+    xhr.responseType = "document";
+    xhr.send();
+  } catch (e) {
+    window.setTimeout(function() {
+      if (!done) {
+        done = true;
+        callback(false);
+      }
+    }, 0);
+  }
+}
+
+ +

参数callback是一个函数,如果HTML解析是支持的,则将以true作为唯一参数被异步调用,如果不支持HTML解析,则为false。

+ +

在JSFiddle中查看

+ +

字符编码

+ +

如果在HTTP Content-Type 头部中声明了字符编码,则使用该字符编码。否则,如果存在字节顺序标记,则使用由字节顺序标记指示的编码。否则,如果有一个meta tag声明文件的前1024个字节中的编码,则使用该编码。否则,文件被解码为UTF-8。

+ +

老版本的浏览器中处理HTML

+ +

XMLHttpRequest最初只支持XML解析。 HTML解析支持是最近的一个补充。对于较老的浏览器,您甚至可以使用与正则表达式关联的responseText属性,以获取例如已知其ID的HTML元素的源代码:

+ +
function getHTML (oXHR, sTargetId) {
+  var  rOpen = new RegExp("<(?!\!)\\s*([^\\s>]+)[^>]*\\s+id\\=[\"\']" + sTargetId + "[\"\'][^>]*>" ,"i"),
+       sSrc = oXHR.responseText, aExec = rOpen.exec(sSrc);
+
+  return aExec ? (new RegExp("(?:(?:.(?!<\\s*" + aExec[1] + "[^>]*[>]))*.?<\\s*" + aExec[1] + "[^>]*[>](?:.(?!<\\s*\/\\s*" + aExec[1] + "\\s*>))*.?<\\s*\/\\s*" + aExec[1] + "\\s*>)*(?:.(?!<\\s*\/\\s*" + aExec[1] + "\\s*>))*.?", "i")).exec(sSrc.slice(sSrc.indexOf(aExec[0]) + aExec[0].length)) || "" : "";
+}
+
+var oReq = new XMLHttpRequest();
+oReq.open("GET", "yourPage.html", true);
+oReq.onload = function () { console.log(getHTML(this, "intro")); };
+oReq.send(null);
+
+ +
注: 该解决方案对于解释器来说更为昂贵. 仅在确实需要的情况下使用.
+ +

Specifications

+ + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('XMLHttpRequest')}}{{Spec2('XMLHttpRequest')}}Initial definition
+ +

Browser compatibility

+ +

{{CompatibilityTable}}

+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari (WebKit)
Support18{{CompatGeckoDesktop("11.0")}}10{{CompatUnknown}}{{CompatNo}}
+ {{CompatVersionUnknown}}[1]
+
+ +
+ + + + + + + + + + + + + + + + + + + +
FeatureAndroidFirefox Mobile (Gecko)IE PhoneOpera MobileSafari Mobile
Support{{CompatUnknown}}{{CompatGeckoMobile("11.0")}}{{CompatUnknown}}{{CompatUnknown}}{{CompatUnknown}}
+
+ +

[1] This feature was implemented in {{WebKitBug("74626")}}.

-- cgit v1.2.3-54-g00ecf