JavaScript(14) - basic
JavaScript 관련 포스팅
- JavaScript(1) - async vs. defer
- JavaScript(2) - variable
- JavaScript(3) - operator
- JavaScript(4) - function
- JavaScript(5) - class vs. object
- JavaScript(6) - object
- JavaScript(7) - array
- JavaScript(8) - JSON
- JavaScript(9) - callback
- JavaScript(10) - promise
- JavaScript(11) - Regular expressions
- JavaScript(12) - Prototype과 Class 피하기
- JavaScript(13) - localStorage
※ 이 글은 윤인성님의 Youtube 강의 내용을 참고 작성한 글입니다.
예시는 변경해 적용한 부분이 많으니 참고하시기 바랍니다.
원본 출처는 문서 하단을 확인하시기 바랍니다.
1. 요소 값 추출 및 입력
1-1. 요소 값 추출
-
textContent
,innerHTML
<body> <h1 id="first">h1 태그에 입력된 기존 문자열입니다.</h1> <script src="main.js"></script> </body>
document.addEventListener('DOMContentLoaded', () => { const header1 = document.querySelector('#first'); // 태그 확인 console.log(header1); // 값 추출 console.log(header1.textContent); console.log(header1.innerHTML); });
-
querySelector('selector')
사용 방법selector
: CSS selector를 string으로 넣음<h1 id="header">제목</h1>
document.querySelector('h1') document.querySelector('#header') document.querySelector('h1#header')
<span class="choose">선택</span>
document.querySelector('span') document.querySelector('.choose') document.querySelector('span.choose')
<input id="name-input" type="text" name="name">
document.querySelector('input') document.querySelector('#name-input') document.querySelector('[type=text]') document.querySelector('input[type=text]') document.querySelector('input[type=text][name=name]')
1-2. 요소에 원하는 값 입력
textContent
- tag를 일반 문자열로 인식
- 많이 사용
innerHTML
- tag를 인식
- 보안상 문제가 될 수 있어서 많이 사용하지 않음
<body>
<h1 id="first">h1 태그에 입력된 기존 문자열입니다.</h1>
<h2 id="second">h2 태그에 입력된 기존 문자열입니다.</h2>
<script src="main.js"></script>
</body>
document.addEventListener('DOMContentLoaded', () => {
const header1 = document.querySelector('#first');
const header2 = document.querySelector('#second');
// 값 입력
header1.textContent = 'apple pie<br>🥧';
header2.innerHTML = 'apple pie<br>🥧'
// 값 추출
console.log(header1.textContent);
console.log(header2.textContent);
});
2. 속성 조작하기
2-1. 표준에 있는 속성 조작하기
- 해당 속성을 직접 지정
<body> <img src="" alt=""> <script src="main.js"></script> </body>
document.addEventListener('DOMContentLoaded', () => { const img = document.querySelector('img'); // 값 입력 img.src = 'http://placekitten.com/200/200'; // 값 추출 console.log(img.src); });
2-2. 표준에 없는 속성(사용자 정의 속성) 조작하기
setAttribute('속성 이름', '값')
-
getAttribute('속성 이름')
<body> <img src="" alt=""> </body>
document.addEventListener('DOMContentLoaded', () => { const img = document.querySelector('img'); // 값 입력 img.setAttribute('src', 'http://placekitten.com/152/152'); // 값 추출 console.log(img.getAttribute('src')); });
3. 스타일 조작하기
style.backgroundColor
- 일반적으로 많이 사용
style['background-color']
- CSS의 속성 명으로 쓰고 싶을 때 사용
<body> <!-- div tag 10개 --> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <script src="main.js"></script> </body>
document.addEventListener('DOMContentLoaded', () => { const divs = document.querySelectorAll('div'); // div 여러 개 이므로 divs로 표현 divs.forEach((div, key) => { // key는 index값 // 값 입력 div.style.backgroundColor = `rgb(${key*25.5}, ${key*25.5}, ${key*25.5})`; div.style.height = '30px'; // 반드시 문자열로 넣고 단위 생략하면 안 됨! // 값 추출 console.log(div.style.backgroundColor) }) });
4. 문서 객체 생성하기
document.createElement('태그 이름')
- element 생성
appendChild()
- 화면에 element 붙이기
<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 만들기 // createElement() const header = document.createElement('h1'); // element의 속성 지정 header.textContent = 'createElement로 만든 tag'; header.style.color = 'salmon'; // element 붙이기 // appendChild() const body = document.querySelector('body'); body.appendChild(header); });
5. 문서 객체 제거하기
removeChild()
- 해당 요소를 직접 제거
parentNode.removeChild()
- 부모 요소를 이용해 제거하는 방법
- 많이 사용함
<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 만들기 // createElement() const header1 = document.createElement('h1'); const header2 = document.createElement('h2'); header1.textContent = 'createElement로 만든 tag1입니다!'; header2.textContent = 'createElement로 만든 tag2입니다!'; header1.style.color = 'green'; header2.style.color = 'red'; // element 붙이기 // appendChild() const body = document.querySelector('body'); body.appendChild(header1); body.appendChild(header2); // element 제거하기 // 편의상 2초 뒤에 element가 제거되도록 setTimeout() 사용 setTimeout(() => { // body.removeChild(header1); header1.parentNode.removeChild(header1); // 많이 사용함 }, 2000); });
body.removeChild()
vs.header.parentNode.removeChild()
body
와header.parentNode
는 같은 의미임-
header.parentNode
의 경우, 부모요소(body
) 언급없이 제거할 요소만 지칭하므로 사용하기 편리해 많이 씀
6. 문서 객체 이동하기
-
setTimeout(function, delay)
<!-- index.html --> <body> <div class="first"> <h1>첫 번째 div tag 내부</h1> </div> <hr> <div class="second"> <h1>두 번째 div tag 내부</h1> </div> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 만들기 const header = document.createElement('h2'); header.textContent = '추가된 h2 tag입니다'; const first = document.querySelector('.first'); const second = document.querySelector('.second'); // element 붙이기 first.appendChild(header); const toFirst = () => { first.appendChild(header); setTimeout(toSecond, 1000); // 1초 뒤에 toSecond() 실행 } const toSecond = () => { second.appendChild(header); setTimeout(toFirst, 1000); // 1초 뒤에 toFirst() 실행 } toFirst(); });
-
1초마다 두 화면이 번갈아가며 나타남
-
또는 다음과 같은 방법으로 실행할 수도 있음
array
에 element를 넣음setInterval()
<!-- index.html --> <body> <div class="first"> <h1>첫 번째 div tag 내부</h1> </div> <hr> <div class="second"> <h1>두 번째 div tag 내부</h1> </div> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 만들기 const header = document.createElement('h2'); header.textContent = '추가된 h2 tag입니다'; const array = [ document.querySelector('.first'), document.querySelector('.second') ]; let counter = 0; const move = () => { array[counter % 2].appendChild(header); counter ++; }; setInterval(move, 1000); move(); // 1초 뒤부터 h2 tag가 나타나므로 처음 한 번은 실행해 줌 });
7. event 연결
addEventLister('이벤트_이름', 이벤트 리스너(이벤트 핸들러))
- 이벤트가 실행될 때 호출되는
callBack fn
을이벤트 리스너
또는이벤트 핸들러
라고 부름 - 문서 객체에서
on
으로 시작하는 속성들을 이벤트와 관련되므로 적절한 항목을 골라 사용자에 반응하는 프로그램을 만들 수 있음 e.g.)onmousedown
,onmouseenter
,onmouseleave
등
<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 생성 const header = document.createElement('h1'); header.textContent = 'Click = 0' header.style.color = 'salmon'; header.style.border = '1px solid salmon'; header.style.userSelect = 'none'; // 연속 click시 text가 선택되지 않도록 설정 // element 붙이기 // body 태그 내부에 붙이기 document.body.appendChild(header); let count = 0; // 변수 설정 // h1 태그를 click할 때마다 이벤트를 발생시킴 header.addEventListener('click', () => { count ++; header.textContent = `Click = ${count}`; }); });
- h1 태그를 click할 때마다 숫자가 하나씩 증가함
- 이벤트가 실행될 때 호출되는
8. 이벤트 제거
removeEventLister()
click
연결 시 사용했던 eventLister를 별도의 변수(여기서는listener
)에 담아 주어야 함
<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js let count = 0; const listener = () => { header.textContent = `클릭 횟수 = ${++count}`; } // element 생성(h1) const header = document.createElement('h1'); header.style.border = '1px solid black'; header.style.userSelect = 'none'; // click시 text가 선택되지 않도록 설정 header.textContent = '클릭 횟수 = 0'; // element 생성(p) const p = document.createElement('p'); p.textContent = '이벤트 연결 상태: 해제'; p.style.userSelect = 'none'; // click시 text가 선택되지 않도록 설정 // element 생성(button) const connectButton = document.createElement('button'); connectButton.textContent = '이벤트 연결'; connectButton.addEventListener('click', () => { header.addEventListener('click', listener) p.textContent = '이벤트 연결 상태: 연결'; }); // element 생성(button) const disconnectButton = document.createElement('button'); disconnectButton.textContent = '이벤트 제거'; disconnectButton.addEventListener('click', () => { header.removeEventListener('click', listener) p.textContent = '이벤트 연결 상태: 해제'; }); // 화면에 element 추가(순서대로) document.body.appendChild(header); document.body.appendChild(connectButton); document.body.appendChild(disconnectButton); document.body.appendChild(p);
이벤트 연결
버튼을 클릭하면,- 이벤트 연결 상태가
ON
로 바뀌면서 - header 클릭시 클릭 횟수가 증가
이벤트 제거
버튼을 클릭하면,- 이벤트 연결 상태가
OFF
로 바뀌면서 - header 클릭시 클릭 횟수가 증가하지 않음
9. 키보드 이벤트
- event가 발생했을 때, 해당 event와 관련된 정보가
이벤트 객체
형태로 callback fn의 첫 번째 parameter로 가져옴document.addEventListener('이벤트', (이벤트 객체) => { });
- 일반적으로 이 parameter의 이름은
event
또는e
로 설정함e.code
: 입력한 키e.keyCode
: 입력한 키를 나타내는 숫자e.altKey
:Alt
키를 눌렀는지e.ctrlKey
:Ctrl
키 를 눌렀는지e.shiftKey
:Shift
키를 눌렀는지e.currentTarget
: event를 발생시킨 객체
- 일반적으로 이 parameter의 이름은
-
currentTarget
,this
를 사용한 코드 숙지하기<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 생성(h1) const header = document.createElement('h1'); header.textContent = '글자 수 = 0'; header.style.color = 'salmon'; header.style.border = '1px solid salmon'; // element 생성(textarea) const textarea = document.createElement('textarea'); textarea.placeholder = '글자를 입력하세요'; // 화면에 element 추가 document.body.appendChild(header); document.body.appendChild(textarea); // 첫 번째 방법 textarea.addEventListener('keyup', (e) => { h1.textContent = `글자 수: ${textarea.value.length}`; }); // 두 번째 방법 // currentTarget 사용 textarea.addEventListener('keyup', (e) => { h1.textContent = `글자 수: ${e.currentTarget.value.length}`; }); // 세 번째 방법 // function을 만들어 this를 사용 textarea.addEventListener('keyup', function () { h1.textContent = `글자 수: ${this.value.length}`; }); });
-
글을 입력하면 글자 수를 알려줌
-
console.log(e.currentTarget)
를 보면, 이벤트를 발생시킨 객체가 나옴 - 첫 번째 방법
keyup
keydown
인 상태에서는 입력한 글자 수를 알 수 없음
- 두 번째 방법
keypress
- 아시아 문자에서는 제대로 작동하지 않는 경우가 있음
- 세 번째 방법
this
사용eventHandler
내부에서this
가 이벤트 발생 객체를 의미함
-
10. 기본 이벤트 막기
preventDefault()
- 기본 이벤트를 막음
- a 태그
- 기본 이벤트: 클릭하면 지정된 주소로 이동
click
이벤트에preventDefault()
를 설정하면 지정 주소로 이동하지 않음
- 요소에서 우클릭
- 기본 이벤트: context menu가 나옴
contextmenu
이벤트에preventDefault()
를 설정하면 context menu가 나오지 않음- 블로그의 우클릭 방지기능
<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 생성(a 태그) const link = document.createElement('a'); link.textContent = 'Google'; link.href = 'https://www.google.com'; // element 추가 document.body.appendChild(link); // a 태그 click시 링크가 연결되는 것 막기 link.addEventListener('click', (event) => { event.preventDefault(); }); // a 태그 우click시 context menu가 나오는 것 막기 link.addEventListener('contextmenu', (event) => { event.preventDefault(); }); });
preventDefault()
적용 전preventDefault()
적용 후
11. 입력 양식(1) - Button
- 세 가지 형태가 존재
// 1. <button>글자</button> // 2. <input type="button" value="글자"> // 3. <form action=""> <input type="submit" value="글자"> </form>
- 첫 번째와 두 번째는
click 이벤트
활용시에 사용 - 세 번째는
submit 이벤트
활용시에 사용
- 첫 번째와 두 번째는
11-(1) click 이벤트 사용하기
event.currentTarget
: 이벤트를 발생시킨 객체<!-- index.html --> <body> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 선택(button) const firstButton = document.querySelector('button'); const secondButton = document.querySelector('input[type=button]'); // button 클릭시 event 지정 firstButton.addEventListener('click', (event) => { event.currentTarget.textContent += '😎'; }); secondButton.addEventListener('click', (event) => { event.currentTarget.value += '🌈'; }); });
- button을 클릭할 때마다 버튼의 내용이 바뀜
11-(2) click 이벤트 사용하기
- form 태그의 button을 클릭하면,
- 태그 안의 데이터를 서버로 넘김
⇒ 주소가 바뀜 - submit 이벤트는 form 태그를 선택해(
document.querySelector('form')
) 이벤트를 연결해야 함! - form 태그 내부에 있는 button은 submit 태그와 동일하게 동작하므로 주의!
-
form 태그 내부에
input[type=button]
button을 만들어야 submit 이벤트가 일어나지 않음<!-- index.html --> <body> <form action=""> 이메일 형식으로 입력하세요!<br> <!-- name 값을 반드시 입력해야 함 --> <input type="text" name="test" id=""> <input type="submit" value="글자"> </form> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 선택(form) const form = document.querySelector('form'); // (주의!) form 태그를 선택해 submit 이벤트를 관리함 form.addEventListener('submit', (event) => { const text = document.querySelector('input[type=text]'); // indexOf()로 '@'가 있는지 확인 if (text.value.indexOf('@') >= 0) { alert('정상 제출합니다!'); } else { alert('이메일 형식으로 입력해주세요!'); // 이메일 형식이 아닐경우 기본 submit 이벤트를 막음 event.preventDefault(); } }); });
@
가 포함되어있지 않으면 주소 변경이 일어나지 않음- 정상제출을 하면, 주소가 바뀜
12. 입력 양식(2) - 글자 입력
<input type="text">
- 한 줄의 글자 입력
<textarea></textarea>
- 여러 줄의 글자 입력
contenteditable="true"
-
해당 태그의 내용을 직접 수정가능하게 만들어줌
<p contenteditable="true">contenteditable!</p>
-
(참고) keydown, keypress, keyup, change 이벤트
- 키 이벤트와 입력 순서
keydown
→keypress
→ ★입력양식에 값이 들어감★→keyup
-
keydown
이나,keypress
이벤트를 주면,
입력 양식에 값이 들어가는 것이 시간상 더 이후이므로 코드 실행시 변환이 일어나지 않은 결과를 보여줌button.addEventListener('keydown', () => { p.textContent = `${Number(input.value) * 2.54}cm`; });
keydown
시점에 이벤트가 실행되므로 입력 양식에 값이 들어가기 전이라 p태그에 값이 없음
- 참고로
change
이벤트의 경우, 값 입력을 마쳤다는 선언(enter
키 입력)이 있어야 함
<예제> 입력받은 cm 단위를 inch로 변환하기예제>
<!-- index.html -->
<body>
<input type="text" name="inch" id="" placeholder="숫자"> inch <br>
<p id="result">숫자를 입력해주세요</p>
<script src="main.js"></script>
</body>
// main.js
document.addEventListener('DOMContentLoaded', () => {
// element 선택
const input = document.querySelector('input[name=inch]');
const p = document.querySelector('#result');
// 입력한 값을 숫자로 변경해 inch 단위로 변경
button.addEventListener('click', () => {
p.textContent = `${Number(input.value) * 2.54}cm`;
});
});
<textarea></textarea>
를 사용했을 때도 마찬가지로 value 속성으로 text를 추출하면 됨
13. 입력 양식(3) - 체크박스/라디오버튼
- 체크 박스
- true 또는 false 가 선택됨
- 라디오 버튼
- name 속성 지정 필수
- 같은 name 속성을 갖는 그룹으로 묶임
<예제> checkbox, radio button 선택시 해당 내용 출력하기예제>
forEach()
- 라디오 버튼이 여러 개 이므로 각각 돌면서
addEventListener()
를 실행
<!-- index.html --> <body> <!-- true 또는 false를 선택 --> <input type="checkbox" name="" id=""> <p id="checkValue"></p> <!-- 여러 대상 중 하나만 선택 --> <input type="radio" name="food" value="아이스크림">🍦 <input type="radio" name="food" value="치킨">🍗 <input type="radio" name="food" value="도넛">🍩 <p id="radioValue"></p> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 선택 const checkBox = document.querySelector("input[type=checkbox]"); // 라디오 버튼 모두 선택 const radios = document.querySelectorAll("input[type=radio][name=food]"); const checkValue = document.querySelector("p#checkValue"); const radioValue = document.querySelector("p#radioValue"); // 체크박스가 체크되면 이벤트 실행 checkBox.addEventListener("change", () => { if (checkBox.checked) { checkValue.textContent = "체크!"; } else { checkValue.textContent = "안 체크!"; } }); // 라디오버튼이 선택되면 이벤트 실행 // forEach문으로 각 radio버튼 돎 radios.forEach((radio) => { radio.addEventListener('change', (event) => { radioValue.textContent = event.currentTarget.value; }) }) });
- 라디오 버튼이 여러 개 이므로 각각 돌면서
<예제> checkbox 선택시 배경색 바뀌면서, 타이머 작동시키기예제>
구조 분해 할당
(destructuring assignment)- 객체나 배열을 변수로 분해할 수 있게 해주는 특별한 문법
- 참고 예시
setInterval()
과clearInterval()
<!-- index.html --> <body> <input type="checkbox" name="" id=""> 타이머 ON <p id="timer">0초</p> <script src="main.js"></script> </body>
// main.js document.addEventListener('DOMContentLoaded', () => { // element 선택 const checkBox = document.querySelector("input[type=checkbox]"); const timer = document.querySelector("p#timer"); let [seconds, timerId] = [0, 0]; // 구조분해 할당 // 체크박스가 체크되면 이벤트 실행 checkBox.addEventListener("change", () => { if (checkBox.checked) { document.body.style.backgroundColor = 'pink'; timerId = setInterval(() => { seconds += 1; timer.textContent = `${seconds}초`; }, 1000) } else { document.body.style.backgroundColor = 'white'; clearInterval(timerId); } }); });
< 출처 >
“혼공 자바스크립트 40~46강,” 게시자 “윤인성,” https://www.youtube.com/playlist?list=PLBXuLgInP-5kxpAKy2DNXoebCse2grHjl