search

Home  >  Q&A  >  body text

javascript - 如何优雅的用js动态的添加html代码?

如果需要在js里动态的加载一些html代码,一般会选择下面这样的方式

str="<p class="dialog"><p class="title"><img src="close.gif" alt="点击可以关闭" />亲爱的提示条</p><p class="content"><img src="delete.jpg" alt="" /><span>您真的要GG吗?</span></p><p class="bottom"><input id="Button2" type="button" value="确定" class="btn"/>&nbsp;&nbsp;<input id="Button3" type="button" value="取消" class="btn"/></p></p>"

但是感觉这样太丑了,可读性和可维护性都很差。有什么更加优雅和简洁的方式吗?

伊谢尔伦伊谢尔伦2896 days ago641

reply all(7)I'll reply

  • 迷茫

    迷茫2017-04-10 12:49:56

    把你想要的结构写在HTML里,用一个display:none的标签来包裹,一般而言,会使用:

    • 不设置为type="text/javascript"的script标签
    • textarea标签

    <script type="text/html" id="theTemplate">
        <p class="dialog"><p class="title"><img src="close.gif" alt="点击可以关闭" />亲爱的提示条</p><p class="content"><img src="delete.jpg" alt="" /><span>您真的要GG吗?</span></p><p class="bottom"><input id="Button2" type="button" value="确定" class="btn"/>&nbsp;&nbsp;<input id="Button3" type="button" value="取消" class="btn"/></p></p>
    </script>
    

    <textarea id="theTemplate" style="display:none">
        <p class="dialog"><p class="title"><img src="close.gif" alt="点击可以关闭" />亲爱的提示条</p><p class="content"><img src="delete.jpg" alt="" /><span>您真的要GG吗?</span></p><p class="bottom"><input id="Button2" type="button" value="确定" class="btn"/>&nbsp;&nbsp;<input id="Button3" type="button" value="取消" class="btn"/></p></p>
    </textarea>
    

    使用这些标签,是为了避免这些不被直接使用的标签一被浏览器读取到就被渲染。而且这样做的话,里面的img的src也不会被浏览器自动获取。

    如果你使用script标签,就可以如下代码得到它:

    //使用script包裹
    var template = document.getElementById("theTemplate").innerHTML ;
    //使用textarea包裹
    var template = document.getElementById("theTemplate").value ;
    

    使用时textarea时要注意,textarea无法嵌套自身;script标签也无法自嵌套。

    但如果文档结构是固定的,里面的数据需要动态填充呢?请参考面向数据编程。

    P.S. 对于innerHTML和value的使用可能会造成XSS。

    动态添加HTML代码,前端若由模板导出,在JS里面写结构,或者在HTML里面写结构,这个结构对于黑客来说都是白盒的,白盒攻击相对简单,黑客可以通过阅读代码来看到哪一些代码可以被利用。比如$用户签名$,发现这里的用户签名是用户可控制的数据之后,黑客可以构造一个<img src="javascript:window.open()">之类的用户签名,未经过滤<>的话,就可以做到XSS。

    因此,在面向数据编程里讲到的方案中,通过json进行动态匹配替换时,一定要保证后端输出的数据JSON里,<>等语义敏感的字符正确转义。

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 12:49:56

    https://github.com/janl/mustache.js

    View:

    {
      "name": {
        "first": "Michael",
        "last": "Jackson"
      },
      "age": "RIP"
    }
    

    Template:

    *** {{name.first}} {{name.last}}
    * {{age}}**
    

    Output:

    * Michael Jackson
    * RIP
    

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 12:49:56

    三种方案:

    使用DOM

    // 使用createElement创建元素
    var dialog = document.createElement('p');
    var img = document.createElement('img');
    var btn = document.createElement('input');
    var content = document.createElement('span');
    // 添加class
    dialog.className = 'dialog';
    // 属性
    img.src = 'close.gif';
    // 样式
    btn.style.paddingRight = '10px';
    // 文本
    span.innerHTML = '您真的要GG吗?';
    // 在容器元素中放入其他元素
    dialog.appendChild(img);
    dialog.appendChild(btn);
    dialog.appendChild(span);
    

    关于添加class如果不考虑IE兼容性问题,可以使用classList方法,详细API在这里。 还有很多方法用于DOM操作,在这里。

    使用HTML5 template标签

    <template id="dialog_tpl">
      <p class="dialog">
        <img src="" alt="">
        <input type="button" value="确认">
        <span></span>
      </p>
    </template>
    

    接着还是得使用DOM操作,只是不需要创建元素了,然后复制一份副本放入正文即可。

    var dialog = document.querySelector('#dialog_tpl');
    dialog.content.querySelector('img').src = 'close.gif';
    dialog.content.querySelector('span').innerHTML = '您真的要GG吗?';
    document.body.appendChild(dialog.content.cloneNode(true));
    

    template标签是隐藏的,最多是用在列表中,可以产生多个副本。详细使用方法可以参考这篇文章。如果要兼容不支持template的浏览器,可以把content的部分写一个兼容方法,并且把template用CSS隐藏掉即可。

    使用HTML模板

    这里有各种模板,并且按语法风格分类。其实模板大同小异,就是动态修改模板文件使之成为一个可用的静态HTML文件,其实你也可以自己在需要的地方加载一部分HTML。只需要使用ajax请求一个情态的HTML文件并把返回的HTML代码放入当前的HTML中即可。

    reply
    0
  • 巴扎黑

    巴扎黑2017-04-10 12:49:56

    用javascript预编译模版。 我使用的是ejs,非常简单的库,几分钟看一下文档,立刻就能上手用。 国内的话还有artdialog的作者写的artTemplate,据说是最快的预编译模版。 这里有性能测试,优势十分明显: http://aui.github.io/artTemplate/

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 12:49:56

    我用的是Jade。 可读性一等一的好。

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 12:49:56

    如果不需要引入模版文件的依赖关系并保持HTML结构的可读性,我推荐楼主使用CoffeeScript。

    为什么CoffeeScript可以解决楼主提出的问题呢?

    因为它支持类似于Python的跨行字符串,这样很轻易的就能保持HTML结构的可读性,而不需要使用“+”或者采用拼数组的形式。

    同时跨行字符串还支持嵌入变量和表达式,类似与PHP和Ruby的双引号。这样就避免了引入外部模版。

    所以楼主的代码在CoffeeScript里面就变成了这样:

    str = "
       ...
        <p>
           <img src=#{item.href} />
       </p>
       ...
    "
    

    上面的代码在WebStorm和Sublime Text中都可以得到很好的格式化支持,详细的使用例子可以看这里。

    CoffeeScript绝对是一个值得JavaScript爱好者投资的技术,有了它你甚至都能感觉到你写下的不是一行行的代码,而更像一行行的诗歌,每一行都那么地简洁和优雅。

    reply
    0
  • 迷茫

    迷茫2017-04-10 12:49:56

    我正在研究这个链接的方法(肯定是可以的):http://blog.sina.com.cn/s/blog_484d87770101dovv.html
    我正研究着,做成 qq分组的那种效果。以上链接的内容可以完成你要的效果。

    reply
    0
  • Cancelreply