如何优雅而简洁地在JavaScript文件中包含HTML?

29

我正在构建一个带有几个模态对话框的小应用程序。窗口需要一点点HTML。我已经在JavaScript库中硬编码了窗口HTML,但对此解决方案并不满意。是否有更优雅的方法来解决这个问题?似乎JavaScript没有多行字符串/HereDoc语法。

var html = "<div id='email_window'><h2>Email Share</h2><div>";
html = html + "<form action='javascript:emailDone();' method='post'>";
html = html + "<div><label for='to'>To</label><input id='to' type='text'></div>";
html = html + "<div><label for='from'>From</label><input id='from' type='text' value='" + email + "'></div>";
html = html + "<div><label for='subject'>Subject</label><input id='subject' type='text' disabled='disabled' value='" + subject + "'></div>";
html = html + "<div><label for='body'>Body</label><input id='body' type='text' disabled='disabled' value='" + body + "'></div>";
html = html + "<div><input type='submit' value='Send'><input type='button' value='Cancel' onClick='javascript:$.fancybox.close();'></div>";
html = html + "</form></div>";

$("#data").html(html);

澄清原始信息所添加-

任何解决方案都不能使用Ajax / XHR来拉取模板文件,因为Javascript库将位于不同的域中,而包含它的HTML文件会在其中。这有点像ShareThis。该库将被包含在许多不同的网站上,并附加到具有属性sharetool ="true"的div内的任何锚标记的onClick事件。

例如:

http://www.bar.com - index.html
<html>
...
<script type="text/javascript" src="http://www.foo.com/sharetool.js"></script>
...
<body>
<div sharetool="true">
</div>
...
</html>
7个回答

21

您可以将HTML包含在页面末尾的不可见div中,作为常规标记。然后,您就可以使用jQuery引用它。

接下来,您需要以编程方式设置您的变量字段(电子邮件、主题、正文)。

<div id='container' style='display: none;'>
  <div id='your-dialog-box-contents'>
    ...
    ...
  </div>
</div>

<script type='text/javascript'>
  $("#from").val(from);
  $("#subject").val(subject);
  $("#body").val(body);
  $("#data").html($("#your-dialog-box-contents"));
</script>

+1 这非常聪明,我过去曾经使用过并取得了成功。 - jackJoe
3
谢谢你的想法。对于这个项目来说,它不是我所需要的。我正在编写的JS库旨在在许多不同的网站上使用,因此在所有包含库的页面中添加隐藏的div并不实际。 - Andrew Hopper

16

模板。选你所爱

您可以将它们内嵌为脚本块或使用 AJAX 将它们作为外部资源加载。

我个人使用 EJS 作为外部模板文件,然后让 EJS 加载它们并将其注入到绑定了 JSON 数据的模板容器中。

new EJS({ 
    url: "url/to/view"
}).update('html_container_name', {
    "foobar": "Suprise"
});

然后使用通用视图逻辑查看文件。

// url/to/view
<p> <%=foobar %></p>

我想说我在工作中对EJS非常满意。拥有一个单独的文件可以更好地设置MVC。 - Darien
@Darien 和文件重用在使用 SSJS 时非常方便。 - Raynos
这看起来非常有前途。我在原始帖子中没有提到JavaScript文件和包含它的html文件位于不同的域上。查看EJS源代码,似乎使用XMLHttpRequest获取模板。这在跨域情况下行不通,对吗? - Andrew Hopper
@andrew 不是的。但是你可以向模板发送一个get请求,并手动将它们传递到EJS中。这意味着你需要在EJS周围编写一个包装器。 - Raynos
明白了。也许我会为这个项目贡献远程模板包装器。 - Andrew Hopper
这篇文章是由LinkedIn的一位开发人员撰写的,最近对客户端JavaScript模板技术进行了全面比较,内容相当详尽。 - chb

8
对于多行字符串(不使用框架,仅使用JavaScript),有几种解决方案。请参阅我在此SO问题的回答。您可以将其与一些简单的模板组合使用:
String.prototype.template = String.prototype.template ||
        function (){
            var  args = Array.prototype.slice.call(arguments)
                ,str = this
                ,i=0
                ;
            function replacer(a){
                var aa = parseInt(a.substr(1),10)-1;
                return args[aa];
            }
            return  str.replace(/(\$\d+)/gm,replacer)
};
//basic usage:
'some #1'.template('string'); //=> some string
//your 'html' could look like:
var html =
  [ '<form action="javascript:emailDone();" method="post">',
    ' <div><label for="to">To</label>',
    '       <input id="to" type="text"></div>',
    ' <div><label for="from">From</label>',
    '       <input id="from" type="text" ',
    '         value="$0"></div>',
    ' <div><label for="subject">Subject</label>',
    '      <input id="subject" type="text" disabled="disabled" ',
    '        value="$1"></div>',
    ' <div><label for="body">Body</label>',
    '      <input id="body" type="text" disabled="disabled" ',
    '        value="$2"></div>',
    ' <div><input type="submit" value="Send"><input type="button" ',
    '        value="Cancel" ',
    '        onClick="javascript:$.fancybox.close();"></div>',
    '</form>'
  ] .join('').template(email, subject, body);

5

个人而言,我喜欢这样构建DOM树:

$('#data').html(
    $('<div/>', {
        id: 'email_window',
        html: $('<h2/>', {
            html: 'Email Share'
        })
    }).after(
        $('<form/>', {
            action: 'javascript:emailDone();',
            method: 'post',
            html: $('<div/>', {
                html: $('<label/>', {
                    for: 'to',
                    html: 'To'
                }).after($('<input/>', {
                    id: 'to',
                    type: 'text'
                }))
            }).after(
                ... etc
            )
        })
    )
);

自闭合的 HTML 标签里面带有内容 :( 我确定自闭合标签不包含内容。 - Raynos
2
从jQuery的角度来看确实更好,但从可读性的角度来看非常差(元数据比例太低)。 - Brad Christie
1
@Raynos:无论如何,根据 jQuery 在选择器中测试标记的正则表达式,/ 都会被忽略。 - Brad Christie
1
@Raynos,不是的,它们有一个应用于它们的HTML属性。jQuery将使用此属性的值将自闭合标记修改为非自闭合标记 :-) - Darin Dimitrov
@BradChristie 我知道jQuery会忽略它并处理得很好。@DarinDimitrov 只是不太语义化。感觉在<div/>中放置内容是错误的。 - Raynos
显示剩余4条评论

5

你的问题有两种解决方案: - 在JavaScript中,heredoc语法的替代方法是使用转义换行符 \

var tpl = "hello\
stackoverflow\
World !";

字符被转义并忽略,不会出现在最终的字符串中。

您还可以使用模板创建一个纯 html 文件,在您的 js 脚本中创建一个隐藏的 iframe 并加载跨域 html 模板。现在可以访问 iframe 的文档对象并检索 body.innerHTML。理论上来说!但我还没有测试过这个解决方案...


1

你说得对,JS没有heredocs或多行字符串。话虽如此,通常的方法是将HTML放在...中,并根据需要显示或隐藏它。你已经在使用jQuery了,所以你已经完成了大部分工作:

<div style="display:none;">
    <form method='post' class="email">
         <input id='from' type='text'> <!-- other form fields omitted for brevity -->
    </form>
    <form method='post' class="facebook"></form> <!-- again, omitted for brevity -->
</div>

然后,您可以填写表单并将其放在正确的位置:

$('#data').html($('form.email').find('input#from').val(email).end().html());

谢谢你的想法。对于这个项目来说,它不是我所需要的。我正在编写的JS库旨在在许多不同的网站上使用,因此在所有包含库的页面中添加隐藏的div并不实际。 - Andrew Hopper

0

Cook.js

div([
  button({click:[firstEvent, secondEvent]},
         'You can bind (attach) events on the fly.'),
  p('Here are some popular search engines'),
  ul([
    li([
      a('Google', {href:'http://www.google.com'})
    ]),
    li([
      a('Bing', {href:'http://www.bing.com'})
    ]),
    li([
      a('Yahoo', {href:'http://www.yahoo.com'})
    ])
  ])
]);

它是如何工作的

Objects = Attribute & Events
    -> {href:'facebook.com', src:'static/cat.gif', ng-bind:'blah'}
String  = Text or Html
    -> 'hello world'
Array   = Elements
    -> [a('hello world', {href:'facebook.com'}), img({src:'static/cat.gif'})] 

更多关于cook.js的内容!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接