【问题标题】:Append stuff the right way以正确的方式添加内容
【发布时间】:2014-01-19 11:42:07
【问题描述】:

我正在为自己构建一个小型 js 库,但遇到了 appendprepend 方法的问题。这是我目前的设置

prepend: function(str) {
    this.node.innerHTML = str + this.node.innerHTML;
},
append: function(str) {
    this.node.innerHTML += str;
}

它们都按预期工作,正在添加内容,但不幸的是,我正在修改的标签内的元素的所有事件侦听器都丢失了。有趣的是,我没有想到这可能会导致问题。无论如何,我尝试查看 jQuery 以了解他们是如何做到的,但他们的代码显然不是为了让我理解。我尝试查找其他问题,但并没有真正找到解决方案。

如何在不失去听众的情况下实现这一目标?

【问题讨论】:

  • jQuery 使用内部 DOMManip 函数构建实际的 DOM 节点,这样所有元素都附加了本机 appendChild,附加了 insertBefore 等,并且从不使用 innerHTML。
  • @adeneo 所以我猜这是一项艰巨的工作,但是我如何将 html 字符串拆分为节点:/
  • 你不会,你会用浏览器解析器解析字符串,例如通过将字符串设置为 documentFragment 的内容,然后提取节点并将它们插入到实际的 DOM 中。跨度>
  • 查看我的 Q stackoverflow.com/q/11515383/908879接受的答案

标签: javascript append


【解决方案1】:

如果您将 DOM 中的元素作为对象而不是原始字符串表示形式移动,则它们附加的事件和其他元数据将被保留。

您需要使用 DOM 的 appendChildinsertBefore 方法。小提琴:http://jsfiddle.net/QMLpL/2/

这是您更新后的 sn-p:

prepend: function(newNode) {
    this.node.insertBefore(newNode,this.node.firstChild);
},
append: function(newNode) {
    this.node.appendChild(newNode);
}

更新后的 sn-p 需要一个 DOM 节点而不是字符串。


如果您需要一个字符串,请考虑将该字符串用作 CDATA 节点:

node = document.createTextNode(str);

增强的小提琴:http://jsfiddle.net/QMLpL/3/

用法:

prepend: function(str) {
    newNode = document.createTextNode(str);
    this.node.insertBefore(newNode,this.node.firstChild);
},
append: function(str) {
    newNode = document.createTextNode(str);
    this.node.appendChild(newNode);
}

链接小提琴的内容如下。

HTML:

<div id="one">
    <p><a id="clicky" href="#">Hello World</a></p>
</div>
<div id="two">
    <p>Lorem Ipsum</p>
</div>

JavaScript:

var clicky = document.getElementById('clicky');
clicky.onclick = function() {
    console.log('clicked!');
    return false;
};

function append(target,node) {
    if ( typeof node === 'string' ) {
        node = document.createTextNode(node); // cast string as CDATA
    }
    target.appendChild(node);
}

function prepend(target,node) {
    if ( typeof node === 'string' ) {
        node = document.createTextNode(node);
    }
    target.insertBefore(node,target.firstChild);
}

var twoDiv = document.getElementById('two');
append(twoDiv,clicky);

var newElement = document.createElement('p');
newElement.onclick = function() {
    console.log('clicked the p');
    return false;
};
newElement.appendChild(document.createTextNode('Dolor sit amet.')); // add a CDATA node to the new P element
prepend(twoDiv,newElement);

append(twoDiv,'Waddup?');

【讨论】:

  • 我正在寻找一种附加 html 字符串的方法,但这将是我的替代方案。感谢您的努力!
  • @php_nub_qq 我有点困惑,如果你有 HTML 的字符串表示,你为什么会对维护孩子的事件感兴趣?如果孩子有事件,那意味着您的曲目中有最父节点对象。处理原始 DOM 节点比将其序列化为字符串然后让 DOM 重新解析它要快。
【解决方案2】:

使用 insertAdjacentHTML:

prepend: function(str) {
    this.node.insertAdjacentHTML("beforebegin", str);
},
append: function(str) {
    this.node.insertAdjacentHTML("afterend", str);
}

【讨论】:

  • 这似乎正是我要找的,我不敢相信 Firefox 不支持它:&lt;
  • 根据 MDN Firefox 8.0 及以上版本支持insertAdjacentHTML
  • 其实我在查看旧信息,MDN 声明目前所有主流浏览器都支持这个,即使它不在 ECMA 中。谢谢!
【解决方案3】:

好的,这可能会奏效, 我不知道。制作怎么样 有问题的对象的深层克隆。 然后解析你想要的新html 添加另一个变量。下一个循环 递归地遍历这两个对象并添加所有 他们的孩子要一个新的。终于换了 有问题的对象与您的新对象。这 我认为保留听众的方式。不会的 很容易写,但它可能会给你一个想法。 干杯。

【讨论】:

  • 当您拥有完整的 DOM 引擎时,为什么还要自己解析它?
  • insertAdjacentHTML 不受 Firefox 支持。请记住这一点。我建议使用 appendChild 进行递归循环。以及用于创建新的合并 obj 的 innerHTML。
  • 似乎所有主流浏览器都支持insertAdjacentHTML。见 MDN developer.mozilla.org/en-US/docs/Web/API/…
  • 现在是第 24 版,我相信自 2012 年以来没有更新过的任何人都自己带来了这个:D
【解决方案4】:
请用户 insertBefore() JS HTML DOM METHOD 在元素内容之前添加字符串

Check MDN

或用户 appendChild() JS HTML DOM METHOD 用于在元素内容之后添加字符串

Check MDN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多