简体   繁体   English

附上 <head> 使用Javascript的元素与.innerHTML一起使用,但不能与XML子节点一起使用

[英]Attaching <head> elements with Javascript works with .innerHTML, but not XML child nodes

There are probably easier ways to do this, but I'm trying something new. 可能有更简单的方法来做到这一点,但我正在尝试一些新的东西。

The basic gist is that I want to have one JS and one jQuery attachment per head per page on my static website. 基本要点是我希望在我的静态网站上每页每个页面都有一个JS和一个jQuery附件。 I want to be able to append elements to the body, but head as well. 我希望能够将元素附加到身体上,但也可以。 My files are: 我的文件是:

home.html home.html的

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="eco.js"></script>
</head>

eco.js eco.js

window.addEventListener("load", function() {
    var ajax = new XMLHttpRequest();
    ajax.onload = postdata;
    ajax.open("GET", ADDRESS, true);
    ajax.send();
} );

function postdata() {
    var xml = jQuery.parseXML(this.responseText);
    $("head").append(xml.querySelector("head").childNodes);
}

and common.xml 和common.xml

<head>
    <link href='eco.css' type='text/css' rel='stylesheet' /> 
    <link href='home.css' type='text/css' rel='stylesheet' /> 
</head>

However, this does not work (common.xml is requested and retrieved successfully). 但是,这不起作用(请求并成功检索common.xml)。 Chrome dev tools show that the xml nodes are appended successfully as well, into the head. Chrome开发工具显示xml节点也成功附加到头部。 Yet the page does not reflect the changes, notably the css is not incorporated. 然而,该页面并未反映出这些变化,特别是css未被纳入。 However, if I change 但是,如果我改变了

    var xml = jQuery.parseXML(this.responseText);
    $("head").append(xml.querySelector("head").childNodes);

to

$("head").append(this.responseText);

(and fix the common.xml to remove the unneeded tags) then the page reflects changes. (并修复common.xml以删除不需要的标记)然后页面反映更改。 Could anyone explain what's going on here? 谁能解释一下这里发生了什么?

Thanks! 谢谢!

jQuery.parseXML() returns an XMLDocument object which represents a generic XML DOM, which is not compatible with the HTML DOM. jQuery.parseXML()返回一个XMLDocument对象,该对象表示与HTML DOM不兼容的通用XML DOM。

When you append your child nodes after parsing your XML file as XML, what you end up inserting are XML elements, not HTML elements. 在将XML文件解析为XML后附加子节点时,最终插入的是XML元素,而不是HTML元素。 Since an HTML processor only understands HTML link elements, it does not recognize them when they come from an XML DOM — they become unknown elements, and do not have their intended meaning. 由于HTML处理器只能理解HTML link元素,因此当它们来自XML DOM时它不会识别它们 - 它们变成未知元素,并且没有它们的预期含义。

When you append the response markup directly, that markup is interpreted as HTML because you are working directly with the HTML DOM in your page. 当您直接附加响应标记时,该标记将被解释为HTML,因为您正在直接使用页面中的HTML DOM。 This allows your link elements to work as intended, referencing external stylesheets for use with your page. 这允许您的link元素按预期工作,引用外部样式表以用于您的页面。


The following example, with a non-head element, demonstrates how a b element differs between HTML and XML using the same methods in your question. 以下示例使用非head元素,演示了如何使用问题中的相同方法在HTML和XML之间区分b元素。 In HTML, it represents text that is meant to stand out from a paragraph , with associated default styles. 在HTML中,它表示旨在从段落中脱颖而出的文本 ,以及相关的默认样式。 In plain XML, it's just an arbitrary element, with no default styles. 在纯XML中,它只是一个任意元素,没有默认样式。 In Firefox and IE, each b element also responds to namespaced CSS selectors correctly (note that they use the XHTML namespace even with HTML elements), although IE doesn't insert the XML element at all, instead throwing a WrongDocumentError . 在Firefox和IE中,每个b元素也正确响应命名空间的CSS选择器(请注意,即使使用HTML元素,它们也使用XHTML命名空间),尽管IE根本不插入XML元素,而是抛出WrongDocumentError The included CSS doesn't work very well in Chrome either — presumably because, as with IE, trying to wrangle HTML and XML together isn't exactly the smartest thing to do. 包含的CSS在Chrome中也不能很好地工作 - 大概是因为,与IE一样,尝试将HTML和XML纠缠在一起并不是最聪明的事情。

 $(function() { var html = '<b>HTML b element</b>'; var xml = '<root><b>XML b element</b></root>'; $('p.html').append(html); var xmlDoc = jQuery.parseXML(xml); $('p.xml').append(xmlDoc.querySelector(':root').childNodes); }); 
 @namespace 'http://www.w3.org/1999/xhtml'; b::before { content: 'Default namespace '; } |b::before { content: 'Non-namespaced '; } /* Any or no namespace */ *|b { color: blue; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <p class="html"></p> <p class="xml"></p> 

What's interesting is that if you use xml.querySelector("head").innerHTML rather than xml.querySelector("head").childNodes , it seems to work, despite the fact that the Element object is not an HTMLElement (ie xml.querySelector("head") instanceof HTMLElement returns false). 有趣的是,如果你使用xml.querySelector("head").innerHTML而不是xml.querySelector("head").childNodes ,它似乎工作,尽管Element对象不是HTMLElement (即xml.querySelector("head") instanceof HTMLElement返回false)。 According to this new answer by Louis , in the latest versions of Firefox and Chrome innerHTML represents the XML serialization of the contents of an XML element node, which explains this behavior. 根据Louis的这个新答案 ,在最新版本的Firefox和Chrome中, innerHTML表示XML元素节点内容的XML序列化,这解释了这种行为。 However, this particular quirk of innerHTML should not be relied on as it is not cross-browser compatible. 但是,不应该依赖innerHTML这个特殊怪癖,因为它不是跨浏览器兼容的。

Ultimately, your best option is to not parse your document as XML in the first place; 最终,您最好的选择是不首先将您的文档解析为XML; simply treat it as a regular HTML fragment by appending responseText directly, as jQuery is able to handle HTML fragments. 通过直接附加responseText简单地将其视为常规HTML片段,因为jQuery能够处理HTML片段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM