最近客串了一把前端,有行复制的功能用 jQuery 来实现了。感觉比以前原生js用 CreateElement 要简单多了,但还是遇到了一些陷阱比如IE7的bug,这里记录下来。先看看 table 的样子:这里3行是一组,按下"Copy"连值复制,按下"Add"只增加行不复制值。calendar 使用的是 jQuery UI 里的 datepicker
下图只是一个简单的demo,没有复杂的样式表:
为了灵活对应不同的表格,提取了一个共通的 js 来处理,作为使用前提:
1. table 必须有 id;
2. 有 id 的 tr 才会被复制;(tr的id从1开始编号)
3. table 内所有id都必须以 xxx_n 编号
function RowCopyUtility(opts) { // 表格Id this.tableId = opts.tableId; // 分组内有多少行 this.rowGroupNumber = opts.rowGroupNumber; // 一组内Button对应的方法Map(key=Button value, value=对应方法名) // 所有方法都应以 function (idx) 方式调用 this.buttonHandlers = opts.buttonHandlers; this._countForRowsGroup = -1; this._keyForRow = -1; this.getTargetRowGroup = function(groupIdx) { var rows = []; if (groupIdx > 0) { for(var i=1; i<this.rowGroupNumber+1; i++) { rows[i-1] = $("#row" + i + "_" + groupIdx); } } else { for(var i=0; i<this.rowGroupNumber; i++) { rows[i] = $("#" + this.tableId + " tr[id]").eq(i); } } return rows; }; this.addRow = function (groupIdx, needCopyValue) { if (this._countForRowsGroup == -1) { this._countForRowsGroup = ($("#" + this.tableId + " tr[id]").length - 1)/this.rowGroupNumber; this._keyForRow = parseInt($("#" + this.tableId + " tr[id]:not(#row_add):last").attr("id").split("_")[1]) + 1; } if (groupIdx == 0) { var firstRow = $("#" + this.tableId + " tr[id]:first"); var currentIdx = firstRow.attr("id").split("_")[1]; groupIdx = currentIdx; } var regForId = new RegExp("^(\\w+_)" + groupIdx + "$"); var regForName = new RegExp("^(\\w+_)" + groupIdx + "$"); var regForRadioId = new RegExp("^(\\w+_)" + groupIdx + "(.*)$"); var targetRows = this.getTargetRowGroup(groupIdx); // 重要:注意闭包参数的作用域 var idx = this._keyForRow; for(var i=0; i<targetRows.length; i++) { // clone target rows var cloneRow = targetRows[i].clone(false); var newRowId = cloneRow.attr("id").split("_")[0] + "_" + idx; cloneRow.attr("id", newRowId); var radios = []; cloneRow.find("[id]").each(function() { var id = $(this).attr("id"); var oldId = id; var name = $(this).attr("name"); id = id.replace(regForId, "$1" + idx); $(this).attr("id", id); var newname = name.replace(regForName, "$1" + idx); $(this).attr("name", newname); if ($(this).hasClass("hasDatepicker")) { $(this).removeClass("hasDatepicker"); } if ($(this).attr("type") == "checkbox") { if($(this).next().attr("for") != "") { $(this).next().attr("for", id); } if (!needCopyValue) { $(this).attr("checked", ""); } } else if ($(this).attr("type") == "radio") { id = id.replace(regForRadioId, "$1" + idx); $(this).attr("id", id); var radio = new Object(); radio.id = id; radio.oldId = oldId; radio.name = name; radio.newname = newname; // IE7's Bug radio.checked = document.getElementById(oldId).checked; radios[radios.length] = radio; if($(this).next().attr("for") != "") { $(this).next().attr("for", id); } if (!needCopyValue) { $(this).attr("checked", ""); } } else if ($(this).attr("tagName") == "SELECT") { if (needCopyValue) { $(this).val(document.getElementById(oldId).value); } } else if ($(this).attr("tagName") == "TEXTAREA" || $(this).attr("type") == "text" || $(this).attr("type") == "hidden") { if (!needCopyValue) { $(this).val(""); } } }); // insert into document cloneRow.insertBefore("#" + this.tableId + " tr:last"); // replace name for radio for(var n=0; n<radios.length; n++) { document.getElementById(radios[n].id).outerHTML = document.getElementById(radios[n].id).outerHTML.replace(radios[n].name, radios[n].newname); // IE7's Bug document.getElementById(radios[n].oldId).checked = radios[n].checked; } // Event Handler var maps = this.buttonHandlers; cloneRow.find("input:button").each(function() { var value = $(this).attr("value"); var funcName = maps[value]; if (funcName != undefined) { var func = null; func = function() { eval(funcName + "(" + idx + ")"); }; if (func != null) { $(this).attr("onclick", ""); $(this).unbind("click"); $(this).attr("onclick", "").click(func); } } }); } this._countForRowsGroup++; this._keyForRow++; }; this.copyRow = function(groupIdx) { this.addRow(groupIdx, true); }; this.deleteRow = function(groupIdx) { if (this._countForRowsGroup == -1) { this._countForRowsGroup = ($("#" + this.tableId + " tr[id]").length - 1)/this.rowGroupNumber; this._keyForRow = parseInt($("#" + this.tableId + " tr[id]:not(#row_add):last").attr("id").split("_")[1]) + 1; } var allRows = $("#" + this.tableId + " tr[id]"); var miniRowsCount = this.rowGroupNumber + 1; var tbl = $("#" + this.tableId); if (allRows.length == miniRowsCount) { tbl.find("input:text").each(function() { $(this).val(""); }); tbl.find("textarea").each(function() { $(this).val(""); }); tbl.find("input:hidden").each(function() { $(this).val(""); }); tbl.find("input:radio").each(function() { $(this).attr("checked", ""); }); tbl.find("input:checkbox").each(function() { $(this).attr("checked", ""); }); tbl.find("select").each(function() { document.getElementById($(this).attr("id")).selectedIndex = 0; }); tbl.find(".fg-common-field-errored").each(function() { $(this).removeClass("fg-common-field-errored"); }); return; } for(var i=1; i<this.rowGroupNumber+1; i++) { tbl.find("#row" + i + "_" + groupIdx).remove(); } this._countForRowsGroup--; }; }
实际遇到的问题与解决办法:
1. jQuery 的 Clone() 方法,就算传入 false,元素的事件依然会被复制过来。(IE测试)
2. attr("name", name); 在IE中,不会直接替换掉,而是生成 submitName 保存。在 IE7 里 radio 会因为 name 相同而出现问题。
3. 在大量的匿名方法中,特别要注意闭包封送参数的作用域。
4. IE7里的Bug:在radio被复制时,原来的元素的选择值就没了。因此在复制前保存了复制源的radio属性,加入document之后再次设定:
// replace name for radio for(var n=0; n<radios.length; n++) { document.getElementById(radios[n].id).outerHTML = document.getElementById(radios[n].id).outerHTML.replace(radios[n].name, radios[n].newname); // IE7's Bug document.getElementById(radios[n].oldId).checked = radios[n].checked; }
5. jQuery里清除事件单独用 attr("onclick", "") 并不好用;后期用 click(function) 绑定的事件用 unbind("click") 可以移除。
if (func != null) { $(this).attr("onclick", ""); $(this).unbind("click"); $(this).attr("onclick", "").click(func); }
6. jQuery UI 的 DatePicker 当创建了 datepicker 之后,可以通过 hasClass("hasDatepick") 判断是否存在,否则在复制之后有问题。
(多次复制之后 datepicker settings 会莫名其妙丢失)
7. 其他,剩下就是要注意 jQuery 选择器不要过度使用了,越复杂的表达式效率越低。
顺便推荐看一下:15个值得开发人员关注的jQuery开发技巧和心得
还要说下IE9 的 debug 工具真心不错,提高不少开发效率哦一定要利用。
就这些,希望能对大家有帮助。最后附上,测试用的 html:
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="Expires" content="0" /> <style> body{font-family:'Open Sans',arial,sans-serif;} tr{height:30px} input.button{width:60px} table.main { border-width: 2px; border-spacing: 1px; border-style: solid; border-color: gray; border-collapse: collapse; background-color: white; } table.main th { border-width: 1px; padding: 5px; border-style: inset; border-color: gray; background-color: #f0f0f0; -moz-border-radius: ; } table.main td { border-width: 1px; padding: 5px; border-style: inset; border-color: gray; background-color: white; -moz-border-radius: ; } </style> <script type="text/javascript" language="JavaScript" src="jquery.js"></script> <script type="text/javascript" language="JavaScript" src="jquery-ui.js"></script> <script type="text/javascript" language="JavaScript" src="rowCopyUtil.js"></script> <link rel="stylesheet" href="jquery-ui.css" type="text/css" media="all" /> <link type="text/css" href="jqueryCalendarStyle.css" rel="stylesheet" /> <script type="text/javascript" > var rowUtil = new RowCopyUtility( { tableId: "tab1", rowGroupNumber: 3, buttonHandlers: {"Copy":"copyRows", "Delete":"deleteRows", "calendar":"showDatepicker", "some button":"someButtonClick"} } ); function showDatepicker(idx) { var textId = "#calendar_" + idx; if (!$(textId).hasClass("hasDatepicker")) { var text = $(textId).datepicker({ showOn : "calendar", dateFormat : "yy/mm/dd" }); } $(textId).datepicker('show'); } function addRows() { rowUtil.addRow(0, false); } function copyRows(idx) { rowUtil.copyRow(idx); } function deleteRows(idx) { rowUtil.deleteRow(idx); } function someButtonClick(idx) { alert(idx); } </script> </head> <body> <table id="tab1" class="main"> <tr> <th>Header1</th> <th>Header2</th> <th>Header3</th> <th>Header4</th> </tr> <tr id="row1_0"> <td rowspan="3" > <input class="button" type="button" value="Copy" onclick="copyRows(0);" /> <input class="button" type="button" value="Delete" onclick="deleteRows(0);" /> </td> <td>text:<input type="text" id="text_0" /></td> <td> <input type="radio" name="radioAB_0" id="radioA_0" value="1" /><label for="radioA_0">Raido_A </label> <input type="radio" name="radioAB_0" id="radioB_0" value="2" /><label for="radioB_0">Radio_B </label> </td> <td> <select id="select_0"> <option value="0">---select---</option> <option value="1">select option1</option> <option value="2">select option2</option> </select> </td> </tr> <tr id="row2_0"> <td> <input type="checkbox" id="checkA_0" /><label for="checkA_0">Check_A </label> <input type="checkbox" id="checkB_0" /><label for="checkB_0">Check_B </label> </td> <td colspan="2"> <input type="text" id="calendar_0" style="width:90px"/><input type="button" value="calendar" onclick="showDatepicker(0);" /> <input type="button" value="some button" onclick="someButtonClick(0);" /> </td> </tr> <tr id="row3_0"> <td colspan="3"> textarea:<textarea id="textarea_0" style="width:100%"></textarea> </td> </tr> <tr id="row_add"> <td colspan="4"> <input class="button" type="button" value="Add" onclick="addRows();" /> </td> </tr> </table> </body> </html>
Atas ialah kandungan terperinci 利用 jQuery Clone进行复制操作. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

JavaScript adalah di tengah -tengah laman web moden kerana ia meningkatkan interaktiviti dan dinamik laman web. 1) Ia membolehkan untuk menukar kandungan tanpa menyegarkan halaman, 2) memanipulasi laman web melalui Domapi, 3) menyokong kesan interaktif kompleks seperti animasi dan drag-and-drop, 4) mengoptimumkan prestasi dan amalan terbaik untuk meningkatkan pengalaman pengguna.

C dan JavaScript mencapai interoperabilitas melalui webassembly. 1) Kod C disusun ke dalam modul WebAssembly dan diperkenalkan ke dalam persekitaran JavaScript untuk meningkatkan kuasa pengkomputeran. 2) Dalam pembangunan permainan, C mengendalikan enjin fizik dan rendering grafik, dan JavaScript bertanggungjawab untuk logik permainan dan antara muka pengguna.

JavaScript digunakan secara meluas di laman web, aplikasi mudah alih, aplikasi desktop dan pengaturcaraan sisi pelayan. 1) Dalam pembangunan laman web, JavaScript mengendalikan DOM bersama -sama dengan HTML dan CSS untuk mencapai kesan dinamik dan menyokong rangka kerja seperti JQuery dan React. 2) Melalui reaktnatif dan ionik, JavaScript digunakan untuk membangunkan aplikasi mudah alih rentas platform. 3) Rangka kerja elektron membolehkan JavaScript membina aplikasi desktop. 4) Node.js membolehkan JavaScript berjalan di sisi pelayan dan menyokong permintaan serentak yang tinggi.

Python lebih sesuai untuk sains data dan automasi, manakala JavaScript lebih sesuai untuk pembangunan front-end dan penuh. 1. Python berfungsi dengan baik dalam sains data dan pembelajaran mesin, menggunakan perpustakaan seperti numpy dan panda untuk pemprosesan data dan pemodelan. 2. Python adalah ringkas dan cekap dalam automasi dan skrip. 3. JavaScript sangat diperlukan dalam pembangunan front-end dan digunakan untuk membina laman web dinamik dan aplikasi satu halaman. 4. JavaScript memainkan peranan dalam pembangunan back-end melalui Node.js dan menyokong pembangunan stack penuh.

C dan C memainkan peranan penting dalam enjin JavaScript, terutamanya digunakan untuk melaksanakan jurubahasa dan penyusun JIT. 1) C digunakan untuk menghuraikan kod sumber JavaScript dan menghasilkan pokok sintaks abstrak. 2) C bertanggungjawab untuk menjana dan melaksanakan bytecode. 3) C melaksanakan pengkompil JIT, mengoptimumkan dan menyusun kod hot-spot semasa runtime, dan dengan ketara meningkatkan kecekapan pelaksanaan JavaScript.

Aplikasi JavaScript di dunia nyata termasuk pembangunan depan dan back-end. 1) Memaparkan aplikasi front-end dengan membina aplikasi senarai TODO, yang melibatkan operasi DOM dan pemprosesan acara. 2) Membina Restfulapi melalui Node.js dan menyatakan untuk menunjukkan aplikasi back-end.

Penggunaan utama JavaScript dalam pembangunan web termasuk interaksi klien, pengesahan bentuk dan komunikasi tak segerak. 1) kemas kini kandungan dinamik dan interaksi pengguna melalui operasi DOM; 2) pengesahan pelanggan dijalankan sebelum pengguna mengemukakan data untuk meningkatkan pengalaman pengguna; 3) Komunikasi yang tidak bersesuaian dengan pelayan dicapai melalui teknologi Ajax.

Memahami bagaimana enjin JavaScript berfungsi secara dalaman adalah penting kepada pemaju kerana ia membantu menulis kod yang lebih cekap dan memahami kesesakan prestasi dan strategi pengoptimuman. 1) aliran kerja enjin termasuk tiga peringkat: parsing, penyusun dan pelaksanaan; 2) Semasa proses pelaksanaan, enjin akan melakukan pengoptimuman dinamik, seperti cache dalam talian dan kelas tersembunyi; 3) Amalan terbaik termasuk mengelakkan pembolehubah global, mengoptimumkan gelung, menggunakan const dan membiarkan, dan mengelakkan penggunaan penutupan yang berlebihan.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

EditPlus versi Cina retak
Saiz kecil, penyerlahan sintaks, tidak menyokong fungsi gesaan kod

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Dreamweaver Mac版
Alat pembangunan web visual

MinGW - GNU Minimalis untuk Windows
Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.
