2010-02-07 22 views
48

Có cách nào tốt nhất để tạo các phần tử HTML phức tạp trong jQuery? Tôi đã thử một vài cách khác nhau.jQuery - Phương pháp hay nhất để tạo các đoạn HTML phức tạp

Trước tiên tôi cố gắng sử dụng createElement và chaining rất nhiều những cùng với AppendTo và những thứ tương tự:

var badge = $(document.createElement("div")).attr("class", "wrapper1").appendTo("body"); 
$(document.createElement("div")).attr("class", "wrapper2").appendTo(".wrapper1"); 
$(document.createElement("table")).attr("class", "badgeBody").appendTo(".wrapper2"); 
$(document.createElement("tr")).attr("class", "row1").appendTo(".badgeBody"); 
$(document.createElement("td")).appendTo(".row1"); 
$(document.createElement("span")).attr("class", "badgeUnlocked").text("UNLOCKED! ").appendTo("td"); 
$(document.createElement("td")).attr("class", "badgeTitleText").appendTo(".row1"); 
$(document.createElement("span")).attr("class", "badgeTitle").text(name).appendTo(".badgeTitleText"); 
$(document.createElement("tr")).attr("class", "row2").appendTo(".badgeBody"); 
$(document.createElement("td")).appendTo(".row2"); 
$(document.createElement("img")).attr("src", imgUrl).appendTo(".row2 td"); 
$(document.createElement("td")).attr("class", "badgeText").appendTo(".row2"); 
$(document.createElement("span")).attr("class", "badgeDescription").text(description).appendTo(".badgeText"); 

Đây có thể là thô từ appendTo muốn thêm vào mỗi yếu tố phù hợp để tất cả mọi thứ cần tên riêng của mình nếu không nó kết thúc tăng thêm liên tục khắp nơi.

Sau đó, tôi cố gắng tạo ra một mảng và tham gia nó với nhau:

var badgeFragment = [ 
'<div><div id="'+ closeId+'" class="closeTab">X</div>', 
'<div id="'+ badgeId+'" class="wrapper1">', 
'<div class="wrapper2">', 
'<div class="badgeBody">', 
'<div class="badgeImage">', 
'<img src="'+ imgUrl +'">', 
'</div>', 
'<div class="badgeContents">', 
'<div class="badgeUnlocked">ACHIEVEMENT UNLOCKED: </div>', 
'<div class="badgeTitle">'+ name +'</div>', 
'<div id="'+ textId+'" class="badgeDescription">'+ description +'</div>', 
'</div>', 
'<div style="clear:both"></div>', 
'</div></div></div></div></div>', 
] 

badgeFragment = $(badgeFragment.join('')); 

Điều này có vẻ làm việc khá tốt, mặc dù trong IE khi tôi sẽ đặt một cảnh báo ($ (badgeFragment) .text()) nó thường trở lại trống rỗng. (Đây là một phần của việc gỡ lỗi một vấn đề lớn hơn). Tôi rõ ràng là một chút mới để jQuery (và thậm chí Javascript thực sự) để thử và chắc chắn rằng đây không phải là vấn đề tôi đã thử một phương pháp thứ ba - chuỗi khổng lồ nối:

var badgeFragment = 
'<div><div id="'+ closeId+'" class="closeTab">X</div>' + 
'<div id="'+ badgeId+'" class="wrapper1">' + 
'<div class="wrapper2">' + 
'<div class="badgeBody">' + 
'<div class="badgeImage">' + 
'<img src="C:/Users/Ryan/Documents/icons/crystal_project/64x64/apps/chat.png">' + 
'</div>' + 
'<div class="badgeContents">' + 
'<div class="badgeUnlocked">ACHIEVEMENT UNLOCKED: </div>' + 
'<div class="badgeTitle">test</div>' + 
'<div id="'+ textId+'" class="badgeDescription">test</div>' + 
'</div>' + 
'<div style="clear:both"></div>' + 
'</div></div></div></div></div>'; 

Là một trong những phương pháp này nói chung được coi là tốt hơn so với những người khác? Tôi không thực sự tốt với các trình biên dịch khác nhau vì vậy tôi không chắc chắn làm thế nào để xác minh điều này bản thân mình. Ngoài ra còn có câu hỏi về việc liệu tất cả các phương pháp này có tuân thủ trình duyệt chéo hay không.

+0

Thông báo của bạn trong IE đã đưa ra sản phẩm nào vì ".text()" không có được tất cả các nội dung của cây con DOM của bạn. Hãy thử $ (badgeFragment) .html() – Pointy

Trả lời

56

Với jQuery 1,4, bạn can create HTML elements like so:

// create an element with an object literal, defining properties 
var e = $("<a />", { 
    href: "#", 
    "class": "a-class another-class", // you need to quote "class" since it's a reserved keyword 
    title: "..." 
}); 

// add the element to the body 
$("body").append(e); 

Đây's a link to the documentation.

Tôi không chắc rằng cách tiếp cận này nhanh hơn sử dụng hàm html() của jQuery. Hoặc nhanh hơn việc bỏ qua jQuery tất cả cùng nhau và sử dụng thuộc tính innerHTML trên một phần tử. Nhưng theo như khả năng đọc đi; cách tiếp cận jQuery là yêu thích của tôi. Và trong hầu hết các trường hợp, hiệu suất đạt được của việc sử dụng innerHTML là biên.

+1

Bạn đã bỏ lỡ dấu phẩy sau đối số đầu tiên của jQuery ($). – Spidey

+1

Cảm ơn Spidey. Đã cập nhật câu trả lời. – roosteronacid

+1

@roosteronacid tùy thuộc vào [tài liệu jQuery] (http://api.jquery.com/jQuery/) 'Tên" lớp "phải được trích dẫn trong đối tượng vì đó là từ dành riêng cho JavaScript'. – Pierre

3

Cá nhân tôi nghĩ rằng điều quan trọng hơn đối với mã là có thể đọc được và có thể chỉnh sửa được so với người thực hiện. Cho dù bạn thấy dễ dàng hơn khi nhìn vào và thực hiện các thay đổi mà không phá vỡ nó thì bạn nên chọn nó.

8

Bạn không cần phải gọi document.createElement:

$('#existingContainer').append(
    $('<div/>') 
    .attr("id", "newDiv1") 
    .addClass("newDiv purple bloated") 
    .append("<span/>") 
     .text("hello world") 
); 

Có tất cả các loại công cụ hữu ích trong jQuery cho việc mở rộng/ammending DOM. Hãy xem xét các phương thức "bọc" khác nhau.

Một khả năng khác: cho các đốm màu lớn của nội dung mới, bạn có thể nên sử dụng máy chủ của mình chuẩn bị (sử dụng hệ thống khuôn mẫu phía máy chủ, bất cứ điều gì phù hợp với bạn) và tìm nạp chúng với $.load() hoặc phương pháp tiếp cận ajax khác .

8

Tôi'd be inclined để look at 1 của các templating engines for jquery like jQote

+1

+1. hoặc jsRender, hoặc gạch dưới - có rất nhiều lựa chọn, và chúng tốt hơn nhiều vì Javscript không hỗ trợ các chuỗi nhiều dòng và kiểu sprintf của các hàm thay thế tham số – msanjay

7

John Resig (tác giả của jQuery) đề nghị sử dụng phương pháp khuôn mẫu này trở lại trong năm 2008. Nó thực sự có một số tính năng khá hấp dẫn:

<script type="text/html" id="item_tmpl"> 

    <div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>"> 
    <div class="grid_1 alpha right"> 
     <img class="righted" src="<%=profile_image_url%>"/> 
    </div> 
    <div class="grid_6 omega contents"> 
     <p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p> 
    </div> 
    </div> 

</script> 

sau đó lấy nó bằng cách sử ...

var results = document.getElementById("results"); 
results.innerHTML = tmpl("item_tmpl", dataObject); 

Xem ở đây để biết chi tiết đầy đủ:
http://ejohn.org/blog/javascript-micro-templating/

+2

Ngày nay, bạn có thể đi một bước đơn giản hơn và đẹp hơn và sử dụng [ICanHaz] (http://icanhazjs.com/), kết hợp cách tiếp cận này với hệ thống tạo mẫu Mustache cho các mẫu đẹp hơn và tạo thành phần một dòng. –

+0

ICanHaz trông tuyệt vời, @MarkAmery, nhưng nó chỉ lãng phí một vài giờ thời gian của tôi trước khi tôi cuối cùng đã tìm ra rằng một trong hai nó hoặc Mustache templating không xử lý các ký tự nhất định rất tốt, chẳng hạn như dấu chéo ngược \. Tôi không có khả năng lãng phí thời gian này! – ErikE

+0

@ErikE Ouch. Tôi khá ngạc nhiên rằng một thư viện với nhiều hoạt động như icanhaz sẽ bị phá vỡ theo bất kỳ cách nào đáng kể. Bất kỳ cơ hội bạn có thể cung cấp một trường hợp demo tối thiểu trong một jsfiddle? Tôi có thể chơi và xem tôi có thể sửa lỗi không. –

0

Con đường tôi đang làm được hiển thị dưới đây. Tôi không chắc liệu bạn có nên tạo ra rất nhiều div nhưng nó đã làm việc khá tốt với tôi.

var div1 = $('<div class="colwrap_fof"></div>');  //THE COMPLEX DIV ITSELF 
var div2 = $('<div class="homeimg"></div>');     
var div21 = $('<div id="backImageDiv'+fof_index+'" class="backDiv"></div>'); 
var div22 = $('<div id="frontImageDiv'+fof_index+'" class="frontDiv"></div>'); 
div2.append(div21); 
div2.append(div22); 
div1.append(div2); 
$("#df_background").append(div1);  // ADDING the complex div to the right place  

Chúc mừng,

+2

Xin chào @marcelosalloum, từ kinh nghiệm của tôi, điều này hoàn toàn gây đau đớn khi ai đó nói tôi cần bạn thêm vào vào mã của bạn ..Có, nó không hoạt động, và tôi không thể bình luận về hiệu suất, nhưng nó rất đau đớn để duy trì .. – Ads

+0

Nếu mục đích của bạn là chỉ đơn thuần là tạo ra một mẫu và sau đó điền nó với một số dữ liệu, cá nhân tôi chỉ muốn thực hiện một ' hiển thị: none; 'container cho các phần tử mẫu của tôi, tìm nạp chúng vào các biến javascript bằng cách sử dụng getElementById() hoặc jQuery, sao chép nó, sau đó xử lý dữ liệu tự điền (.textContent = val/.text (val), .setAttribute (attr, val/attr (attr, val)) bởi vì nó dễ dàng hơn để làm điều đó bản thân hơn lo lắng cho dù một số thư viện templating shoddy sẽ làm công việc của mình một cách chính xác và nhiều hơn nữa performant vì tôi biết chính xác những gì tôi muốn làm với các mẫu. –

2

Nó là dễ đọc hơn và duy trì nếu mã JavaScript giống với cấu trúc thẻ HTML. Bạn có thể đi theo tuyến đường jQuery chính thức bằng cách sử dụng $ ('div', {'class': 'etc'}) ...

Đây là một cách tiếp cận hơi khác với hàm $$ để làm cho mỗi phần tử trở thành đối tượng jQuery có thể chỉnh sửa . Nó sẽ được khá nhanh như không có phân tích cú pháp html diễn ra.

$$('div', {'id':'container'}, 
    $$('div', {'id':'my_div'}, 
     $$('h1',{'class':'my_header'}, 
      $$('a',{'href':'/test/', 'class':'my_a_class'}, 'teststring')))); 

Điều này làm cho phương pháp tiếp cận linh hoạt hơn và bạn có thể thêm trình xử lý sự kiện, dữ liệu v.v ... vào các đối tượng jQuery lồng nhau bằng cách sử dụng chuỗi khá dễ dàng.

$$('div', {'id':'container'}, 
    $$('div', {'id':'my_div'}, 
     $$('h1',{'class':'my_header'}, 
      $$('a', { 'href': '/test/', 'class': 'my_a_class' }, 'teststring') 
     ).click(function() { alert('clicking on the header'); }) 
    ).data('data for the div') 
).hide(); 

Mã này có thể đọc được nhiều hơn nếu người ta phải sử dụng jQuery cách tiếp cận chính thức để làm việc đó với các cuộc gọi riêng biệt để .append(), .text(), .html() vv hoặc bằng cách ăn các jQuery $ string ghép nối.

chức năng tham khảo $$:

function $$(tagName, attrTextOrElems) { 
    // Get the arguments coming after the params argument 
    var children = []; 
    for (var _i = 0; _i < (arguments.length - 2) ; _i++) { 
     children[_i] = arguments[_i + 2]; 
    } 

    // Quick way of creating a javascript element without JQuery parsing a string and creating the element 
    var elem = document.createElement(tagName); 
    var $elem = $(elem); 

    // Add any text, nested jQuery elements or attributes 
    if (attrTextOrElems) { 
     if (typeof attrTextOrElems === "string") { // text 
      var text = document.createTextNode(attrTextOrElems); 
      elem.appendChild(text); 
     } 
     else if (attrTextOrElems instanceof jQuery) { // JQuery elem 
      $elem.append(attrTextOrElems); 
     } 
     else // Otherwise an object specifying attributes e.g. { 'class': 'someClass' } 
     { 
      for (var key in attrTextOrElems) { 
       var val = attrTextOrElems[key]; 
       if (val) { 
        elem.setAttribute(key, val); 
       } 
      } 
     } 
    } 

    // Add any further child elements or text  
    if (children) { 
     for (var i = 0; i < children.length; i++) { 
      var child = children[i]; 
      if (typeof child === "string") { // text 
       var text = document.createTextNode(child); 
       elem.appendChild(text); 
      } else { // JQuery elem 
       $elem.append(child); 
      } 
     } 
    } 
    return $elem; 
} 
Các vấn đề liên quan