Template Binding
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="one-way-bind">
<h3>{{language}}</h3>
<select id="lang">
<option value="english">English</option>
<option value="korean">한국어</option>
</select>
<h3>{{timeTable}}</h3>
<table border="1">
<thead>
<tr>
<th>{{no}}</th>
<th>{{time}}</th>
<th>{{updateBtn}}</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>{{time1}}</td>
<td>
<button type="button" id="update-time-1">{{btnText}}</button>
</td>
</tr>
<tr>
<td>2</td>
<td>{{time2}}</td>
<td>
<button type="button" id="update-time-2">{{btnText}}</button>
</td>
</tr>
<tr>
<td>3</td>
<td>{{time3}}</td>
<td>
<button type="button" id="update-time-3">{{btnText}}</button>
</td>
</tr>
</tbody>
</table>
</div>
<script>
const useTemplate = (selector) => {
const TEMPLATE_PROPERTY = '$template';
const elem = document.querySelector(selector);
const delimiters = ['{{', '}}'];
const cacheData = {};
const changeTextNode = elem => {
let startPosition = 0;
let endPosition = 0;
let val = '';
let copiedTemplate = '';
//템플릿 캐싱
if(!elem.hasOwnProperty(TEMPLATE_PROPERTY)){
elem[TEMPLATE_PROPERTY] = elem.textContent;
}
copiedTemplate = elem[TEMPLATE_PROPERTY];
while(startPosition > -1){
val = '';
//시작 위치를 찾는 다
startPosition = copiedTemplate.indexOf(
delimiters[0],
startPosition
);
//데이터가 모두 변경되어 탬플릿 키워드가 없을 때
if(startPosition === -1) break;
//종료 위치를 찾는 다
endPosition = copiedTemplate.indexOf(
delimiters[1],
startPosition + delimiters[0].length - 1
);
//변수 key값을 찾는 다.
const variableName = copiedTemplate.substring(
startPosition + delimiters[0].length,
endPosition
);
//데이터에 변수값이 있을 경우 반영한다.
if(typeof cacheData[variableName] !== 'undefined'){
val = cacheData[variableName];
}
copiedTemplate = copiedTemplate.replace(
delimiters[0] + variableName + delimiters[1],
val,
);
}
if(elem.textContent !== copiedTemplate){
elem.textContent = copiedTemplate;
}
};
const cacheObj = data => {
for(const key in data){
cacheData[key] = data[key];
}
};
const traversal = elem => {
elem.childNodes.forEach(node => {
if(node.childNodes.length > 0){
traversal(node);
}else{
changeTextNode(node);
}
});
};
const bindData = data => {
cacheObj(data);
traversal(elem);
};
return {bindData}
}
</script>
<script>
const LANGUAGES = {
english: {
no: 'No.',
time: 'Time',
updateBtn: 'Button',
timeTable: 'Time Table',
language: 'Language',
btnText: 'Update Button'
},
korean: {
no: '넘버',
time: '시간',
updateBtn: '버튼',
timeTable: '시간표',
language: '한국어',
btnText: '시간 변경'
}
};
const template = useTemplate('#one-way-bind');
template.bindData(LANGUAGES.english);
const updateDate = index => {
template.bindData({
[`time${index}`]: +new Date()
});
};
const lang = document.querySelector('#lang');
lang.onchange = () => {
template.bindData(LANGUAGES[lang.value]);
};
Array
.from({length: 3}, (_v, i) => i + 1)
.forEach((i) => {
updateDate(i);
document.querySelector(`#update-time-${i}`).onclick = ((index => {
return () => {
updateDate(index);
};
})(i));
})
</script>
</body>
</html>