(7) 노드 생성,추가,삭제
지난 포스팅에서 innerHTML = ' '; 을 가급적이면 사용하지 말
것을 강조했다. innerHTML에서 사용자가 태그를 사용하거나 스타일시트 명령어를 내릴
경우, 전체 페이지에 영향을 줄 수 있기 때문이다. 사용자의 글을 받을 때는 createXXX 시리즈 메소드를 활용하여
동적인 어플리케이션을 구현해야 한다.
1 노드 생성 및 추가
form에서 input태그를 이용하여, 사용자의 url 이름을 받은 후에, <a>태그를 createElement('a')로 만들고, appendChild 메소드를 이용하여 createTextNode를 실행한다. 아래 예제를 실행해보자. 사용자가 입력한 텍스트와 사이트 주소가 링크된 결과로 값이 나온다.
[예제]
<form>
<div>
<label for='name'>사이트명:</label><br>
<input type="text" id="name" size="30" name="name">
</div>
<div>
<label for='url'>URL:</label><br>
<input type="url" id="url" name="url" size="50">
</div>
<div>
<input type="button" id="btn" value="추가"/>
</div>
</form>
<div id="list"></div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function( ){
document.getElementById('btn').addEventListener('click',function( ){
var name = document.getElementById('name');
var url = document.getElementById('url');
//<a>생성
var anchor = document.createElement('a');
anchor.href = url.value;
// text노드 생성
var text = document.createTextNode(name.value);
anchor.appendChild(text);
//br요소 생성
var br = document.createElement('br');
var list = document.getElementById('list');
list.appendChild(anchor);
list.appendChild(br);
})
})
</script>
createXXX 메소드의 종류를
정리해보자.
메소드 |
생성노드 |
createElement(요소명) |
요소 노드 |
createAttribute(속성명) |
속성 노드 |
createTextNode(텍스트) |
텍스트 노드 |
createCDATASection(텍스트) |
CDATA 섹션 |
createComment(텍스트) |
주석 노드 |
createEntityReference(실체명) |
실체 참조 노드 |
createProcessingInstruction(타겟명,데이터) |
처리 명령 노드 |
createDocumentFragment( ) |
문서의 단편 |
2 insertBefore( ) & appendChild( )
insertBefor( ) 메소드와 appendChild( ) 메소드의 차이점은 먼저 들어가는 인자의 차이가 있다. appendChild( )같은 경우는 요소1.appendChild( 요소2 )라고 한다면, 요소2는 요소1의 맨 끝에 삽입된다.
만일, 요소2를 요소1 앞에 넣고 싶다면, 요소1.insertBefor( 요소2, 요소1.firstChild )라고 해야 한다. 반대로, insertBefore( )메소드에서 요소2를 맨 끝에 위치하고 싶다면, 다음과 같이 작성한다.
`` 요소1.insertBefore( 요소2 , null ); ``
3 속성노드 추가
위의 코드에서 href.value = url.value 라고 작성한 부분이 있다. 이를 조금 엄밀하게 코딩한다면 아래처럼 코딩해야 한다.
var href = document.createAttribute('href');
href.value = url.value;
anchor.setAttributeNode(href);
4 createFragment( )
[예제]
<ul id="list"></ul>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function(){
var car = [
{ title:'우라칸', brand:'람보르기니' },
{ title:'CT7', brand:'캐딜락'},
{ title:'DB11', brand:'애스턴마틴'}
]
var list = document.getElementById('list');
for(var i=0; i<car.length; i++){
var car_ = car[i];
var li = document.createElement('li');
var content = document.createTextNode(car_.title+','+car_.brand);
li.appendChild(content);
list.appendChild(li);
}
})
</script>
위의 코드는 얼핏 보기에 별 문제가 없는 것처럼 보인다. 그러나 마지막 list.appendChild(li);에서 계속 createElement(li)가 실행된다. 콘텐츠를 다시 그려야 하기 때문이다.
[frag예제]
5 노드 치환/ 삭제
<ul id='list'>
<li><a href="#" data-exp="04">애스턴마틴 뱅퀴시S Side</a></li>
<li><a href="#" data-exp="05">애스턴마틴 뱅퀴시S Front</a></li>
<li><a href="#" data-exp="06">애스턴마틴 뱅퀴시S Back</a></li>
<li><a href="javascript:void(0)" data-exp="07">애스턴마틴 뱅퀴스S Interior</a></li>
</ul>
<input type="button" id="del" value="삭제" disabled />
<div id="pic"></div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function( ){
var list = document.getElementById('list');
var pic = document.getElementById('pic');
var del = document.getElementById('del');
list.addEventListener('click',function(e){
var dataexp = e.target.getAttribute('data-exp');
if(dataexp){
var img = document.createElement('img');
img.src = 'http://carholic.net/wp-content/uploads/2016/12/Aston_Martin-Vanquish_S-2017-1600-'+dataexp+'.jpg';
img.height = 150;
img.width = 224;
if(pic.getElementsByTagName('img').length > 0){
pic.replaceChild(img,pic.lastChild);
}else{
del.disabled = false;
pic.appendChild(img);
}
}
});
del.addEventListener('click',function( ){
pic.removeChild(pic.lastChild);
del.disabled = true;
});
});
</script>
* Live 노드 주의점
아래 코드는 무한루프가 된다.
<ul
id="one">
<li>사과</li>
<li>복숭아</li>
<li>청포도</li>
<li>블루베리</li>
</ul>
<ul
id="two"> </ul>
<script>
document.addEventListener('DOMContentLoaded, function(
){
var two = document.getElementById('two');
var li =
document.getElementsByTagName('li');
for( var i=0; i < li.length; i++
){
var item = li.item( i );
var new_li = document.createElement( 'li' );
var new_txt = document.createTextNode(item.textContent);
new_li.appendChild(new_txt);
two.appendChild(new_li);
}
}
</script>
ul id =one의 요소들을 복사해서 ul id=two로 옮겨가는 코드처럼 보이지만 위의 코드는 무한루프에 빠진다. HTMLCollection 객체는 살아있는 객체이기 때문이다.
for구문에 의해 루프를 할 때마다 노드의 개수 (li.length)는 변한다. 따라서 for블록의 종료 조건인 i < li.length가 false로 되지 않아 무한루프가 되는 것이다. 이를 방지하려면, 값을 미리 변수에 담아두는 방식으로 for루프구문을 아래처럼 작성해야 한다.
`` for( var i=0; len = li.length; i < len; i++ ) ``
length 값을 변수 len에 보관함으로써, lenth 프로퍼티의 변화가 종료
조건에 영향을 끼치지 않는 코드가 된다. length 자체가 큰 오버헤드를 유발하므로 for루프구문은 위의 코드로
사용하도록 하자.
'코드 스터디' 카테고리의 다른 글
Angular 기본 (1) Angular cli설치 (0) | 2019.05.31 |
---|---|
html5 문법 (8) 이벤트 심화[사용자 화면] (0) | 2019.05.30 |
html5 문법 (6) 파일업로드 (0) | 2019.05.28 |
html5 문법 (5) form값 얻기 (0) | 2019.05.27 |
html5 문법 (4) 속성 프로퍼티 (0) | 2019.05.26 |
댓글