使用 html <模板>:innerHTML.replace

Posted

技术标签:

【中文标题】使用 html <模板>:innerHTML.replace【英文标题】:Using html <template>: innerHTML.replace 【发布时间】:2015-02-28 05:53:20 【问题描述】:

most popular intro 表示我可以轻松地在我的文档中克隆 html 模板。

<template id="mytemplate">
  <img src="" >
  <div class="comment"></div>
</template>

然而,“模板”一词意味着您不会按原样复制粘贴它,未经修改。模板意味着您要使用特定值更新一些变量。它建议使用以下方法更新节点:

var t = document.querySelector('#mytemplate');
// Populate the src at runtime.
t.content.querySelector('img').src = 'logo.png';

var clone = document.importNode(t.content, true);
document.body.appendChild(clone);

这不是完美的吗?有 querySelector 来获取元素,以便您可以更新其属性。我只是不明白他为什么在克隆模板之前更新模板。但这不是我的问题。真正的问题是,在我的情况下,要更新的变量的位置是未知的。无论模板结构是什么,它都可以是属性或内部文本。我相信这是最普遍和最频繁使用的模板。所以,我可以确保变量 id 在模板中是唯一的,比如#reply here

<template id="comment-template">
  <li class="comment">
    <div class="comment-author"></div>
    <div class="comment-body"></div>
    <div class="comment-actions">
      <a href="#reply" class="reply">Reply</a>
    </div>
  </li>
</template>

应该更新#reply,但作者没有解释如何做到这一点。我成功地在原始模板document.querySelector('#mytemplate').innerHTML.replace(id, value) 上使用了innerHTML,但这会破坏模板供以后使用,如上所述。我未能更新克隆的文本。这可能是因为 template.clone 生成了一个没有 innerHTML 的文档片段。但是,在推进之前,我决定研究替代方案,因为我知道 innerHTML/outerHTML 不是很标准。

Alternative for innerHTML? 检查了 innerHTML 的替代方案,但同样,他们对模板的假设过多。他们不只是用用户值替换一些特定的标识符,而是完全重新创建模板,这违背了模板的整个概念。一旦您在变量评估中重新创建其整个代码,模板就会失去任何意义。那么,&lt;template&gt; 应该怎么用呢?

【问题讨论】:

【参考方案1】:

这是我的解决方案,valuate 函数

  <div id="div1">env: </div>
  <template id="template1">
        <a href="#ref">var1=var2</a>
  </template>

<script language="javascript">
    function valuate(template, targetParent, dict) 
        var t = document.querySelector('#' + template);
        var clone = t.cloneNode(true)
        for (key in dict) 
            clone.innerHTML = clone.innerHTML.replace(key, dict[key])
        
        var fragment = document.importNode(clone.content, true)
        var canvas = document.querySelector('#' + targetParent);
        canvas.appendChild(fragment);
        //alert(canvas.innerHTML)
    
    valuate("template1", "div1", var1:"1+1", var2:2, "#ref":"abc.net")
</script>

它需要模板、字典和目标元素。不幸的是,it fails for SVG hierarchies。你不知道为什么吗?

【讨论】:

【参考方案2】:

再次使用&lt;template&gt;.querySelectorAll 选择元素并使用setAttribute 更改href

 var a = <template>.querySelectorAll("a[href='#reply']");
 a[0].setAttribute("href", <url>)

这是一个更通用的函数。它改变了克隆模板中选定元素的属性,当然这是非常基本的,

    //object = the cloned template.
    //selector = the selector argument which selects all nodes.
    //attribute = the attribute to change.
    //value = the value that needs to be set to the attribute.

function changeTemplateValues(object, selector, attribute, value)

    elements = object.querySelectorAll(selector);
    if (elements.length == 0)
    
        return false; //stop executing. No elements were found.
    
    else if (!attribute && !value)
    
        return elements; //no attributes and values are set, return nodelist;
    
    else
    
        if (attribute)
        
            //loop over all selected elements to change them.
            for (var i = 0; i < elements.length; ++i)
            
                if (attribute.match(/innerHTML|textContent|text|nodeValue/g) )
                
                    elements[i][attribute] = value;
                
                else
                
                    elements[i].setAttribute(attribute, value);
                
            
        
        else
        
            //No attribute return false;
            return false;
        
    

【讨论】:

但我为什么要更新 [0] 属性?我的意思是,假设第一个是模板,一旦你更新了属性#replay -&gt; value,它就不再是#replay。这会破坏模板以供以后使用,不是吗?此外,这种方法不适用于 innerText 变量,对吧? 你是对的。您需要在新克隆的模板上调用 querySelectorAll。所以 clone.querySelectorAll 在您的示例代码中。这样只有克隆的版本会被更新。对于innerText,只需将setAttribute 替换为innerText = string。火狐不支持innerText!

以上是关于使用 html <模板>:innerHTML.replace的主要内容,如果未能解决你的问题,请参考以下文章

使用 html <模板>:innerHTML.replace

JavaScript之innerHTML

html模板引擎jade的使用

Html模板引擎Handlerbars使用demo

Thymeleaf模板使用

如何使用 EJS 模板有条件地显示 HTML?