在 jQuery 中构建 html 元素的最清晰的方法

在 jQuery 中,我看到了很多不同的创建元素的风格(以及很少的不同方法)。我很好奇构建它们的 非常清楚方法,以及是否有任何特定的方法由于任何原因客观上优于另一种方法。下面是我看到的一些样式和方法的 例子

var title = "Title";
var content = "Lorem ipsum";


// escaping endlines for a multi-line string
// (aligning the slashes is marginally prettier but can add a lot of whitespace)
var $element1 = $("\
<div><h1>" + title + "</h1>\
<div class='content'>  \
" + content + "        \
</div>                 \
</div>                     \
");


// all in one
// obviously deficient
var $element2 = $("<div><h1>" + title + "</h1><div class='content'>" + content + "</div></div>");


// broken on concatenation
var $element3 = $("<div><h1>" +
title +
"</h1><div class='content'>" +
content +
"</div></div>");


// constructed piecewise
// (I've seen this with nested function calls instead of temp variables)
var $element4 = $("<div></div>");
var $title = $("<h1></h1>").html(title);
var $content = $("<div class='content'></div>").html(content);
$element4.append($title, $content);


$("body").append($element1, $element2, $element3, $element4);

请随意演示您可能使用的任何其他方法/样式。

84656 次浏览

在构建 DOM 时,我尽量避免字符串串联,因为它们可能导致细微的错误和未正确编码的输出。

我喜欢这个:

$('<div/>', {
html: $('<h1/>', {
html: title
}).after(
$('<div/>', {
'text': content,
'class': 'content'
})
)
}).appendTo('body');

产生:

    ...
<div><h1>some title</h1><div class="content">some content</div></div>
</body>

它确保正确的 HTML 编码和 DOM 树的建立与匹配的开始和结束标记。

我的建议是: 不要尝试用 jQuery 构建 html 元素,这不是它的责任。

使用像 胡子< strong > HandlebarJs 这样的 Javascript 模板系统。

使用非常有限的代码行,您可以直接从 Javascript 对象创建 html 元素。这并不复杂,只有2个函数和一个模板。

<div class="entry">
<h1>\{\{title}}</h1>
<div class="body">
\{\{body}}
</div>
</div>


var context  = {title: "My New Post", body: "This is my first post!"}
var template = Handlebars.compile($("#template-skeleton"));
var html     = template(context);

编辑:
另一个没有 html 的例子,纯 Javascript (来自 ICanHaz) :

var skeleton = '<div><h1>\{\{title}}</h1><div class="content">\{\{content}}</div></div>';
var data = { title: "Some title", content: "Some content" };
var html = Mustache.to_html(skeleton, data);

它比一系列连接可维护得多。

在周围看了一会儿后,我找到了我最终决定的风格。首先,我要说我使用 Mustache 作为模板,它工作得很好。不过,有时候您只需要一次构建一个元素,而不需要重用它,或者有其他动机不引入另一个库。在这种情况下,我开始使用:

$("body")
.append(
$("<div>")
.append(
$("<div>")
.append(
$("<h1>").text(title)
)
)
.append(
$("<div>").text(content)
)
);​

这是因为 append()返回对您是 附加 < strong > 到 的对象的引用,所以链接的 append()连接到同一个对象。通过适当的缩进,标记的结构非常明显,并且这种方式很容易修改。显然,这比使用模板要慢(整个系统必须一块一块地构建) ,但是如果您只是将其用于初始化或类似的目的,那么这是一个很好的折衷方案。

有许多方法可以格式化这样的结构,但是我选择了一种方法来清楚地表明正在发生的事情。我使用的规则是,每行最多应该有一个开括号和/或一个闭括号。另外,这些附加树的叶子不需要传递给 jQuery 构造函数,但是我在这里这样做是为了可视化重复。

模板非常棒,如果您在项目中可以访问它们,我建议您使用它们。如果您使用 下划线Lodash,它是内置的。然而,在某些情况下,无论是重构还是测试,您都需要在代码中构建 HTML。我发现下面的格式是最清楚的阅读时,这是要求。

注意: HTML 规范允许标记中的属性使用单引号或双引号,因此不必费心进行疯狂的转义。

this.$fixture = $([
"<div>",
"  <div class='js-alert-box'></div>",
"  <form id='my-form-to-validate'>",
"    <input id='login-username' name='login-username'>",
"  </form>",
"</div>"
].join("\n"));

这是根据贝尔的回答改编的。我发现它更具可读性,不需要创建和加入数组,不需要在每一行都加上引号:

Http://jsfiddle.net/emza5ljb/

var html =


'                                                           \
<div>                                                     \
<div class="js-alert-box"></div>                        \
<form id="my-form-to-validate">                         \
<input id="login-username" name="login-username">     \
</form>                                                 \
</div>                                                    \
'


// using jQuery:
//
var dom = $( html )


// or if you need performance, don't use jQuery
// for the parsing.
// http://jsperf.com/create-dom-innerhtml-vs-jquery
//
var div       = document.createElement( 'div' )
div.innerHTML = html
var dom = $( div )

仅供参考,当性能不成问题,元素包含大量动态数据时,我有时只是编写这样的代码(注意,闭包编译器会抛出关于未引用 class 属性的警告,但是在现代浏览器中,这种方法工作得很好) :

$(
'<a></a>'


, {
text     : this.fileName
, href     : this.fileUrl
, target   : '_blank'
, class    : 'file-link'
, appendTo : this.container
}
)

2015年答案 :

对于 ES6,使用 JavaScript 模板字符串

var str = `
<!doctype html>
<html>
<body>
<h1>❤ unicorns</h1>
</body>
</html>`

对于较老的浏览器,使用 多线电话

var str = multiline(function(){/*
<!doctype html>
<html>
<body>
<h1>❤ unicorns</h1>
</body>
</html>
*/});

我发现函数式方法非常方便

// reusable generics TABLE constructor helpers
var TD = function(content) { return $('<td>', { html: content }) }
var TH = function(content) { return $('<th>', { html: content }) }
var TR = function(cell, cells) {  // note the kind of cell is a 2^order parameter
return $('<tr>', { html: $.map(cells, cell) })
}


// application example
THEAD = $('<thead>', {html:
TR(TH, [1,2,3,4])})
TBODY = $('<tbody>', {html: [
TR(TD, ['a','b','c','d']),
TR(TD, ['a','b','c','d']),
]})

现在该打电话了

$('#table').append($('<table>', {html: [THEAD, TBODY]}))

产量

<table><thead><tr><th>1</th><th>2</th><th>3</th><th>4</th></tr></thead><tbody><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr></tbody></table>

edit

I have refined my approach, now available for instance as html_uty.js

下面是一个使用 $(htmlString)并模仿 HTML 代码标准布局的例子:

function getPage(title, contents) {
return (
$("<div>", {id: "container", class: "box"}).append(
$("<div>", {class: "title"}).append(
$("<h1>").text(title)
),
$("<div>").html(contents)
)
);
}

这样做的最简单的方法是使用反勾-

var optionsForLength =  `
<option value="Kilometre">Kilometre</option>
<option value="Metre">Metre</option>
<option value="Centimetre">Centimetre</option>
<option value="Milimetre">Milimetre</option>
<option value="Micrometre">Micrometre</option>
<option value="Nanometre">Nanometre</option>
<option value="Mile">Mile</option>
<option value="Yard">Yard</option>
<option value="Foot">Foot</option>
<option value="Inch">Inch</option>
`;

或者也可以使用单引号将 HTML 包装在 javascript-中

var optionsForLength =
'<option value="Kilometre">Kilometre</option>'+
'<option value="Metre">Metre</option>'+
'<option value="Centimetre">Centimetre</option>'+
'<option value="Milimetre">Milimetre</option>'+
'<option value="Micrometre">Micrometre</option>'+
'<option value="Nanometre">Nanometre</option>'+
'<option value="Mile">Mile</option>'+
'<option value="Yard">Yard</option>'+
'<option value="Foot">Foot</option>'+
'<option value="Inch">Inch</option>'+
'<option value="Nautical mile">Nautical mile</option>';