-
혼자 공부하는 자바스크립트 7장 - 문서 객체 모델자바스크립트/혼자 공부하는 자바스크립트 2021. 8. 8. 23:51
문서 객체 모델
DOM, Document Object Model: 문서 객체를 조합해서 만든 전체적인 형태
HTML 요소를 자바스크립트에서는 문서 객체라고 부른다. 즉, 문서 객체를 조작한다는 말은 HTML 요소를 조작한다는 의미이다.
DOMContentLoaded 이벤트
문서 객체를 조작할 때는 DOMContentLoaded 이벤트를 사용한다. 이때, 오탈자를 입력해도 오류가 발생하지 않으므로 주의한다.
document.addEventListner("DOMContentLoaded", () => { })
HTML 문서에서,
<head> > <script> > document.body
의 문장은 실행되지 않는다.body
태그에 앞서body
를 조작했기 때문이다.head
태그 안에서body
태그에 접근 하려면DOMContentLoaded
이벤트를 사용해 문서 객체를 모두 읽고 나서 실행되도록 해야한다.<head> <title>DOMContentLoaded</title> <script> document.addEventListner("DOMContentLoaded", () => { const h1 = (text) => `<h1>${text}</h1>`; document.body.innerHTML += h1("DOMContentLoaded 이벤트 발생"); }) </script> </head>
웹 브라우저가 문서 객체를 모두 읽고 나면(즉, DOMContentLoaded 상태가 되면), 콜백함수를 호출해 문서 body에
DOMContentLoaded 이벤트 발생
이라는 내용의h1
태그가 생성된다.문서 객체 가져오기
document.body
,document.head
,document.title
등으로 HTML 요소를 불러올 수 있다. 이외의 다른 요소들은 별도의 메소드를 사용한다.document.querySelector(CSS 선택자) document.querySelectorAll(CSS 선택자)
querySelector()
메소드는 요소를 하나만 추출하고,querySelectorAll()
메소드는 문서 객체를 여러 개 추출한다.글자 조작하기
textContent
는 입력된 문자열을 그대로 넣고,innerHTML
은 입력된 문자열을 HTML 형식으로 넣는다.<head> <script> document.addEventListner("DOMContentLoaded", () => { const a = document.querySelector("#a"); const b = document.querySelector("#b"); a.textContent = `<h1>textContent 속성</h1>` b.innerHTML = `<h1>innerHTML 속성</h1>` }) </script> </head> <body> <div id = a></div> <div id = b></div> </body>
실행해보면
div#a
의 경우에는 내용에<h1>textContent 속성</h1>
이 그대로, 태그까지 적혀있지만,div#b
의 경우에는innerHTML 속성
이라는 내용이h1
요소로 변환된 채로 적혀있는 것을 확인할 수 있다.속성 조작하기
객체.setAttribute(속성, 값)
은 특정 속성에 값을 지정하고,객체.getAttribute(속성, 값)
은 특정 속성을 추출한다.스타일 조작하기
문서 객체의 스타일을 조작할 때는
style
속성을 사용한다.style
속성은 객체이며, 내부에는 CSS를 사용해 지정할 수 있는 스타일들이 있다. 이때, CSS에선background-color
와 같이 하이픈 기호가 쓰인 속성은 자바스크립트에선backgroundColor
와 같이 캐멀 케이스로 나타낸다.h1.style.backgroundColor = "red"; // 이 방식을 가장 많이 사용한다. he.style["backgroundColor"] = "red"; h1.style["background-color"] = "red";
const divs = document.querySelectorAll("body > div"); // body 태그 아래의 div 태그 25개를 선택한다. divs.forEach( (div, index) =>{ console.log(div, index); const val = index * 10; div.style.height = `10px`; div.style.backgroundColor = `rgb(${val}, ${val}, ${val})`; })
divs
배열에 들어있는 25개div
요소들의 인덱스에 10을 곱한 값을 rgb로 배경색으로 지정하는 코드이다.body
에div
태그 25개를 생성하면 rgb(0, 0, 0)에서 rgb(250, 250, 250)까지의div
들을 볼 수 있다.문서 객체 생성하기
문서 객체를 생성하고 싶을 때엔
document.createElement(문서 객체 이름)
을 사용한다. 만든 뒤, 부모 객체에 추가하기 위해부모 객체.appendChild(자식 객체)
메소드를 사용한다.이때, 문서 객체의 부모는 언제나 하나여야 하므로, 다른 문서 객체에
appendChild()
를 사용하면 해당 객체는 이동한다.제거할 때는
부모 객체.removeChild(자식 객체)
메소드를 사용한다.이벤트 설정하기
모든 문서 객체는 생성, 클릭 등을 할 때 이벤트가 발생한다. 이벤트가 발생할 때 실행할 함수를 이벤트 리스너 또는 이벤트 핸들러라고 하고, 변수 또는 상수로 미리 선언한 뒤, 이를 연결과 제거할 때 사용한다.
추가할 땐
addEventListner()
메소드, 제거할 땐removeEventListener()
메소드를 사용한다.객체.addEventListner(이벤트 이름, 이벤트 리스너); 객체.removeEventListener(이벤트 이름, 이벤트 리스너);
이벤트 활용
이벤트 모델
이벤트를 연결하는 방법을 이벤트 모델이라고 하며,
addEventListenter()
메소드는 현재 표준 이벤트 모델이다.과거에는 문서 객체가 갖고 있는
onXXX
속성에 함수를 할당해 이벤트를 연결했는데, 이를 고전 이벤트 모델이라고 한다.document.body.onkeyup = (event) => { }
onXXX
속성을 HTML 요소에 직접 넣어서 이벤트를 연결하는 것을 인라인 이벤트 모델이라고 한다.const listner = (event) => { }// HTML<body onkeyup="listener(event)"> </body>
인라인 이벤트 모델은 고전 이벤트 모델처럼,
onXXX
속성에 자바스크립트 코드를 넣는 것이다. 위의 코드에선onkeyup
속성에서listener()
함수를 호출하고 있다. 이때,listener
함수의 매개변수는event
이다.모든 이벤트 모델의 이벤트 리스너는 첫 번째 매개변수로 이벤트 객체를 받는다. 이 이벤트 객체에는 이벤트와 관련된 정보가 들어있다.
2000년대 이전의 웹은 인라인 이벤트 모델을 주로 사용했다. 이후 2010년대 이전까진 자바스크립트의 활용이 늘어나며 고전 이벤트 모델을 많이 사용했다. 하지만 고전 이벤트 모델은 이벤트 리스너를 하나만 연결할 수 있다는 단점이 있으므로, 현재는 표준 이벤트 모델을 사용해 이벤트 리스너를 여러 개 연결하는 방식을 많이 사용한다.
인라인 이벤트 모델을 사용되지 않은지 오래 되었지만, 최근 프론트엔드 프론트엔드 프레임워크들이 인라인 이벤트 모델을 활용하는 형태로 코드를 작성해서, 현재에는 인라인 이벤트 모델 역시 많이 사용한다.
키보드 이벤트
키가 눌릴 때 실행되는
keydown
, 키가 입력되었을 때 실행되는keypress
, 키가 떨어질 때 실행되는keyup
이벤트가 있다.keydown
이벤트와keypress
이벤트는 웹 브라우저에 따라 한, 중, 일어 등의 아시아권 문자를 제대로 처리하지 못하는 문제가 있어 일반적으로keyup
이벤트를 사용한다.키보드 이벤트를 실행할 때는 이벤트 객체로 어떤 키를 눌렀는지와 관련된 속성들이 따라온다.
altKey
,ctrlKey
,shiftKey
속성은 해당 키를 눌렀는 지 불 자료형 값이 들어있고,code
속성은 입력한 키를 나타내는 문자열이 들어있다.트위터 메인 페이지에서 N을 누르면 새 트윗 작성, I를 누르면 새 쪽지 작성 등을 할 수 있는데, 이러한 단축키는 키보드 이벤트 속성을 사용하여 구현할 수 있다.
IE나 구 버전의 엣지 브라우저는
code
속성을 지원하지 않으므로, 해당 웹 브라우저까지 지원하려면 입력한 키를 숫자로 나타내는keyCode
속성을 사용해야 한다.이벤트 발생 객체
코드의 규모가 커지면 이벤트 리스너를 외부로 분리하는 경우가 많아지는데, 이때 이벤트 리스너 내부에서 문서 객체 변수에 접근할 수 없는 경우가 있다. 이땐
event.currentTarget
속성을 사용하거나,this
키워드를 사용한다. 전엔this
키워드를 사용하는 방식이 많이 쓰였지만, 화살표 함수 등장 이후 두 가지 방식 모두 많이 쓰인다.event.currentTarget
const listener = (event) => { const length = event.currentTarget.value.length; h1.textContent = `글자 수: ${length}`; } document.addEventListener("DOMContentLoaded", () => { const textarea = document.querySelector("textarea"); const h1 = document.querySelector("h1"); textarea.addEventListener("keyup", listner); })
만일
event.currentTarget
속성을 사용하지 않았다면textarea
변수에 지정할 수 없어 오류가 났을 것이다.this
const listener = (event) => { const length = this.value.length; h1.textContent = `글자 수: ${length}`; } document.addEventListener("DOMContentLoaded", () => { const textarea = document.querySelector("textarea"); const h1 = document.querySelector("h1"); textarea.addEventListener("keyup", listner); })
글자 입력 양식 이벤트
사용자로부터 입력을 받을 때 사용하는 요소를 입력 양식이라고 부른다. HTML의
input
,textarea
,button
,select
태그 등이 모두 입력 양식이다.inch 단위를 cm로 바꾸는 프로그램:
document.addEventListener("DOMContentLoaded", () => { const input = document.querySelector("input"); const button = document.querySelector("button"); const p = document.querySelector("p"); button.addEventListener("click", () => { const inch = Number(input.value); if(isNaN(inch)) { p.textContent = `숫자를 입력해주세요`; return; } const cm = inch * 2.54; p.textarea = `${cm}cm`; }) })
버튼을 클릭할 때마다 입력받은 값을
isNaN()
메소드를 통해 숫자인지 검사하고, 숫자임이 확인되면 2.54를 곱해 출력한다.숫자가 아닌 경우
return
키워드를 리턴해 이후의 코드는 실행되지 않는다. 조기 리턴이라는 이름의 패턴으로, 자주 사용되는 패턴이다.const input = document.querySelector("input") const value = input.value; const isEmail = (value) => { return (value.indexOf("@") >= 1) // @를 갖고 있고 && (value.split("@")[1].indexOf(".") > 1) // 골뱅이 뒤에 점이 있다면 true 리턴 } isEmail(value);
해당 방식으로 입력받은 값이 이메일의 형식인지 아닌지 알 수 있다.
indexOf("@") >= 1
를 통해 @을 갖고 있는지,indexOf(".") > 1
를 통해 @ 뒤에 점이 있는지를 따져true
혹은false
를 리턴한다.이 함수는 간단한 형태로,
garudanish@k.
를 입력해도 이메일 형식으로 인식한다. 일반적으로 이런 유효성 검사를 할 땐 정규표현식을 사용하면 더 쉽고 확실하게 구현할 수 있다.드롭다운 목록 활용하기
드롭다운 목록은 기본적으로
select
태그로 구현한다.<select> <option>떡볶이</option> <option>순대</option> <option>오뎅</option> <option>튀김</option> </select>
드롭다운 목록에서 항목을 선택하면
select
태그의options.selectedIndex
속성이 선택한 항목의 인덱스로 바뀐다. 이를 활용하면 드롭다운 선택 항목에 따라 출력을 달리하는 코드를 짤 수 있다.const select = document.querySelector("select"); select.addEventListener("change", (event) => { const options = event.currentTarget.options; const index = event.currentTarget.options.selectedIndex; p.innerText = `선택: ${options[index].textContent}` })
select
태그에multiple
속성을 부여하면 ctrl이나 shift 키로 여러 항목을 선택할 수 있다. 이를 multiple select 태그라고 한다.const select = document.querySelector("select"); select.addEventListener("change", (event) => { const options = event.currentTarget.options; const list = []; for (const option of options) { if (option.selected) { list.push(option.textContent); } } p.textContent = `선택: ${list.join(",")}`; })
options
속성에는forEach()
메소드가 없으므로 반복문을 돌려 선택되었는지 여부를 확인한다. 선택되었다면 빈 배열에 추가하고 반복문이 완료되면 출력한다.체크 박스 활용하기
HTML에서
input:checkbox
로 생성한 체크 박스는checked
속성을 가지므로 이를 활용한다.라디오 버튼 활용하기
라디오 버튼은
input:radio
로 생성한다.<input type="radio" name="pet" value="강아지"> <span>강아지</span> <input type="radio" name="pet" value="고양이"> <span>고양이</span> <input type="radio" name="pet" value="햄스터"> <span>햄스터</span> <input type="radio" name="pet" value="기타"> <span>기타</span>
이때 항목에
name
속성을 입력하지 않으면 다중 선택이 가능하며, 선택 후 선택을 취소할 수 없으므로name
속성을 반드시 사용하여야 한다.라디오 버튼은 체크박스와 마찬가지로
checked
속성을 가지므로 이를 활용하면 된다.const radios = document.querySelectorAll("[name=pet]") radios.forEach((radio) => { radio.addEventListener("change", (event) => { const current = event.currentTarget if (current.checked) { p.textContent = `좋아하는 애완동물은 ${current.value}군요!` } }) })
기본 이벤트 막기
우클릭 시 컨텍스트 메뉴가 나타나는 것처럼 웹 브라우저가 기본적으로 처리해주는 이벤트를 기본 이벤트라고 부른다. 기본 이벤트에는 그 외에도 링크 클릭 시 이동, 제출 버튼 클릭 시 이동 등이 있다. 이런 기본 이벤트를 제거할 때는
event.preventDefault()
메소드를 사용한다.이미지 우클릭 시 컨텍스트 메뉴가 뜨는 기본 이벤트를 방지하는 코드:
const img = document.querySelector("img"); img.addEventListener("contextmenu", (event) => { event.preventDefault(); })
'자바스크립트 > 혼자 공부하는 자바스크립트' 카테고리의 다른 글
혼자 공부하는 자바스크립트 9장 - 클래스 (0) 2021.08.16 혼자 공부하는 자바스크립트 8장 - 예외 처리 (0) 2021.08.08 혼자 공부하는 자바스크립트 6장 - 객체 (0) 2021.08.01 혼자 공부하는 자바스크립트 5장 - 함수 (0) 2021.07.31 혼자 공부하는 자바스크립트 4장 - 배열, 반복문 (0) 2021.07.25