XMLHttpRequest 中的 HTML

基线 广泛可用

此功能已得到充分确立,并且可在许多设备和浏览器版本中使用。它自以下时间起在所有浏览器中都可用: 2015 年 7 月.

W3C 的 XMLHttpRequest 规范为 XMLHttpRequest 添加了 HTML 解析支持,该规范最初仅支持 XML 解析。此功能允许 Web 应用使用 XMLHttpRequest 获取 HTML 资源作为已解析的 DOM

要概述如何普遍使用 XMLHttpRequest,请参阅 使用 XMLHttpRequest

限制

为了避免同步使用 XMLHttpRequest,在同步模式下无法使用 HTML 支持。此外,仅当 responseType 属性已设置为 "document" 时,才可以使用 HTML 支持。此限制避免在旧版代码以默认模式使用 XMLHttpRequest 检索 responseText 以获取 text/html 资源时无用地浪费时间解析 HTML。此外,此限制避免了旧版代码出现问题,这些代码假设对于 HTTP 错误页面(通常具有 text/html 响应正文),responseXMLnull

用法

使用 XMLHttpRequest 将 HTML 资源检索为 DOM 的方式与使用 XMLHttpRequest 将 XML 资源检索为 DOM 的方式相同,只是您不能使用同步模式,并且必须通过将字符串 "document" 分配给 XMLHttpRequest 对象的 responseType 属性来显式请求文档,此操作应在调用 open() 后但在调用 send() 之前进行。

js
const xhr = new XMLHttpRequest();
xhr.onload = () => {
  console.log(xhr.responseXML.title);
};
xhr.open("GET", "file.html");
xhr.responseType = "document";
xhr.send();

功能检测

方法 1

此方法依赖于该功能的“强制异步”特性。当您尝试在 XMLHttpRequest 对象打开为“同步”后设置其 responseType 为“document”时,这会在实现该功能的浏览器中引发错误,而在其他浏览器中则可以正常工作。

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

在 JSFiddle 上查看

此方法是同步的,不依赖于外部资源,尽管它可能不如下面描述的方法 2 可靠,因为它没有检查实际功能,而是检查该功能的指示。

方法 2

准确检测浏览器是否支持 XMLHttpRequest 中的 HTML 解析存在两个挑战。首先,检测结果是异步获取的,因为 HTML 支持仅在异步模式下可用。其次,您必须实际通过 HTTP 获取测试文档,因为使用 data: URL 进行测试将同时测试 data: URL 支持。

因此,要检测 HTML 支持,需要在服务器上有一个测试 HTML 文件。此测试文件很小,并且不是格式良好的 XML

html
<title>&amp;&<</title>

如果文件名为 detect.html,则可以使用以下函数来检测 HTML 解析支持

js
function detectHtmlInXhr(callback) {
  if (!window.XMLHttpRequest) {
    setTimeout(function () {
      callback(false);
    }, 0);

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

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

在 JSFiddle 上查看

字符编码

如果在 HTTP Content-Type 标头中声明了字符编码,则使用该字符编码。否则,如果存在字节顺序标记,则使用字节顺序标记指示的编码。否则,如果在文件的前 1024 个字节内存在声明编码的 <meta> 元素,则使用该编码。否则,将文件解码为 UTF-8。

规范

规范
XMLHttpRequest 标准
# interface-xmlhttprequest

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅