JQuery를 사용하여 추가 할 HTML 템플릿 정의
반복되는 배열이 있습니다. 조건이 참일 때마다 HTML
일부 값이있는 컨테이너 요소에 아래 코드 사본을 추가하고 싶습니다 .
이 HTML을 현명하게 재사용 할 수있는 위치는 어디입니까?
<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
});
});
프로젝트에서 다음과 같은 템플릿 엔진을 사용하도록 결정할 수 있습니다.
다른 라이브러리를 포함하고 싶지 않은 경우 John Resig는 아래와 유사한 jQuery 솔루션을 제공 합니다.
브라우저와 화면 판독기는 인식 할 수없는 스크립트 유형을 무시합니다.
<script id="hidden-template" type="text/x-custom-template">
<tr>
<td>Foo</td>
<td>Bar</td>
<tr>
</script>
jQuery를 사용하여 템플릿을 기반으로 행을 추가하는 것은 다음과 같습니다.
var template = $('#hidden-template').html();
$('button.addRow').click(function() {
$('#targetTable').append(template);
});
오래된 질문이지만 "jQuery 사용"이라는 질문이 있기 때문에 공급 업체 종속성을 도입하지 않고도이 작업을 수행 할 수있는 옵션을 제공 할 것이라고 생각했습니다.
많은 템플릿 엔진이 있지만 최근에는 반복 ( <% for
), 조건부 ( <% if
) 및 변환 ( <%= myString | uppercase %>
)이 기껏해야 마이크로 언어로 간주되고, 최악의 경우 안티 패턴으로 간주되는 등 여러 기능이 최근에 불리 해졌습니다. 현대의 템플릿 관행은 단순히 객체를 DOM (또는 다른) 표현에 매핑하도록 장려합니다. 예를 들어 ReactJS의 구성 요소 (특히 상태 비 저장 구성 요소)에 매핑 된 속성으로 보는 것.
HTML 내부 템플릿
템플릿의 HTML을 나머지 HTML 옆에 유지하기 위해 신뢰할 수있는 한 가지 속성은 비 실행을 사용하는 것입니다 ( <script>
type
예 : <script type="text/template">
. 귀하의 경우 :
<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>
문서로드시 템플릿을 읽고 간단한 String#split
var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);
Notice that with our token, you get it in the alternating [text, property, text, property]
format. This lets us nicely map it using an Array#map
, with a mapping function:
function render(props) {
return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}
Where props
could look like { url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' }
.
Putting it all together assuming you've parsed and loaded your itemTpl
as above, and you have an items
array in-scope:
$('.search').keyup(function () {
$('.list-items').append(items.map(function (item) {
return itemTpl.map(render(item)).join('');
}));
});
This approach is also only just barely jQuery - you should be able to take the same approach using vanilla javascript with document.querySelector
and .innerHTML
.
Templates inside JS
A question to ask yourself is: do you really want/need to define templates as HTML files? You can always componentize + re-use a template the same way you'd re-use most things you want to repeat: with a function.
In es7-land, using destructuring, template strings, and arrow-functions, you can write downright pretty looking component functions that can be easily loaded using the $.fn.html
method above.
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>
`;
Then you could easily render it, even mapped from an array, like so:
$('.list-items').html([
{ url: '/foo', img: 'foo.png', title: 'Foo item' },
{ url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));
Oh and final note: don't forget to sanitize your properties passed to a template, if they're read from a DB, or someone could pass in HTML (and then run scripts, etc.) from your page.
Use HTML template instead!
Since the accepted answer would represent overloading script method, I would like to suggest another which is, in my opinion, much cleaner and more secure due to XSS risks which come with overloading scripts.
I made a demo to show you how to use it in an action and how to inject one template into another, edit and then add to the document DOM.
example 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>
example 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 <template>
+Its content is effectively inert until activated. Essentially, your markup is hidden DOM and does not render.
+Any content within a template won't have side effects. Scripts don't run, images don't load, audio doesn't play ...until the template is used.
+Content is considered not to be in the document. Using
document.getElementById()
orquerySelector()
in the main page won't return child nodes of a template.+Templates can be placed anywhere inside of
<head>
,<body>
, or<frameset>
and can contain any type of content which is allowed in those elements. Note that "anywhere" means that<template>
can safely be used in places that the HTML parser disallows.
Fall back
Browser support should not be an issue but if you want to cover all possibilities you can make an easy check:
To feature detect
<template>
, create the DOM element and check that the .content property exists:
function supportsTemplate() {
return 'content' in document.createElement('template');
}
if (supportsTemplate()) {
// Good to go!
} else {
// Use old templating techniques or libraries.
}
Some insights about Overloading script method
- +Nothing is rendered - the browser doesn't render this block because the
<script>
tag hasdisplay:none
by default. - +Inert - the browser doesn't parse the script content as JS because its type is set to something other than
"text/javascript"
. - -Security issues - encourages the use of
.innerHTML
. Run-time string parsing of user-supplied data can easily lead to XSS vulnerabilities.
Full article: https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-old
Useful reference: https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode http://caniuse.com/#feat=queryselector
Add somewhere in body
<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>
then create css
.hide { display: none; }
and add to your js
$('#output').append( $('.hide').html() );
Other alternative: Pure
I use it and it has helped me a lot. An example shown on their website:
HTML
<div class="who">
</div>
JSON
{
"who": "Hello Wrrrld"
}
Result
<div class="who">
Hello Wrrrld
</div>
In order to solve this problem, I recognize two solutions:
The first one goes with AJAX, with which you'll have to load the template from another file and just add everytime you want with
.clone()
.$.get('url/to/template', function(data) { temp = data $('.search').keyup(function() { $('.list-items').html(null); $.each(items, function(index) { $(this).append(temp.clone()) }); }); });
Take into account that the event should be added once the ajax has completed to be sure the data is available!
The second one would be to directly add it anywhere in the original html, select it and hide it in jQuery:
temp = $('.list_group_item').hide()
You can after add a new instance of the template with
$('.search').keyup(function() { $('.list-items').html(null); $.each(items, function(index) { $(this).append(temp.clone()) }); });
Same as the previous one, but if you don't want the template to remain there, but just in the javascript, I think you can use (have not tested it!)
.detach()
instead of hide.temp = $('.list_group_item').detach()
.detach()
removes elements from the DOM while keeping the data and events alive (.remove() does not!).
참고URL : https://stackoverflow.com/questions/18673860/defining-a-html-template-to-append-using-jquery
'program story' 카테고리의 다른 글
런타임 중에 방향을 잠그는 방법 (0) | 2020.08.08 |
---|---|
이미 컴파일 된 APK에 서명하는 방법 (0) | 2020.08.08 |
텍스트 영역의 문자 계산 (0) | 2020.08.08 |
Android-부팅시 서비스 시작 (0) | 2020.08.08 |
Android : 새 버전의 gradle로 업데이트 한 후 "Manifest merger failed"오류가 발생 함 (0) | 2020.08.08 |