我遇到的一个常见问题是需要在循环中创建多个DOM节点,然后通过应用插件,事件处理程序或类似方式以某种方式激活这些节点。激活步骤要求元素实际上先存在。
所以你最终做了类似的事情:
// Loop 1: Create the nodes
var HTML = '<tr id="UID">';
for(var k in Fields){ // Fields is an object!
HTML += '<td>';
HTML += '<input class="ActivateMe"/>';
HTML += '</td>';
}
var HTML += '</tr>';
$TableBody.children('tr').first().before(HTML);
// Loop 2: Activate the new nodes
$('#'+UID).children('td').children('.ActivateMe').each(function(index){
$(this).InitSomePlugin();
});
上面的代码针对这个问题进行了简化,但假设给定单元格中的每个元素可以不同(可能是输入,可能是div),也可能需要不同的插件(也许它是一个颜色选择器,也许这是一个组合框)。
是否可以避免两次循环数据集并一次性执行插入和激活?我认为可以通过在第一个循环中附加节点来实现,这也可以允许在第一个循环中激活。但通常认为在循环中使用append而不是将所有HTML存储在var中并立即附加所有HTML是不好的做法。同时,在同一组数据上循环两次似乎效率也很低。在对性能影响最小的情况下处理此方案的最佳方法是什么?
答案 0 :(得分:2)
是。不要构建冗长的HTML字符串,而是在第一个循环中以编程方式创建元素,以便您可以直接在其上实例化插件:
var $TableBody = …,
var $row = $('<tr>', {id:UID});
for(var k in Fields) { // sure that Fields is an object?
// For an array, use a normal for loop
var $cell = $('<td>');
var $input = $('<input class="ActivateMe"/>');
$input.InitSomePlugin();
$input.appendTo($cell);
$cell.appendTo($row);
}
$row.prependTo($TableBody);
在调用.InitSomePlugin()
之前,您可能需要执行附加操作。您也可能希望嵌套调用并使用链接来缩短代码:
var $row = $('<tr>', {id:UID}).prependTo(…);
for(var k in Fields)
$('<input class="ActivateMe"/>')
.appendTo($('<td>').appendTo($row))
.InitSomePlugin();
答案 1 :(得分:-1)
由于激活步骤要求元素已经存在且(可能)在DOM中,因此您只有两个选择:
1)您可以单独创建每个DOM元素(使用document.creatElement()
或jQuery&#39; s $(html)
之类的东西),这样您就可以保存DOM对象引用,以后可以用来初始化插件
或
2)你可以像你一样建立一串HTML。插入该字符串,让浏览器为您创建所有元素,然后您必须找到适当的DOM元素才能初始化插件。
测试表明,通常情况下,浏览器在给定HTML字符串时会更快地创建大量HTML对象,而不是手动创建和插入单个DOM对象,因此使用HTML字符串没有特别的问题。 / p>
这里没有100%正确或错误的答案。除非您有数百到数千个DOM元素,否则性能可能不是主要问题。我倾向于选择最简洁,最简单的代码。
在您的情况下,您必须迭代Fields对象,这样您才能避免这种情况。您必须找到表格的第一行,这样才能避免这种情况。
如果您已经决定构建HTML字符串是编写代码的最便捷的方法(它可能就在这里),那么您就无法重新构建需要激活的对象。 DOM。
你可以尽可能高效地处理事情。
这里有一点精简,与基本理念保持一致:
// create the new rows
var HTML = '<tr id="UID">';
for(var k in Fields) {
HTML += '<td>' + '<input class="ActivateMe"/>'+ '</td>';
}
HTML += '</tr>';
// create an insert new content, save reference to new content
var newObj = $(HTML);
$TableBody.prepend(newObj);
// now activate the plugin on the appropriate objects in the new content
newObj.find(".ActivateMe").InitSomePlugin();
简化步骤:
.prepend()
将其设为第一行,而不是查找所有行并选择第一行.each()
循环。你可以这样:newObj.find(".ActivateMe").InitSomePlugin();
没有.each()
。您也可以自己创建DOM对象,而不是使用HTML字符串并跟踪需要激活的对象,以便不必再次找到它们:
// create the new rows
var row = $('<tr id="UID"></tr>'), input, item, activates = [];
for(var k in Fields) {
item = $('<td>');
input = $('<input class="ActivateMe"/>')
activates.push(input);
item.append(input);
row.append(item);
}
// insert row into table
$TableBody.prepend(row);
// now activate the plugin on the appropriate objects that are now inserted
$(activates).InitSomePlugin();
答案 2 :(得分:-1)
$tableBody = $('table');
// Prepare an DOM object but don't append it to DOM yet.
$tr = $('<tr></tr>',{
id: "UID"
});
// Loop over any condition you would see fit.
for(var i = 0; i < 2; ++i) {
$td = $('<td></td>',{
// Prepare your input element with your event bound to it
"html": $('<input/>', {"class": "ActivateMe"}).InitSomePlugin();
});
// append your td element
$tr.append($td);
}
// Add your tr element to the beginning of your table with prepand method.
$tableBody.prepend($tr);