문서 객체 모델을 통해 JavaScript는 HTML과 연관되어 영향을 줄 수 있다.
JavaScript의 기본 문법인 조건문, 반복문, 함수 등을 통해서 다양한 이벤트를 활용할 수 있다.
addEventListenenr()
라는 메소드를 활용할 수 있고, 현재 해당 방식이 표준으로 적용되고 있기 때문에 "표준 이벤트 모델" 이라고도 부른다. document.body.addEventListener('keyup', () => {}
// HTML 바디 부분에서 'keyup'이라는 이벤트를 감지한다.
// () 인자를 두개 넣는데, 그 중 첫번째 인자가 감지하고자 하는 이벤트 (keyup)이다.
// { } 안엔 감지했을 때 실행되어야 할 함수의 내용을 담는다.
onXXX
으로 시작하는 속성에 함수를 할당해서 이벤트를 연결한다. document.body.onkeyup = () => {}
// HTML 바디 부분에서 'keyup'이라는 이벤트를 감지한다.
// () 안에는 전달하고자 하는 인자를, { } 안엔 감지했을 때 실행되어야 할 함수의 내용을 담는다.
onXXX
으로 시작하는 속성 사용하지만, HTML 태그에 직접 추가해서 이벤트를 넣는다.<script> // 스크립트 태그 내부에 listener라는 변수 지정
const listener = (event) => { // 변수에 화살표 함수를 이용해서 (event)라는 인자를 주고,
console.log("keyup") // 이벤트 발생 시 콘솔에 "keyup"이라는 글자가 찍힌다.
};
</script>
<input onkeyup="listener(event)"></input>
// script 태그 내부에 정의된 함수(listener)는 html 태그인 input 태그에 "onkeyup" 이 발생될 때 마다 적용된다.
키보드 이벤트는 크게 3가지가 있다.
이벤트 | 설명 |
---|---|
keydown | 키가 눌릴 때 실행. 키보드를 꾹 누르고 있을 때도, 입력될 때도 실행된다. |
keypress | 키가 입력되었을 때 실행. 기본적으로 keydown과 비슷하다. 하지만 아시아권 문자 사용시 적용할 수 없다. |
keyup | 키보드에서 키가 떨어질 때 (누르고 손을 뗄 때) 이벤트가 실행된다. 가장 일반적으로 사용된다. |
예시: 이벤트가 발생한 횟수 카운트 하기
<body>
<script>
let counter = 0 // 3. 이벤트 발생 횟수를 세기 위해 "counter"라는 변수를 선언하고 0을 할당했다.
const listener = (event) => {
// 2. 이벤트 발생 시 실행될 함수를 상수 "listener"에 할당하고 이벤트 객체를 첫번째 매개변수로 줬다.
counter++
// 4. 이벤트 발생 시, "counter"에 할당된 값은 1씩 증가한다.
console.log(`keypress: ${counter}`)
// 5. 이벤트 발생 시, 콘솔에 "keypress: {카운터의 값}"이 출력된다.
};
</script>
<input onkeypress="listener(event)"></input> // 1. 인풋필드에 onkeypress 이벤트를 연결시켰다.
</body>
keydown
을 사용할 경우, 키보드가 눌릴 때마다 콘솔에 1이 증가한다.keypress
와 다르게, 아시아권 문자도 인식한다.keyup
을 사용할 경우, 키보드에서 손이 떨어질 때 콘솔에 1이 증가한다.이벤트 속성 이름 | 설명 |
---|---|
code | code 속성은 입력한 키를 나타내는 문자열이 들어있다. 의미한다. |
keyCode | 입력한 키를 나타내는 숫자 |
altKey | alt 키를 눌렀는지 boolean 형식으로 확인 |
ctrlKey | ctrl 키를 눌렀는지 boolean 형식으로 확인 |
shiftKey | shift 키를 눌렀는지 boolean 형식으로 확인 |
<script>
document.addEventListener("DOMContentLoaded", () => {
// DOM 구조 파악이 끝난 이후에 이벤트가 실행된다
const h1 = document.querySelector("h1");
// h1 이라는 상수에 쿼리셀렉터를 이용해서 html에 있는 <h1>를 담는다
const print = (event) => {
// print 라는 상수에 이벤트가 감지되었을 때 실행될 함수를 담는다. (매개변수로 event 설정)
let output = "";
// 이벤트 이후 결과값을 output이라는 변수에 담는다.
output += `alt: ${event.altKey}<br>`;
// output에 alt 키가 눌렸을 때 "alt: true/false" 가 출력되게 설정하고 줄바꿈 추가
output += `ctrl: ${event.ctrlKey}<br>`;
// output에 ctrl 키가 눌렸을 때 "ctrl: true/false" 가 출력되게 설정하고 줄바꿈 추가
output += `shiftKey: ${event.shiftKey}<br>`;
// output에 shift 키가 눌렸을 때 "shift: true/false" 가 출력되게 설정하고 줄바꿈 추가
output += `code: ${
typeof event.code !== "undefined" ? event.code : event.keyCode
}<br>`;
// 만약 event.code의 결과값이 undefined가 아닐 경우 event.code를 출력하고, 아니면 keyCode를 출력한다.
// event.code = event.altKey와 같은 키코드를 감지하는 이벤트를 의미한다.
// event.code가 감지되지 않으면 특수키가 아닌 V, B, 3 등과 같은 일반 키기 때문에, 일반키가 출력된다.
h1.innerHTML = output;
// HTML 태그 속성을 그대로 사용하면서 아웃풋을 출력한다.
// 예시의 경우 전부 h1로 결과값이 출력된다.
};
document.addEventListener("keydown", print);
// 키다운 이벤트가 일어날 때 프린트 함수가 실행된다.
document.addEventListener("keyup", print);
});
</script>
<body>
<h1></h1>
</body>
<script>
document.addEventListener("DOMContentLoaded", () => {
// DOM 구조 파악이 끝난 이후에 이벤트가 실행된다
const star = document.querySelector("h1");
// star라는 상수에 쿼리셀렉터를 이용해서 html에 있는 <h1>를 담는다
star.style.position = "absolute";
// star의 위치값을 absolute로 준다.
// postion이 상위 요소 내부에 속박되지 않고, 독립된 배치 문맥을 가지게 된다. (viewport 내에서 움직임이 자유롭다)
let [x, y] = [0, 0];
// x, y가 들어있는 배열에 다른 배열을 이용해서 각각 0을 할당한다.
const block = 20;
// block 이라는 상수의 값을 20으로 준다.
const print = () => {
star.style.left = `${x * block}px`;
// star의 위치값을 변경할 수 있도록 x*block px를 값으로 할당한다.
star.style.top = `${y * block}px`;
// star의 위치값을 변경할 수 있도록 y*block px를 값으로 할당한다.
};
const [left, up, right, down] = [37, 38, 39, 40];
// 방향키의 키코드는 각 37,38,39,40 이기 때문에, 배열에 할당한다.
document.body.addEventListener("keydown", (event) => {
// HTML의 body 내부에서 'keydown' 이벤트를 감지할 때 실행된다.
switch (event.keyCode) {
// 만약 키코드의 이벤트가:
case left:
// left키를 눌렀을 때, x의 값은 -1이 된다
x -= 1;
// 빼기 할당이 되어서 left 키를 많이 누를 수록 x의 좌표값이 계속해서 줄어든다.
break;
case up:
// up키를 눌렀을 때, y의 값은 -1이 된다
y -= 1;
break;
case right:
// right키를 눌렀을 때, x의 값은 +1이 된다
x += 1;
break;
case down:
// down키를 눌렀을 때, y의 값은 +1이 된다
y += 1;
break;
}
print();
// 조건문이 진행될때마다 위에 만들었던 print 함수가 실행된다.
// print 함수에서 x,y의 값은 block으로 인해 *20px이 되었기 때문에, star의 position을 변경 시킨다.
// 그래서 키보드 방향에 따라 20px씩 상하좌우로 별이 움직인다.
});
});
</script>
<body>
<h1>⭐️</h1>
</body>
<script>
const listener = (event) => {
// 4. listener라는 상수에 이벤트가 감지될 경우 생성되는 함수를 할당한다.
const length = textarea.value.length
// 5. 함수 내부에 length라는 상수에 textarea에 입력된 값의 길이(숫자)를 담는다
h1.textcontent = `글자 수: ${length}`
// 6. textarea에 입력된 글자 수가 html에 있는 h1의 내용으로 표시된다.
}
document.addEventListener('DOMContentLoaded', () =>{
// 1. html의 DOM 파악이 완료되면 이벤트가 실행된다.
const textarea = document.querySelector('textarea')
// 2. textarea 라는 변수에 html에 있는 textarea를 담는다
const h1 = document.querySelector('h1')
// 3. h1이라는 상수에 html에 있는 h1을 담는다
textarea.addEventListener('keyup', listener)
// 7. textarea에 keyup 이벤트가 일어날 경우, listener라는 함수가 실행되도록 한다.
})
</script>
<body>
<h1></h1>
<textarea></textarea>
</body>
<script>
const listener = (event) => {
// 3. listener라는 상수에 이벤트가 감지될 경우 생성되는 함수를 할당한다.
const length = event.currentTarget.value.length;
// 4. 함수 내부에 length라는 상수에 textarea에 입력된 값의 길이(숫자)를 담는다
const h1 = document.querySelector("h1");
// 5. h1이라는 상수에 html에 있는 h1을 담는다
// event.currentTarget의 경우, 하나의 이벤트 핸들러에만 붙일 수 있다.
// 때문에 참조 에러를 피하기 위해 h1은 여기서 선언해야 코드가 에러 없이 실행된다.
h1.textContent = `글자 수: ${length}`;
// 6. textarea에 입력된 글자 수가 html에 있는 h1의 내용으로 표시된다.
};
document.addEventListener("DOMContentLoaded", () => {
// 1. html의 DOM 파악이 완료되면 이벤트가 실행된다.
const textarea = document.querySelector("textarea");
// 2. textarea 라는 변수에 html에 있는 textarea를 담는다
textarea.addEventListener("keyup", listener);
// 7. textarea에 keyup 이벤트가 일어날 경우, listener라는 함수가 실행되도록 한다.
});
</script>
<body>
<h1></h1>
<textarea></textarea>
</body>
event.currentTarget
을 사용함으로 자동적으로 이벤트가 발생하는 객체가 참조되었다.event.currentTarget
외 외부에서 선언된 변수를 참조하기 위해 this
라는 키워드를 사용한다. this
키워드의 경우, 화살표 함수가 아닌 선언적 함수 function() {}
를 사용할 때 적용된다.<script>
const listener = function (event) { // 화살표 함수 대신 선언적 함수를 사용했다
const length = this.value.length; // 참조할 수 없는 변수가 들어간 부분은 this를 사용했다.
const h1 = document.querySelector("h1");
h1.textContent = `글자 수: ${length}`;
};
document.addEventListener("DOMContentLoaded", () => {
const textarea = document.querySelector("textarea");
textarea.addEventListener("keyup", listener);
});
</script>
<body>
<h1></h1>
<textarea></textarea>
</body>
event.currentTarget
과 this
키워드는 프레임워크마다 선호하는 방식이 다르기 때문에 공식 문서 등을 참조해서 어떤 코드가 더 일반적으로 쓰이는지 알아봐야 한다.<script>
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)
const cm = inch*2.54
if(isNaN(inch)){
// 만약 inch에 입력된 값이 숫자가 아닐 경우
p.textContent = `숫자를 입력해주세요`
// p태그 부분에 경고 메세지가 생성된다
return
// if문을 사용하는 경우, 조건이 false가 나올 때 else를 사용하지 않을 수 있다.
// else가 아닌 return을 사용해서 바로 false 일때의 결과값을 출력하는 경우를 "조기 리턴"이라고 한다.
}
p.textContent = `${cm}cm`
})
})
</script>
<body>
<input>inch</input>
<button>계산하기</button>
<p></p>
</body>
<script>
document.addEventListener("DOMContentLoaded", () => {
const select = document.querySelector("select");
const p = document.querySelector("p");
select.addEventListener("change", (event) => {
// 3. 이벤트가 일어날 위치인 select에 addEventListener를 붙이고, 'change' 이벤트를 첫 번째 매개변수로 둔다
const options = event.currentTarget.options;
// 4. 일어날 이벤트의 대상자인 options에 event.currentTarget을 지정한다.
// 5. 드롭다운 설정 시, options 하나만 표시된다.
const index = event.currentTarget.options.selectedIndex;
// 6. 'index'라는 상수에 이벤트 대상자인 options에 추가로 'selectedIndex'라는 속성을 부여한다.
// 7. 드롭다운으로 선택한 옵션의 값을 의미한다.
p.textContent = `선택: ${options[index].textContent}`;
// 8. 사용자가 선택한 옵션의 값이 추출되도록 'options[index]'를 textcontent의 표시된다.
// 9. 떡볶이 선택 시 "떡볶이"라는 글이 p태그 쪽에 표시된다.
});
});
</script>
<body>
<select>
// 1. select 아래에 options를 둔다.
<option>떡볶이</option>
// 2. 원하는 만큼 옵션의 수를 지정하고 각 옵션에 선택지를 둔다.
<option>튀김</option>
<option>순대</option>
<option>어묵</option>
</select>
<p>선택: 떡볶이</p>
</body>
ctrl
혹은 shift
키를 누른 상태로 선택한다.<script>
document.addEventListener("DOMContentLoaded", () => {
const select = document.querySelector("select");
const p = document.querySelector("p");
select.addEventListener("change", (event) => {
const options = event.currentTarget.options;
// 2. 이벤트 대상자인 options에 event.currentTarget을 붙인다.
const list = [];
// 3. 다중 선택의 경우 선택 항목이 여러개이기 때문에, 선택된 항목을 담을 빈 배열을 준비한다.
for (const option of options) {
// 4. select 내부에 있는 모든 options를 돌아야 한다.
// 5. options 속성에는 forEach() 메소드가 없기 때문에, 반복문을 사용한다.
// 6. p 태그 부분에 인덱스 번호가 아니라 option의 값이 필요해서 for of를 사용한다.
if (option.selected) {
// 7. 만약에 선택된 옵션이 있다면
list.push(option.textContent);
// 8. 빈 배열에 선택된 option의 text만 추가한다.
}
}
p.textContent = `선택: ${list.join()}`;
// 9. p 태그에 내용에 추출된 list에 있는 요소들을 합해서 표시한다.
// 10. 다중 선택 시 떡볶이, 튀김, 순대, 어묵으로 출력
});
});
</script>
<body>
<select multiple> // 1. select에 multiple 속성 추가
<option>떡볶이</option>
<option>튀김</option>
<option>순대</option>
<option>어묵</option>
</select>
<p>선택: 떡볶이</p>
</body>
<script>
document.addEventListener("DOMContentLoaded", () => {
let [timer, timerID] = [0,0]
// 2. 구조분해 할당을 이용해서 변수 timer와 timerID에 각각 0 할당
const h1 = document.querySelector('h1')
const checkbox = document.querySelector('input')
checkbox.addEventListener('change', (event) => {
// 3. checkbox에서 change 이벤트가 일어날 경우 함수 실행 선언
if (event.currentTarget.checked){
// 4. 만약 이벤트 대상자 (체크박스)의 속성이 checked라면,
timerID = setInterval (()=>{
// 5. timerID에 할당한 함수 setInterval이 실행된다.
timer += 1
// 6. setInterval() 실행 시, timer의 값은 더하기 할당으로 1씩 증가하고
h1.textContent = `${timer}초`
// 7. html에 있는 h1 태그 내용에 초가 표시된다.
}, 1000)
// 5-1. setInterval 함수는 1초 (1000ms)마다 실행된다.
} else {
// 8. 만약에 이벤트 대상자 (체크박스)의 속성이 checked가 아니라면
clearInterval(timerID)
// 9. timerID를 매개변수로 두고 있는 clearInterval 함수를 실행한다 = setInterval 함수를 초기화한다.
}
})
});
</script>
<body>
<input type = "checkbox"></input>
// 1. 체크박스를 만들기 위해 input에 checkbox 속성 부여
<span>타이머 활성화</span>
<h1></h1>
</body>
<script>
document.addEventListener("DOMContentLoaded", () => {
const output = document.querySelector("#output");
// 5. 상수 output에 id값이 output인 html의 요소를 할당
const radios = document.querySelectorAll("[name=pet]");
// 6. 상수 radios에 name이 pet인 요소들을 일괄적으로 할당
radios.forEach((radio) => {
// 7. 모든 라디오 버튼 확인을 위해 forEach() 메소드 사용
radio.addEventListener("change", (event) => {
// 8. 라디오 버튼 하나에 change 이벤트 추가
const current = event.currentTarget;
// 9. current라는 상수에 지금 이벤트가 일어난 특정 대상을 할당
if (current.checked)
// 10. 만약 current가 선택된 상태면,
output.textContent = `좋아하는 동물은 ${current.value}입니다.`;
// 11. output에 해당 내용을 출력한다.
}
});
});
});
</script>
<body>
<h3>좋아하는 동물을 선택해주세요</h3>
// 1. input 타입에 radio를 설정하고 name과 value 설정
// 2. name으로 모든 라디오 버튼들을 묶어두지 않으면 하나씩 선택할 수 없음 (선택 해제 불가능)
// 3. 라디오 버튼 클릭 시 받아올 값은 value로 설정
<input type="radio" name="pet" value="강아지" />
<label for="강아지">강아지</label>
// 4. label의 경우, 라디오 버튼과 묶고싶다면 for에 라디오 버튼의 value를 할당
<input type="radio" name="pet" value="고양이" />
<label for="고양이">고양이</label>
<input type="radio" name="pet" value="햄스터" />
<label for="햄스터">햄스터</label>
<input type="radio" name="pet" value="기타" />
<label for="기타">기타</label>
<h3 id="output"></h3>
</body>
preventDefault()
메소드를 사용한다.<script>
document.addEventListener("DOMContentLoaded", () => {
const img = document.querySelector("img");
img.addEventListener("contextmenu", (event) => {
// 1. 이벤트가 발생할 대상자인 img에 addEventListener를 붙이고, 'contextmenu'라는 이벤트를 감지하게 한다.
event.preventDefault();
// 2. 해당 이벤트가 감지되었을 때, event.preventDefault() 메소드를 호출시켜 contextmenu를 비활성화한다.
});
});
</script>
<body>
<img
src="https://www.mundoperros.es/wp-content/uploads/2018/02/teckel-saltando.jpg"
alt="블랙탄 닥스훈트가 들판에서 뛰다가 공중에 있는 순간을 찍은 사진"
/>
</body>
querySelectorAll()
를 사용해서 모든 이미지 태그를 선택하고, imgs.forEach((img) =>{ })
복수형 변수에 forEach()를 돌리고 확인해야할 요소에 img를 넣는다.<script>
document.addEventListener("DOMContentLoaded", () => {
let status = false;
// 1. checked 속성은 boolean 자료형이기 때문에, 체크 여부를 확인하기 위해 false라는 값을 갖고 있는 변수를 지정한다.
const checkbox = document.querySelector("input");
checkbox.addEventListener("change", (event) => {
// 2. 이벤트 대상자를 체크박스로 설정하고, 변경이 있을 경우 이벤트를 감지하도록 한다.
status = event.currentTarget.checked;
// 3. 이때 이벤트 대상자의 checked 여부에 status를 재할당한다.
});
const link = document.querySelector("a");
link.addEventListener("click", (event) => {
// 4. 또 다른 이벤트 대상자인 링크에 클릭 이벤트가 생기면 감지하도록 한다.
if (!status) {
// 5. 클릭 이벤트 발생 시 만약 checkbox의 checked 속성이 false라면
event.preventDefault();
// 6. 브라우저 기본 이벤트 (링크 이동)을 막는다.
}
});
});
</script>
<body>
<input type="checkbox" />
<span>링크 활성화</span>
<br />
<a href="https://velog.io/@hailey199535">내 벨로그</a>
</body>
문서 객체를 조작할 때 웹 브라우저가 추가로 제공하는 기능 (API)을 사용하게 된다.
실제로 브라우저는 웹캠 활성화, 알림 설정, 위치 추적 등 다양한 기능을 제공한다.
이때 사용하는 것이 localStorage
객체다.
localStorage.key
혹은 localStorage[key]
형태로 사용할 수 있다. <script>
document.addEventListener("DOMContentLoaded", () => {
const p = document.querySelector("p");
const input = document.querySelector("input");
const button = document.querySelector("button");
const savedValue = localStorage.getItem("input");
// 1. 인풋에 입력된 값을 추출해서 상수 savedValue에 담는다
if (savedValue) {
// 2. 만약 savedValue가 true (스토리지에 무언가가 저장됐다면) 라면
input.value = savedValue;
// 3. input의 값을 savedValue로 지정 (저장되어 있는 값을 보여준다)
p.textContent = `이전 실행 때의 마지막 값: ${savedValue}`;
}
input.addEventListener("keyup", (event) => {
// 4. 인풋에 keyup 이벤트가 생기면 이벤트를 감지한다.
const value = event.currentTarget.value;
// 5. value라는 상수에 이벤트 대상자의 값을 담는다
localStorage.setItem("input", value);
// 6. 인풋에 입력된 값을 키-값 페어로 저장한다.
// 여기서 저장된 내용이 위에 조건문에서 getItem을 통해 불러진다.
});
button.addEventListener("click", (event) => {
// 7. 버튼 클릭 시 localStorage에 담겨있던 정보를 삭제시키거
localStorage.clear();
input.value = "";
// 8. 인풋에 써있던 값을 빈칸으로 초기화 한다.
});
});
</script>
<body>
<p></p>
<button>지우기</button>
<input type="text" />
</body>
JSON.stringfy()
를 이용해서 JSON 형식으로 데이터를 전환한 후에 로컬스토리지에 담고,JSON.parse()
를 사용해서 원래의 데이터 타입으로 복구한다.출처: 혼자 공부하는 자바스크립트 (한빛미디어)