【问题标题】:Insert innerHTML with Prototypejs使用 Prototypejs 插入 innerHTML
【发布时间】:2011-09-01 06:37:48
【问题描述】:

假设我有一个这样的列表:

<ul id='dom_a'>
  <li>foo</li>
</ul>

我知道如何在 ul 标签中插入元素:

Element.insert('dom_a', {bottom:"<li>bar</li>"});

由于我收到的字符串包含 dom id,我需要插入 inner HTML 而不是整个元素。我需要一个函数来做到这一点:

insert_content('dom_a', {bottom:"<ul id='dom_a'><li>bar</li></ul>"});

并获得:

<ul id='dom_a'>
  <li>foo</li>
  <li>bar</li>
</ul>

我应该如何使用 Prototype 做到这一点?

这是我想出的解决方案,有人可以改进吗?

Zena.insert_inner = function(dom, position, content) {
  dom = $(dom);
  position = position.toLowerCase();
  content = Object.toHTML(content);
  var elem = new Element('div');
  elem.innerHTML = content; // strip scripts ?
  elem = elem.down();
  var insertions = {};
  $A(elem.childElements()).each(function(e) {
    insertions[position] = e;
    dom.insert(insertions);
  });
}

【问题讨论】:

标签: javascript dom prototypejs


【解决方案1】:

我一直在查看原型文档,发现了这个:update function

按照您描述的方式,您可以使用更新函数来查找当前的bottom 内容,然后通过添加所需的代码和之前存储的代码来更新它(就像innerHTML)。

【讨论】:

  • 这行不通:你会以
    • foo
      • bar
      这甚至不是合法的 HTML。
【解决方案2】:

我认为您可以解析变量中的代码块,然后向它询问其 innerHTML,然后使用 insert 将其粘贴到 DOM 中实际节点的底部。

可能看起来像这样:

var rep_struct = "<ul id='dom_a'><li>bar</li></ul>";
var dummy_node = new Element('div'); // So we can easily access the structure
dummy_node.update(rep_struct);
$('dom_a').insert({bottom: dummy_node.childNodes[0].innerHTML});

【讨论】:

【解决方案3】:

我认为您可以通过简单地附加临时元素的第一个子元素的 innerHTML 来稍微精简代码:

Zena.insert_inner = function(dom, position, content) {
    var d = document.createElement('div');
    d.innerHTML = content;
    var insertions = {};
    insertions[position] = d.firstChild.innerHTML;
    Element.insert(dom, insertions);
}

不过没有太大的改进,example here

【讨论】:

  • 感谢指向 jsfiddle 的指针。奇怪的是,我不得不将 'firstChild' 更改为 'childElements()[0]' 才能在 Zena 中工作......(jsfiddle.net/gaspard/sDGxe)。
【解决方案4】:

您可以使用正则表达式来剥离外部元素。

Element.Methods.insert_content = function(element, insertions) {
    var regex = /^<(\w+)[^>]*>(.*)<\/\1>/;
    for (key in insertions) {
        insertions[key] = regex.exec(insertions[key])[2];
    }
    Element.insert(element, insertions);
};
Element.addMethods();

$('dom_a').insert_content({bottom:"<ul id='dom_a'><li>bar</li></ul>"});

【讨论】:

    【解决方案5】:

    如果您使用 PrototypeJS,您可能还想将 script.aculo.us 添加到您的项目中。 script.aculo.us 中的 Builder 提供了一种构建复杂 DOM 结构的好方法,如下所示:

    var myList = Builder.node("ul", {
        id: "dom_a"
    },[
        Builder.node("li", "foo"),
        Builder.node("li", "bar"),
    ]);
    

    在此之后,您可以使用任何插入/更新函数(PrototypeJS 的)甚至是标准的 JavaScript appendChild 在 DOM 中的任何位置插入这个应该呈现为 HTML 的对象。

    $("my_div").insert({After: myList});
    

    请注意,在 PrototypeJS 中插入有 4 种不同的模式:After、Before、Top 和 Bottom。如果您使用插入而不指定上述“模式”,则默认值为底部。也就是说,新的 DOM 代码将附加在 below 容器元素的现有内容 as innerHTML 中。 Top 将做同样的事情,但将其添加到现有内容的顶部。 Before 和 After 也是附加到 DOM 的好方法。如果使用这些,内容将被添加到容器元素前后的 DOM 结构中,而不是 inside 作为 innerHTML。

    但是,对于 Builder,需要牢记一件事,.. 确实有两件事: 一世。您不能在对象中输入原始 HTML 作为内容...这将失败:

    Builder.node("ul", "<li>foo</li>");
    

    二。当您指定节点属性时,请记住,您必须使用 className 来表示 HTML 属性类(可能还有 htmlFor for for 属性...虽然 for 属性在 HTML5(?) 中似乎已被弃用,但谁不想使用它用于标签)

    Builder.node("ul", {
        id: "dom_a",
        className: "classy_list"
    });
    

    我知道你因为第 i 点而摸不着头脑。 > 什么,没有原始 HTML,该死! 不用担心。如果您仍然需要在 Builder 创建的 DOM 中添加可能包含 HTML 的内容,只需在第二阶段使用 insert({Before/After/Top/Bottom: string}) 执行此操作。但是你为什么一开始就想做呢?如果您编写一个一次性的函数来生成各种 DOM 元素而不是拼接各种字符串,那将是一个非常好的实践。前一种方法会简洁优雅。这有点像内联样式与类类型的问题。毕竟,好的设计应该将内容与 meta 内容或格式化标记/降价分开。

    在您的工具箱中要方便使用的最后一件事是 Protype 的 DOM 遍历,以防您想像 HTML Houdini 那样动态插入和删除内容。查看 Element next、up、down、previous 方法。此外,$$ 使用起来也很有趣,尤其是如果您了解 CSS3 选择器的话。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      相关资源
      最近更新 更多