为什么要 y.innerHTML = x.innerHTML;被避免? [英] Why should y.innerHTML = x.innerHTML; be avoided?

查看:28
本文介绍了为什么要 y.innerHTML = x.innerHTML;被避免?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们在页面上有一个 DIV x 并且我们想要将该 DIV 的内容复制(复制粘贴")到另一个 DIV y 中.我们可以这样做:

Let's say that we have a DIV x on the page and we want to duplicate ("copy-paste") the contents of that DIV into another DIV y. We could do this like so:

y.innerHTML = x.innerHTML;

或使用 jQuery:

or with jQuery:

$(y).html( $(x).html() );

但是,这种方法似乎不是一个好主意,应该避免使用.

However, it appears that this method is not a good idea, and that it should be avoided.

(1) 为什么要避免这种方法?

(1) Why should this method be avoided?

(2) 这应该怎么做?

(2) How should this be done instead?

更新:
为了这个问题,我们假设 DIV x 中没有带有 ID 的元素.
(对不起,我忘了在我原来的问题中提到这个案例.)

Update:
For the sake of this question let's assume that there are no elements with ID's inside the DIV x.
(Sorry I forgot to cover this case in my original question.)

结论:
我已经在下面发布了我自己对这个问题的回答(正如我最初打算的那样).现在,我也打算接受我自己的答案:P,但是lonesomeday 的答案太神奇了,我不得不接受它.

Conclusion:
I have posted my own answer to this question below (as I originally intended). Now, I also planed to accept my own answer :P, but lonesomeday's answer is so amazing that I have to accept it instead.

推荐答案

这种将 HTML 元素从一个地方复制"到另一个地方的方法是对浏览器功能的误解的结果.浏览器不会将 HTML 文档保存在内存中的某处,而是根据来自 JavaScript 的命令反复修改 HTML.

This method of "copying" HTML elements from one place to another is the result of a misapprehension of what a browser does. Browsers don't keep an HTML document in memory somewhere and repeatedly modify the HTML based on commands from JavaScript.

当浏览器首次加载页面时,它解析 HTML 文档并将其转换为 DOM 结构.这是遵循 W3C 标准的对象关系(嗯,主要是......).原来的 HTML 从那时起就完全多余了.浏览器并不关心原始的 HTML 结构是什么;它对网页的理解是从它创建的 DOM 结构.如果您的 HTML 标记不正确/无效,Web 浏览器将以某种方式对其进行更正;DOM 结构不会以任何方式包含无效代码.

When a browser first loads a page, it parses the HTML document and turns it into a DOM structure. This is a relationship of objects following a W3C standard (well, mostly...). The original HTML is from then on completely redundant. The browser doesn't care what the original HTML structure was; its understanding of the web page is the DOM structure that was created from it. If your HTML markup was incorrect/invalid, it will be corrected in some way by the web browser; the DOM structure will not contain the invalid code in any way.

基本上,HTML 应该被视为一种序列化 DOM 结构的方式,以便通过互联网传递或存储在本地文件中.

Basically, HTML should be treated as a way of serialising a DOM structure to be passed over the internet or stored in a file locally.

因此,它不应用于修改现有网页.DOM(文档对象模型)具有用于更改页面内容的系统.这是基于节点的关系,而不是 HTML 序列化.因此,当您将 li 添加到 ul 时,您有以下两个选项(假设 ul 是列表元素):

It should not, therefore, be used for modifying an existing web page. The DOM (Document Object Model) has a system for changing the content of a page. This is based on the relationship of nodes, not on the HTML serialisation. So when you add an li to a ul, you have these two options (assuming ul is the list element):

// option 1: innerHTML
ul.innerHTML += '<li>foobar</li>';

// option 2: DOM manipulation
var li = document.createElement('li');
li.appendChild(document.createTextNode('foobar'));
ul.appendChild(li);

现在,第一个选项看起来简单多了,但这只是因为浏览器为您抽象了很多:在内部,浏览器必须将元素的子元素转换为字符串,然后附加一些内容,然后转换字符串返回到 DOM 结构.第二个选项对应于浏览器对正在发生的事情的本机理解.

Now, the first option looks a lot simpler, but this is only because the browser has abstracted a lot away for you: internally, the browser has to convert the element's children to a string, then append some content, then convert the string back to a DOM structure. The second option corresponds to the browser's native understanding of what's going on.

第二个主要考虑是考虑 HTML 的局限性.当您考虑网页时,并非与元素相关的所有内容都可以序列化为 HTML.例如,与 x.onclick = function();x.addEventListener(...) 绑定的事件处理程序不会在 innerHTML 中复制代码>,因此它们不会被复制.所以 y 中的新元素不会有事件监听器.这可能不是您想要的.

The second major consideration is to think about the limitations of HTML. When you think about a webpage, not everything relevant to the element can be serialised to HTML. For instance, event handlers bound with x.onclick = function(); or x.addEventListener(...) won't be replicated in innerHTML, so they won't be copied across. So the new elements in y won't have the event listeners. This probably isn't what you want.

所以解决这个问题的方法是使用原生 DOM 方法:

So the way around this is to work with the native DOM methods:

for (var i = 0; i < x.childNodes.length; i++) {
    y.appendChild(x.childNodes[i].cloneNode(true));
}

阅读 MDN 文档可能有助于理解这种做事方式:

Reading the MDN documentation will probably help to understand this way of doing things:

现在的问题(与上面代码示例中的选项 2 一样)是它非常冗长,远远长于 innerHTML 选项.这就是您欣赏拥有为您做这种事情的 JavaScript 库的时候.例如,在 jQuery 中:

Now the problem with this (as with option 2 in the code example above) is that it is very verbose, far longer than the innerHTML option would be. This is when you appreciate having a JavaScript library that does this kind of thing for you. For example, in jQuery:

$('#y').html($('#x').clone(true, true).contents());

这对您想要发生的事情更加明确.例如,除了具有各种性能优势和保留事件处理程序外,它还可以帮助您了解您的代码在做什么.这对您作为 JavaScript 程序员的灵魂有好处,并且大大降低了出现奇怪错误的可能性!

This is a lot more explicit about what you want to happen. As well as having various performance benefits and preserving event handlers, for example, it also helps you to understand what your code is doing. This is good for your soul as a JavaScript programmer and makes bizarre errors significantly less likely!

这篇关于为什么要 y.innerHTML = x.innerHTML;被避免?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆