본문 바로가기

html5 문법(7) 노드생성 추가 삭제

by Recstasy 2019. 5. 29.

(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)가 실행된다. 콘텐츠를 다시 그려야 하기 때문이다.

이런 상황에서는 DocumentFragment 메소드가 유용하다. Fragment는 이름 그대로 조각이다.


일시적으로 노드들을 담아놓는 그릇이 Fragment 메소드이다. 마지막에서 각각 노드들을 다시 그리는 작업을 하지 않는다. 사전에 list 노드들을 저장해 뒀다가, 마지막 appendChild구문에서 붙이기만 하면, 실행속도는 더 빨라진다. Fragment 메소드로 위의 코드를 수정하면 아래처럼 된다.


빨간색 부분을 주의깊게 살펴보자.


[frag예제]

<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');  ul태그는 마지막에 만들어서 붙여넣는다.
var frag = document.createDocumentFragment( );
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);
frag.appendChild(li);
}
document.getElementById('list').appendChild(frag);
})
</script>



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루프구문은 위의 코드로 사용하도록 하자.

댓글

최신글 전체

이미지
제목
글쓴이
등록일