JQuery kullanarak eklenecek bir HTML şablonu tanımlama


125

Döndüğüm bir dizim var. Her koşul doğru olduğunda, HTMLaşağıdaki kodun bir kopyasını bazı değerlere sahip bir kapsayıcı öğesine eklemek istiyorum .

Bu HTML'yi akıllı bir şekilde yeniden kullanmak için nereye koyabilirim?

<a href="#" class="list-group-item">
    <div class="image">
         <img src="" />
    </div>
    <p class="list-group-item-text"></p>
</a>

JQuery

$('.search').keyup(function() {
    $('.list-items').html(null);

    $.each(items, function(index) {
        // APPENDING CODE HERE
    });
});

2
Akıllı bir yol arıyorsanız, tüm bilgilerinizi tek bir DIV'ye koyun ve ona stil verin. Yalnızca iki hücreli çok sayıda tablo oluşturmayın, bunları bağlantılara sarmayın.
Sergey Snegirev

3
OP açıkça uygun kodlama uygulamalarıyla (tebrikler!) İlgileniyor, bu yüzden yardım etmek istedim. Asıl soruna katkıda bulunmak isteseydim, bir cevap gönderirdim. Eminim herkes, bir görüntüyü konumlandırmak için tam gelişmiş iki hücreli bir tablo kullanmanın ve bazı metinlerin gerçekten egzotik gereksinimler (IE4?) Dışında zar zor gerekçelendirildiğini kabul eder
Sergey Snegirev

1
@BrianG. Bir yorum göndermek gerçekten teğet geçtiğiniz anlamına gelmez. Yorumların onlar için uygun bir yer olduğu konusunda hemfikir olsam da (hala alakalı oldukları sürece), aynı zamanda onları bir cevaba genişletmek için vakti olmayan kişilerin arabadan gelebilecekleri ipuçları için de uygundurlar. OP'nin hangisini yaptığınızı netleştirmesi yararlıdır.
millimoose

Sorunu kimse cevaplamadı mı Patrick?
Sebastian Neira

Yanıtlar:


164

Projenizde aşağıdakiler gibi bir şablon oluşturma motorunu kullanmaya karar verebilirsiniz:

Başka bir kitaplık eklemek istemiyorsanız, John Resig aşağıdakine benzer bir jQuery çözümü sunar .


Tarayıcılar ve ekran okuyucular, tanınmayan komut dosyası türlerini göz ardı eder:

<script id="hidden-template" type="text/x-custom-template">
    <tr>
        <td>Foo</td>
        <td>Bar</td>
    <tr>
</script>

JQuery kullanıldığında, şablona göre satır eklemek şuna benzer olacaktır:

var template = $('#hidden-template').html();

$('button.addRow').click(function() {
    $('#targetTable').append(template);
});

@MaksimLuzik haklı. Bıyık (ticari marka yazımına dikkat edin) daha hafiftir ve OP'nin koduna takılır, ancak Gidon dizileri kullanmak için daha fazla özelliğe sahiptir ve sonunda daha yeterli bir çözüm sağlayabilir. İşte güzel bir karşılaştırma makalesi: blog.cubettech.com/…
Michael Scheper

13
Şablonun nasıl düzenleneceğine dair örnek: jsfiddle.net/meehanman/7vw8bc84
Dean Meehan

175

Eski soru, ancak soru "jQuery kullanarak" diye sorduğundan, bunu herhangi bir satıcı bağımlılığı getirmeden yapmanıza izin veren bir seçenek sunacağımı düşündüm.

Piyasada çok sayıda şablon oluşturma motoru varken, özelliklerinin çoğu, en iyi durumda mikro dil olarak görülen iterasyon ( <% for), koşullu ifadeler ( <% if) ve dönüşümler ( <%= myString | uppercase %>) ve en kötü ihtimalle anti-kalıplar ile son zamanlarda gözden düşmeye başladı. Modern şablon oluşturma uygulamaları, bir nesneyi DOM (veya diğer) temsiliyle, örneğin ReactJS'deki bileşenlerle eşlenen özelliklerle (özellikle durumsuz bileşenler) gördüğümüzle eşlemeyi teşvik eder.

HTML İçindeki Şablonlar

Şablonunuzun HTML'sini HTML'nizin geri kalanının yanında tutmak için güvenebileceğiniz bir özellik, yürütülemeyen kullanmaktır <script> type, ör <script type="text/template">. Davanız için:

<script type="text/template" data-template="listitem">
    <a href="${url}" class="list-group-item">
        <table>
            <tr>
                <td><img src="${img}"></td>
                <td><p class="list-group-item-text">${title}</p></td>
            </tr>
        </table>
    </a>
</script>

Belge yüklenirken şablonunuzu okuyun ve basit bir String#split

var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);

Jetonumuzla, onu alternatif [text, property, text, property]biçimde aldığınıza dikkat edin . Bu Array#map, onu bir eşleme işlevi ile bir kullanarak güzel bir şekilde eşlememizi sağlar:

function render(props) {
  return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}

Nereye propsbenzeyebilir { url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' }.

itemTplYukarıdaki gibi ayrıştırıp yüklediğinizi ve itemskapsam dahilinde bir diziniz olduğunu varsayarak hepsini bir araya getirirsek :

$('.search').keyup(function () {
  $('.list-items').append(items.map(function (item) {
    return itemTpl.map(render(item)).join('');
  }));
});

Bu yaklaşım aynı zamanda sadece neredeyse hiç jQuery - aynı yaklaşımı vanilya javascript'i document.querySelectorve ile birlikte kullanabilmelisiniz .innerHTML.

jsfiddle

JS içindeki şablonlar

Kendinize sormanız gereken bir soru şudur: Şablonları HTML dosyaları olarak tanımlamak gerçekten istiyor musunuz / buna ihtiyacınız var mı? Bir şablonu her zaman, tekrarlamak istediğiniz çoğu şeyi yeniden kullandığınız şekilde bileşenleştirebilir + yeniden kullanabilirsiniz: bir işlevle.

Es7-land'de, yıkım, şablon dizgileri ve ok işlevlerini kullanarak, $.fn.htmlyukarıdaki yöntemi kullanarak kolayca yüklenebilen düpedüz güzel görünümlü bileşen işlevleri yazabilirsiniz .

const Item = ({ url, img, title }) => `
  <a href="${url}" class="list-group-item">
    <div class="image">
      <img src="${img}" />
    </div>
    <p class="list-group-item-text">${title}</p>
  </a>
`;

Ardından, bir diziden eşlenmiş olsa bile, şöyle kolayca oluşturabilirsiniz:

$('.list-items').html([
  { url: '/foo', img: 'foo.png', title: 'Foo item' },
  { url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));

Oh ve son not: Bir şablona aktarılan özelliklerinizi, eğer bir veritabanından okunuyorlarsa, ya da birisi sayfanızdan HTML'de geçebilirse (ve sonra komut dosyalarını çalıştırabilir, vb.) Temizlemeyi unutmayın.


1
Güzel şablon motoru.
Arthur Castro

41
Kişisel JS içindeki Şablonlar bölümünde bomba
BigRon

2
"HTML İçinde Şablonlar" yaklaşımı için bir demo / keman ekleyebilir misiniz?
LCJ

1
Vaov! JS içindeki şablon ... Bunu hiç düşünmedim! İnanılmaz!
Roman Lopez

2
Vay canına, bu gerçekten çok güzel. Her şablona bir data-url özelliği ekliyorum. Ve her biri için ajax verilerini alıyorum. Bu çok güzel ve bana çok zaman kazandırdı! Teşekkür ederim.
Davey

42

Bunun yerine HTML şablonu kullanın!

Kabul edilen yanıt, aşırı yükleme komut dosyası yöntemini temsil edeceğinden, bence aşırı yükleme komut dosyalarıyla birlikte gelen XSS riskleri nedeniyle çok daha temiz ve daha güvenli olan başka bir yanıt önermek isterim.

Bunu bir eylemde nasıl kullanacağınızı ve bir şablonu diğerine nasıl ekleyeceğinizi, düzenleyeceğinizi ve sonra DOM belgesine nasıl ekleyeceğinizi göstermek için bir demo hazırladım .

örnek html

<template id="mytemplate">
  <style>
     .image{
        width: 100%;
        height: auto;
     }
  </style>
  <a href="#" class="list-group-item">
    <div class="image">
      <img src="" />
    </div>
    <p class="list-group-item-text"></p>
  </a>
</template>

örnek js

// select
var t = document.querySelector('#mytemplate');

// set
t.content.querySelector('img').src = 'demo.png';
t.content.querySelector('p').textContent= 'demo text';

// add to document DOM
var clone = document.importNode(t.content, true); // where true means deep copy
document.body.appendChild(clone);

HTML <şablon>

  • + İçeriği, etkinleştirilene kadar etkili bir şekilde inerttir. Esasen, işaretlemeniz gizli DOM'dur ve işlemez.

  • + Bir şablondaki herhangi bir içeriğin yan etkisi olmayacaktır. Şablon kullanılana kadar komut dosyaları çalışmaz, resimler yüklenmez, ses oynatılmaz.

  • + İçerik belgede yer almamaktadır. Ana sayfada document.getElementById()veya kullanmak querySelector()bir şablonun alt düğümlerini döndürmez.

  • + Şablonlar içinde herhangi bir yere ait yerleştirilebilir <head>, <body>ya da <frameset>ve bu elemanlar izin verilir bir içeriği içerebilir. "Her yerde" <template>ifadesinin, HTML ayrıştırıcısının izin vermediği yerlerde güvenle kullanılabileceği anlamına geldiğini unutmayın .

Geri çekil

Tarayıcı desteği bir sorun olmamalı, ancak tüm olasılıkları kapsamak istiyorsanız, kolay bir kontrol yapabilirsiniz:

Özelliği algılamak <template>, DOM öğesi oluşturun ve .content özellik var olduğunu kontrol edin:

function supportsTemplate() {
  return 'content' in document.createElement('template');
}

if (supportsTemplate()) {
  // Good to go!
} else {
  // Use old templating techniques or libraries.
}

Aşırı yükleme komut dosyası yöntemi hakkında bazı bilgiler

  • + Hiçbir şey oluşturulmaz - <script>etiket display:nonevarsayılan olarak sahip olduğu için tarayıcı bu bloğu işlemez .
  • + Inert - tarayıcı komut dosyası içeriğini JS olarak ayrıştırmaz çünkü türü, dışında bir şeye ayarlanmıştır "text/javascript".
  • -Güvenlik sorunları - kullanımını teşvik eder .innerHTML. Kullanıcı tarafından sağlanan verilerin çalışma zamanı dizesi ayrıştırması, kolayca XSS güvenlik açıklarına yol açabilir.

Tam makale: https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-old

Faydalı referans: https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode http://caniuse.com/#feat=queryselector

WEB BİLEŞENLERİ OLUŞTURMA Trawersy Media tarafından hazırlanan HTML şablonlarını kullanarak özel web bileşenleri öğreticisi oluşturma: https://youtu.be/PCWaFLy3VUo


4
templateEleman (2018 itibariyle, IE11) Internet Explorer tarafından desteklenmez. W3c.github.io/html/single-page.html'deki örnek 580 ile test edilmiştir .
Roland

Ben gibi <template>berraktır, ben özgürce sınıfları kullanarak öneririm olsa yani ne sahne neye seti alıyorsanız. Verilerinizi şablonla doğru bir şekilde eşlemek, özellikle de büyük veri kümelerinde eşleme yapmak için bileşenler tarzı bir yaklaşım kullanmak, bazı js becerileri gerektirir. Şahsen ben hala HTML'yi işlevlerde oluşturmayı veya ideal olarak DOM'u doğrudan JS'nin kendisi ile oluşturmayı ve HTML'yi tamamen terk etmeyi seviyorum (örneğin, React bunu nasıl yapıyor).
Qaribou'dan Josh

Şablon yaklaşımı benim için iyi çalıştı. Bir önerim, önce şablonu klonlamak (sonunda değil) ve klonlanmış nesne ile çalışmaktır. Aksi takdirde, yaptığınız değişiklikler şablonun kendisine olur. Bazı özellikleri / içeriği yalnızca belirli zamanlarda ayarladığınız koşullu mantığınız olsaydı, bu özellikler şablonu bir sonraki kullanımınızda mevcut olacaktır. Her kullanımdan önce klonlayarak, çalışmak için her zaman tutarlı bir tabana sahip olduğunuzdan emin olursunuz.
jt.

13

Vücutta bir yer ekleyin

<div class="hide">
<a href="#" class="list-group-item">
    <table>
        <tr>
            <td><img src=""></td>
            <td><p class="list-group-item-text"></p></td>
        </tr>
    </table>
</a>
</div>

sonra css oluştur

.hide { display: none; }

ve js'nize ekleyin

$('#output').append( $('.hide').html() );

1
OP'nin bir JSON'si vardır ve bu diziyi veri kaynağı olarak kullanarak bir miktar html oluşturmak ister. Bu cevap sorunu nasıl ele alıyor? Cevabınız bir html düğümü alır ve onu klonlar / çoğaltır ve veri bağlamayla ilgili hiçbir şey yapmaz.
Adrian Iftode

Yani olumsuz oy veren benim.
Adrian Iftode

Gerçekten daha iyi bir yanıt almanıza yardımcı olmadığınızı düşünüyorum, çünkü sorunun daha geniş olduğunu hatırlatarak başlayabilirdiniz.
Sebastian Neira

1
Bu işe yarıyor, ancak yapmaktan .children().clone()ziyade daha verimli .html(). Hız, <tr/>bu kodu kullanan bir sayfada rastgele gördüğüm için yaklaşık 3: 1 i=10000; time=performance.now(); while (--i) {$a.clone().append(0 ? $b.html() : $b.children().clone())} performance.now()-time. Oran aslında biraz daha abartılı çünkü ben $ a.clone () kullanıyorum, ancak onu boşaltmaya çalışmak her yineleme klonlamadan çok bir performans vuruşu, bu yüzden onu nasıl daha doğru hale getireceğimi bilmiyorum çünkü zamanlama fonksiyonlarının kendi maliyetleri vardır.
Chinoto Vokro

1
Bu yaklaşım kötü. temel olarak, kullanmamış olsanız bile şablon içeriği indirilir ve ayrıştırılır. Bu, bunu geçerli bir cevap olarak kabul etmek için çok büyük bir konu. Ayrıca yukarıdaki başka bir menthon gibi, en azından .html () yerine klon kullanmanız gerekiyorsa
DevWL

3

Diğer alternatif: Saf

Kullanıyorum ve bana çok yardımcı oldu. Web sitelerinde gösterilen bir örnek:

HTML

<div class="who">
</div>

JSON

{
  "who": "Hello Wrrrld"
}

Sonuç

<div class="who">
  Hello Wrrrld
</div>

2

Bu sorunu çözmek için iki çözüm tanıyorum:

  • İlki, şablonu başka bir dosyadan yüklemeniz ve istediğiniz zaman eklemeniz gereken AJAX ile birlikte gelir .clone().

    $.get('url/to/template', function(data) {
        temp = data
        $('.search').keyup(function() {
            $('.list-items').html(null);
    
            $.each(items, function(index) {
                 $(this).append(temp.clone())
            });
    
        });
    });

    Verilerin mevcut olduğundan emin olmak için ajax tamamlandıktan sonra etkinliğin eklenmesi gerektiğini dikkate alın!

  • İkincisi, onu doğrudan orijinal html'de herhangi bir yere eklemek, seçmek ve jQuery'de gizlemek olacaktır:

    temp = $('.list_group_item').hide()

    Şununla şablonun yeni bir örneğini ekledikten sonra

    $('.search').keyup(function() {
        $('.list-items').html(null);
    
        $.each(items, function(index) {
            $(this).append(temp.clone())
        });
    });
  • Bir öncekiyle aynı, ancak şablonun orada kalmasını istemiyorsanız, ancak sadece javascript'te ise, .detach()gizlemek yerine ( test etmedim!) Kullanabilirsiniz .

    temp = $('.list_group_item').detach()

    .detach() verileri ve olayları canlı tutarken DOM'dan öğeleri kaldırır (.remove () bunu yapmaz!).


-- Problem yok! -
iConnor

Operasyonun bir JSON'si var ve bu diziyi veri kaynağı olarak kullanarak bir miktar html oluşturmak istiyor. Bu cevap sorunu nasıl ele alıyor? Cevabınız bir html düğümü alır ve onu klonlar / çoğaltır ve veri bağlamayla ilgili hiçbir şey yapmaz.
Adrian Iftode

1
Op'tan alıntı yapıyorum: Aşağıdaki HTML kodunun bir kopyasını bazı değerleri olan bir kap elemanına eklemek istiyorum. Bunun onun sorununu çözdüğüne inanıyorum.
Sebastian Neira

Ve "bazı değerler" kısmı nasıl ele alınır?
Adrian Iftode

Bu, sorunu çözmediği anlamına gelmez. Bana noktalardan birini kaçırdığımı söylemenize minnettarım :) Her neyse, hangi değerlerden bahsettiğimizi bilmiyorsam, bu değerleri nasıl ekleyeceğimi nasıl bilebilirim ? Bu kısma bir göz atın Bu HTML'yi akıllı bir şekilde yeniden kullanmak için nereye koyabilirim? . Gerçekten ne soruluyor? JSON veya HTML dahil etme hakkında?
Sebastian Neira

1

Çok iyi cevap dan DevWL yerel HTML5 kullanmayla ilgili şablon elemanı. OP'den gelen bu güzel soruya katkıda bulunmak için template, jQuery kullanarak bu öğenin nasıl kullanılacağına dair bir şeyler eklemek istiyorum , örneğin:

$($('template').html()).insertAfter( $('#somewhere_else') );

İçeriği templatehtml değildir, yalnızca veri olarak değerlendirilir, bu nedenle içeriği jQuery'nin yöntemlerine erişmek için bir jQuery nesnesine sarmalamanız gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.