在 jQuery 中构建 html 元素的最清晰方法
Posted
技术标签:
【中文标题】在 jQuery 中构建 html 元素的最清晰方法【英文标题】:Clearest way to build html elements in jQuery 【发布时间】:2012-04-03 08:34:41 【问题描述】:我已经看到在 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);
请随意演示您可能使用的任何其他方法/样式。
【问题讨论】:
前三个例子中,为什么要用jquery?在 jquery 选择器中编写完整的 html 只是性能损失。var element2 = "<div><h1>"+title+"</h1>...</div>";
我也在用 jQuery 操作这些元素,所以如果我不使用 jQuery 创建它们,我无论如何都必须使用 jQuery 选择器。
【参考方案1】:
模板很棒,如果您可以在项目中使用它们,我建议您使用它们。如果您使用的是Underscore 或Lodash,它是内置的。但是,在某些情况下,无论是重构还是测试,您都需要在代码中构建HTML。我发现以下格式在需要时最容易阅读。
注意:HTML spec 允许标记中的属性使用单引号或双引号,因此不要为所有疯狂的转义而烦恼。
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"));
【讨论】:
哇!绝对完美。花了将近整整两年的时间才得到一个可读且易于维护的实际问题的答案。 我喜欢这个。你觉得.join("\n")
而不是.join("")
怎么样?
请注意,在打字稿中您可以使用模板字符串basarat.gitbooks.io/typescript/docs/template-strings.html
使用“this.$fixture”,除了 jQuery,我还需要安装什么吗?【参考方案2】:
看了一会,找到了我最终确定的风格。首先,我会说我使用 Mustache 做模板,而且效果很好。但是,有时,您只需要一次构建一个元素,而无需重用它,或者有其他动机不引入另一个库。在这种情况下,我开始使用:
$("body")
.append(
$("<div>")
.append(
$("<div>")
.append(
$("<h1>").text(title)
)
)
.append(
$("<div>").text(content)
)
);
这是可行的,因为append()
返回对您要附加到的对象的引用,因此链式append()
s 附加到同一个对象。通过适当的缩进,标记的结构是显而易见的,这样很容易修改。显然这比使用模板要慢(整个东西必须一块一块地构建),但如果你只是将它用于初始化或类似的东西,那么这是一个很好的折衷方案。
有很多方法可以格式化这样的构造,但我选择了一种方法来说明发生了什么。我使用的规则是每行最多应该有一个左括号和/或一个右括号。此外,这些附加树的叶子不需要传递给 jQuery 构造函数,但我在这里这样做是为了视觉重复。
【讨论】:
到目前为止,最干净的 jQuery 风格的方法比将它包含在引号内,如接受的答案所示。接受的答案感觉就像在 phpecho
/shudder 中有 HTML 代码
$("<h1>" + title + "</h1>")
可能是$("<h1>").text(title)
所有这些.append()
调用与构造字符串(例如在var 中)并附加一个.append()
相比是否会对性能产生不利影响?
记住.append()
也可以接受数组可能很有用。例如,这在尝试构建列表时可能会派上用场。然后可以使用匿名函数自调用函数来生成<li>s
的列表。 [类似.append( (function () ... return li; )() )
]
@adamj - 我正好相反 - 我更喜欢接受的版本,因为它实际上类似于嵌套标记,因此更容易阅读。【参考方案3】:
在构建 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 树构建与匹配的开始和结束标签。
【讨论】:
我打算为此添加一个示例,但我从未见过它以可读的方式完成。这个方法虽然很清楚。【参考方案4】:我的建议:不要尝试用 jQuery 构建 html 元素,这不是它的责任。
使用 javascript 模板系统,如 Mustache 或 HandlebarJs。
使用非常有限的行数,您可以直接从 Javascript 对象创建 html 元素。并不复杂,只有两个函数和一个模板。
<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);
它比一系列串联更易于维护。
【讨论】:
我对模板系统的研究不多。我非常喜欢这种语法。但是,目前我正在使用 MVC 框架,并且我的 javascript 与我的实际视图模板很好地分开。这意味着我的 js 模板无论如何都必须构造为字符串(在它们各自的 .js 文件中),否则会通过获取 html 模板中定义的 js 模板来打破 demeter 定律。无论如何 +1,因为这在任何其他情况下都是一个很好的解决方案。 似乎并非不兼容。请参阅我的第二个示例。 在实际尝试之后,结果证明这是一个非常好的解决方案。语法很明显,因为这些模板非常小,所以当它们嵌入到 .js 文件中时看起来不错。另外,如果我的模板变得疯狂,我仍然可以使用转义的换行符。【参考方案5】:2015 年答案:
对于 ES6,使用 JavaScript template strings
var str = `
<!doctype html>
<html>
<body>
<h1>❤ unicorns</h1>
</body>
</html>`
对于旧版浏览器,请使用multiline。
var str = multiline(function()/*
<!doctype html>
<html>
<body>
<h1>❤ unicorns</h1>
</body>
</html>
*/);
【讨论】:
这比到处使用.append
s 简单多了。
很高兴看到 html 的结构并能够使用模板字符串具有的 $myVar 功能干净地传入变量。这种方式有点像 React JSX 的样子,现在每个人都在使用。【参考方案6】:
这是改编自 Baer 的回答。我发现它更具可读性,无需创建和加入数组,无需在每一行加上引号:
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 )
仅供参考,当性能不是问题并且元素包含大量动态数据时,我有时只编写这样的代码(请注意,闭包编译器会针对未引用的类属性发出警告,但在现代浏览器中这很好用):
$(
'<a></a>'
,
text : this.fileName
, href : this.fileUrl
, target : '_blank'
, class : 'file-link'
, appendTo : this.container
)
【讨论】:
【参考方案7】:这是一个使用 $(htmlString) 并模仿 HTML 代码标准布局的示例:
function getPage(title, contents)
return (
$("<div>", id: "container", class: "box").append(
$("<div>", class: "title").append(
$("<h1>").text(title)
),
$("<div>").html(contents)
)
);
【讨论】:
如果您需要附加大量事件处理程序,这种方式最灵活。【参考方案8】:您可能会查看 javascript 视图模板:
http://embeddedjs.com/
http://jupiterjs.com/news/jquery-view-client-side-templates-for-jquery
http://javascriptmvc.com/docs.html#!jQuery.View
【讨论】:
【参考方案9】:我发现函数式方法非常方便。比如
// 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>
编辑
我已经改进了我的方法,现在可以使用 html_uty.js
【讨论】:
您使用html
就好像它是一个属性,就像在 html: content
中一样,但它的行为似乎有所不同。 interesting feature documented 在哪里?
可能在As of jQuery 1.8, any jQuery instance method (a method of jQuery.fn) can be used as a property...
之后,但我隐约记得我是通过反复试验而不是从文档中找到它,同时尝试构建我的类似反应的迷你脚本。顺便说一句,现在我已经完善了构造(特别是样式 attr 不能直接处理,我会在答案中添加指向 github 的链接)
我真的很喜欢这种没有模板语言的脚本。它仍然在弯曲我的大脑(就像 $.map 一直在做的那样,更不用说您将 array 传递给 $.html),但我会继续寻找。【参考方案10】:
使用反引号的最简单方法 -
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>';
【讨论】:
有时我们倾向于过度工作,而这种方法是迄今为止最简单的。我更进一步,将格式化的 HTML 复制到 Excel 中,然后使用简单的公式将每一行包含在引号(包括空格)中,然后将公式结果复制到我的 JS 文件中。这为我提供了格式精美的 HTML(即使这样也太过分了!)。以上是关于在 jQuery 中构建 html 元素的最清晰方法的主要内容,如果未能解决你的问题,请参考以下文章