【问题标题】:Create node from markup string从标记字符串创建节点
【发布时间】:2012-03-09 05:31:37
【问题描述】:

有没有办法在 JavaScript 中将标记字符串转换为节点对象?其实我正在寻找替代品:

document.getElementById("divOne").innerHTML += "<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"

类似

document.getElementById("divOne").appendChild(document.createNodeFromString("<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"))

使用 createNodeFromString 而不是创建 table 元素,然后附加其子元素,然后附加它们各自的属性和值!

【问题讨论】:

  • 我很好奇为什么设置 innerHTML 对你不起作用。设置 innerHTML 后,您可以通过查询 divOne 来获取结果元素。
  • @akonsu,据说你在 divOne 中有 并且在这个 div 之外你有一个带有 onclick= innerHTML-method 的按钮。现在,在 FF10 和 IE9(带有文档模式 IE9)中,在文本框中输入内容并按下按钮,输入的值将被重置!我想看看appendChild会发生同样的事情。顺便说一句,在 IE8 兼容模式下,输入元素的值是持久的..
  • 你是说如果你有一个文本输入字段和一个按钮,当你按下按钮时输入字段的值会被清除?你能在 jsbin.com 上演示一下吗?
  • 你考虑过使用jQuery这样的框架吗?让这种任务变得更容易......
  • 在具有本机兼容性的 FF10 或 IE9 中尝试,然后在 IE8 兼容模式下尝试:jsbin.com/amodag 另外,document.getElementById("divOne").appendChild(document.createElement("input")) 确实保留了 IE9 中的输入值,但我需要将整个表附加到单个语句。

标签: javascript html dom


【解决方案1】:

目前还没有跨浏览器的功能。可以使用以下方法来达到预期的效果(使用DocumentFragment 以获得优化的性能,基于this answer):

function appendStringAsNodes(element, html) {
    var frag = document.createDocumentFragment(),
        tmp = document.createElement('body'), child;
    tmp.innerHTML = html;
    // Append elements in a loop to a DocumentFragment, so that the browser does
    // not re-render the document for each node
    while (child = tmp.firstChild) {
        frag.appendChild(child);
    }
    element.appendChild(frag); // Now, append all elements at once
    frag = tmp = null;
}

用法(为了便于阅读而缩进):

appendStringAsNodes(
    document.getElementById("divOne"),
   "<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"
);

【讨论】:

    【解决方案2】:

    是的,你可以这样做。

    var myNewTable = document.createElement("table");
    myNewTable.innerHTML = "<tbody><tr><td><input type='text' value='0' /></td></tr></tbody>"
    document.getElementById("divOne").appendChild(myNewTable);
    

    【讨论】:

    • 旧 IE 版本会抱怨这一点,因为它们无法处理在某些元素上设置 innerHTML 属性,包括 &lt;table&gt;。另请参阅this article
    【解决方案3】:
    function htmlMarkupToNode(html){
        let template = document.createElement("template");        
        template.innerHTML = html ;
        let node = template.content.cloneNode(true) ;        
        return node ;   
    }
    
    document.getElementById("divOne").appendChild(htmlMarkupToNode("<table><tbody><tr><td><input type='text' value='0' /></td></tr></tbody></table>"));
    

    【讨论】:

    • 啊,现在才看到你的帖子,抱歉我自己添加了它,不过我试着更详细一点……顺便说一句,你可以添加代码的语言(格式化它)通过在 3 个反引号后添加语言名称
    【解决方案4】:

    关于这个主题的一些新闻:

    现代方法是使用 &lt;template&gt; 标签,例如在 body 关闭之前(浏览器会忽略它)。

    它是客户端模板的标准化,不需要使用 .innerHTML,这可能会导致安全问题 (XSS)

    示例:

    <template id='tplArticle'>
      <article class='newsItem'>
        <h1 class='title'></h1>
        <p class='paragraph'>
      </article>
    </template>
    

    只要您需要它,您只需抓取它的内容并克隆(!!)它以重复使用它:

    // .content will grab the content of the template, not the <template> tag
    // this will return a document fragment
    const $articleFragment = document.querySelector('#tplArticle').content;
    
    // clone it, otherwise you get the same reference and it won't be reusable (true makes a deep copy)
    const $article = document.importNode($articleFragment, true);
    
    // then e.g. append it to the body
    document.body.appendChild($article);
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 2014-01-04
    • 2012-05-17
    • 1970-01-01
    • 2017-01-30
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多