Document Object Model
자바스크립트는 HTML조작에 특화된 언어이지만
HTML과 자바스크립트는 다른 언어입니다.
그래서 자바스크립트에선 <p></p>
이런 html을 직접 해석하고 조작할 수 없습니다.
<script>
<p></p>.innerHTML = '안녕' // error
</script>
자바스크립트는 <p>를 못알아듣는데 어떻게 html태그들을 알아보고 조작할 수 있는걸까요?
자바스크립트가 HTML조작을 하기 위해선 HTML을 자바스크립트가 해석할 수 있는 문법으로 변환해 놓으면 됩니다.
HTML을 자바스크립트가 좋아하는 array또는 objcet자료형에 담아버리면 좋을 것 같은데요.
실제로 브라우저가 HTML페이지를 열 때
HTML을 자바스트립트로 쉽게 찾고 바꾸기 위해 object와 비슷한 자료형에 담아줍니다.
예를 들어
<div style="color : red">안녕하세요</div>
브라우저는 이런 HTML을 발견하면 object자료로 바꾸어 보관해줍니다.
구체적으로는 ver document={} 이런 변수를 하나 만들어 이 안에 넣어줍니다.
ver document = {
div1 : {
style : { color : 'red' }
innerHTML : '안녕하세요'
}
}
이런식으로 object자료에 정리를 해놓습니다.
이렇게 해야 점찍어서 원하는 자료를 출력하고 조작할 수 있습니다.
이제 document.div1.innerHTML = '안녕
이 가능합니다.
위 변수를 document object + model을 붙여
Document Objcet Model(DOM)이라고 부릅니다.
요약하자면
자바스크립트가 HTML에 대한 정보들 (id, class, name, style, innerHTML등)을 object 자료로 정리한 것을 DOM이라고 부릅니다.
브라우저는 HTML문서를 위에서부터 차례로 읽어내려갑니다.
읽을 때마다 HTML을 발견하면 DOM에 추가해줍니다.
그래서 이걸 알면 왜 하단 코드가 에러 나는지도 이해할 수 있습니다.
(HTML 파일)
<script>
document.getElementById('test').innerHTML = '안녕';
</script>
<p id="test">임시글자</p>
이렇게 코드를 짜면 에러나는 이유가 뭘까요?
브라우저는 HTML을 위에부터 읽어내려온다고 했습니다.
그런데 갑자기 자바스크립트로 <p id = "test">
인 요소를 DOM에서 찾아 바꾸라고 명령을 주게 되면 에러가 나게 됩니다.
왜냐면 아직 <p id="test">
를 읽기 전이라 p태그에 대한 DOM이 아직 생성되지 않았기 때문입니다.
이렇게 자바스크립트는 DOM이 생성된 경우에만 HTML을 변경할 수 있습니다.
"이 코드는 HTML을 전부 다 읽고 실행해주세요"라고 코드를 짜놓을 수 있습니다.
$(document).ready(function(){ 실행할 코드 })
document.addEventListener('DOMContentLoaded', function() { 실행할 코드 })
이 둘중에 하나 쓰면 됩니다.
이 이벤트리스너들은 "HTML을 다 읽어들였는지"를 알려주는 이벤트리스너입니다.
(html 파일)
<script>
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('test').innerHTML = '안녕';
})
</script>
<p id="test">임시글자</p>
그래서 "저 밑에 있는 <p id="test">
변경해주세요"라고 해도 동작하게 되는겁니다.
그래서 ready아니면 DOMContentLoaded이벤트리스너를 쓰는게 안정적만 요즘은 그냥 자바스크립트를 <body>태그 끝나기 전에 전부 작성하기 때문에 그런 걱정은 안해도 될 듯 합니다.
자바스크립트 위치를 내가 정할 수 없을 경우에 유용한 방법이라고 생각하면 되겠습니다.
load이벤트리스너를 사용하면 DOM 생성 뿐만 아니라 이미지, css, js파일이 로드되었는지도 체크가 가능합니다.
이미지같은게 로드되면 load라는 이벤트가 발생하기 때문입니다.
셀렉터로찾은이미지.addEventListener('load', function(){
// 이미지 로드되면 실행할 코드
}
이런식으로 사용하면 됩니다.
근데 외부 자바스크립트 파일에 저걸 적어놓으면 그 js파일보다 이미지가 더 먼저 로드되는 경우가 있으니 이벤트 발생체크를 못할 수도 있습니다.
$(window).on('load', function(){
// document 안의 이미지, js 파일 포함 전부 로드가 되었을 경우 실행할 코드
});
window.addEventListener('load', function(){
// document 안의 이미지, js 파일 포함 전부 로드가 되었을 경우 실행할 코드
});
window에 붙여도 됩니다.
document에 포함된 이미지, CSS파일 등 모든것이 로드가 되었는지 체크합니다.
ready와의 차이는 앞선 .ready()는 DOM생성만 체크하는 함수인데, 이것보다 약간 더 나아가 모든 파일과 이미지 로드 상태를 체크한다고 보시면 됩니다.
그래서 이걸 쓰면 "이미지가 다 로드되면 보여주는 사이트"를 만들 수 있습니다~
DOM(Document Object Model)
.ready
load