[코딩애플] JavaScript 강의 정리 (Level3 5강 ~ 6강)

이언덕·2024년 5월 7일

코딩애플

목록 보기
16/37
post-thumbnail

5강 / Select 2 : 자바스크립트로 html 생성하는 법

저번시간에 짠 코드는 확장성이 부족한 것 같다.
셔츠사이즈를 95, 100 이라고 하드코딩해놓고 보여주기만 하기 때문이다.
실제 쇼핑몰이라면 셔츠 사이즈가 매일매일 바뀔 것인데
이럴 경우 서버에서 보낸 데이터 갯수에 맞게 <option> 태그를 생성해줘야 좋을듯하다.
select태그 & option태그
먼저 html을 생성하는 법을 알아보자.

html 생성하는 법 1

<div> 안에 <p> 태그를 생성하려면

index.html

<div id="test">
</div>

index.js

let pTag = document.createElement('p');
pTag.innerHTML = '안녕';
document.querySelector('#test').appendChild(pTag);

이러면 생성된. 개발자도구 까보면 div 안에 p태그가 생성되어있다.

  • document.createElement() 쓰면 html 자료를 하나 생성해준다.
  • 그걸 맘대로 조작한 다음 appendChild() 써서 아무데나 넣으면 html이 생성된다.
    createElement(), appendChild(), innerText


html 생성하는 법 2

<div> 안에 <p> 태그를 생성하려면 2

index.html

<div id="test">
</div>

index.js

let a = '<p>안녕</p>';
document.querySelector('#test').insertAdjacentHTML('beforeend', a);

이래도 생성된다.

1번 방법은 코드가 너무 길고 복잡하기 때문에 특별한 이유 없으면 2번 방법을 사용한다.
(1번이 더 빠르게 동작하는데 0.0000x초 차이임)



바지옵션 누르면 다른 사이즈가 나와야하는데

먼저 html에 바지옵션을 추가하자

<form class="container my-5 form-group">
    <p>상품선택</p>
    <select class="form-select mt-2">
      <option>모자</option>
      <option>셔츠</option>
      <option>바지</option>
    </select>
    <select class="form-select mt-2 form-hide">
      <option>95</option>
      <option>100</option>
    </select>
</form>

바지옵션을 누르게 되면 28과 30 사이즈가 담긴 <select>가 떠야한다. 어떻게 코드를 짤 수 있을까?

html을 미리 만들어놨다가 보여줘도 되는데
실제 쇼핑몰의 경우 그렇게 만들어놓을 순 없다.
바지 사이즈가 매일 달라질 수 있기 때문이다.
실제 서비스는 매번 서버에서 데이터를 받아와서 "데이터 갯수만큼 <option> 생성해주세요~" 라고 코드를 짜놓는다.
그래서 우리도 이를 대비하기 위해 html을 미리 만들어놓지말고 자바스크립트로 html을 생성해보자.
방법은 위에서 배운 2번째 방법을 사용해보자

const formSelect = document.querySelectorAll(".form-select");

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    let template = "<option>28</option><option>30</option>";
    formSelect[1].insertAdjacentHTML("beforeend", template);
  }
}

코드실행이 어떤 순서로 이루어질까?
1. 유저가 바지를 선택하면
2. 먼저 둘 째 <select> 보여주세요
3. 둘 째 <select> 안에 비워주세요
4. html 만들어서 둘 째 <select> 안에 append 해주세요



응용

바지 눌렀다가 다시 셔츠 누르면 뭔가 이상해지는 문제도 해결해보기.
(셔츠눌렀을 때 둘 째 <select> 안에 있는 html도 조정해주면 될 것 같다.)

html 옵션 삭제

먼저 html에 있는 셔츠의 옵션 <option>95</option><option>100</option> 이 코드를 삭제헤준다.

<form class="container my-5 form-group">
    <p>상품선택</p>
    <select class="form-select mt-2">
      <option>모자</option>
      <option>셔츠</option>
      <option>바지</option>
    </select>
    <select class="form-select mt-2 form-hide"></select>
</form>

바지 눌렀다가 다시 셔츠 누르면 뭔가 이상해지는 문제도 해결 & 모자 선택시 옵션 없애기

const formSelect = document.querySelectorAll(".form-select");

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    let template = "<option>95</option><option>100</option>";
    formSelect[1].insertAdjacentHTML("beforeend", template);
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    let template = "<option>28</option><option>30</option>";
    formSelect[1].insertAdjacentHTML("beforeend", template);
  } else {
    formSelect[1].classList.add("form-hide");
  }
}




6강 / Select 3 : forEach, for in 반복문

반복문

오늘은 서버에서 바지 사이즈 데이터 가져와서
그 갯수만큼 <option>을 생성해볼 것이다.

const formSelect = document.querySelectorAll(".form-select");
let pants = [28, 30, 32];

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
	<무슨 코드 짜야할까?>
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
	<무슨 코드 짜야할까?>
  } else {
    formSelect[1].classList.add("form-hide");
  }
}

먼저 셔츠부분은 냅두고 바지부분에 대해서 코드를 만들어보자
맨 위에 pants 라는 변수를 하나 만들고 서버에서 보낸데이터라고 가정해보자.
pants 데이터 갯수만큼 <option>을 생성하고싶으면 어떻게 해야할까?
반복문 쓰면 될 것 같다.

const formSelect = document.querySelectorAll(".form-select");
let pants = [28, 30, 32];

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
	<무슨 코드 짜야할까?>
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    for (let i = 0; i < pants.length; i++) {
      let option = document.createElement("option");
      option.value = pants[i];
      option.textContent = pants[i];
      formSelect[1].appendChild(option);
    }
  } else {
    formSelect[1].classList.add("form-hide");
  }
}

이런식으로 작성할 수 있을 것 같다.
한번 for문에 대해 해석해보자

코드해석

  1. 바지가 선택되었을 때 pant배열의 길이가 i보다 작으면 for문안에 있는 코드가 실행된다.
  2. <option> 요소를 생성한 뒤 option 변수에 넣어준다.
  3. option.valueoption.textContent를 사용하여 <option>의 값을 설정한다.
  4. appendChild를 사용하여 빈 select 요소에 추가한다.

이렇게 for문이 완성되면 바지를 선택했을 때 pants로 부터 데이터를 잘 갖고 오는 것을 볼 수 있다.

근데 for문보다 더 쉬운 반복문이 있다. 그 반복문에 대해서 알아보자



forEach 반복문

배열을 순회해서 각 요소를 콜백 함수로 처리하기 위한 함수
쉽게말해 배열의 각 요소에 대해 주어진 콜백 함수를 적용해서 순서대로 한 번씩 실행한다.
한번 아래 예시를 살펴보자

let pants = [28, 30, 32];
pants.forEach(function(){
  console.log('안녕')
});

이렇게 되면 콘솔에는 어떤게 표시될까?

안녕이 3번 반복되는 것을 볼 수 있다.
이로인해 알 수 있는 것은
pants 안의 데이터 갯수만큼
forEach 콜백함수 안에 있는 코드가 실행되는 것을 알수있다.


let pants = [28, 30, 32];
pants.forEach(function(a, i){
  console.log(a, i)
});

콜백함수 안에 파라미터 2개까지 작명이 가능한데 (실은 3개까지 가능하다.)
첫 파라미터는 반복문 돌 때 마다 array 안에 있던 하나하나의 데이터가 되고
둘 째 파라미터는 반복문 돌 때 마다 0부터 1씩 증가하는 정수가 된다.
한번 콘솔에 a와 i 출력해보자


이제 위에서 배운 forEach를 통해 코드를 바꾸어보자

const formSelect = document.querySelectorAll(".form-select");
let pants = [28, 30, 32];

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    let template = "<option>95</option><option>100</option>";
    formSelect[1].insertAdjacentHTML("beforeend", template);
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    pants.forEach(function (size) {
      let optionTemplate = `<option>${size}</option>`;
      formSelect[1].insertAdjacentHTML("beforeend", optionTemplate);
    });
  } else {
    formSelect[1].classList.add("form-hide");
  }
}

이제 pants 라는 서버에서 보낸 데이터가 바뀔 때 마다
거기에 맞게 <option>이 생성될 것 같다. 변화에 대응이 좋은 코드가 되었다!

나머지 셔츠에 대한 부분도 똑같이 만들어보자

const formSelect = document.querySelectorAll(".form-select");
let shirts = [95, 100, 105];
let pants = [28, 30, 32];

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    shirts.forEach(function (size) {
      let optionTemplate = `<option>${size}</option>`;
      formSelect[1].insertAdjacentHTML("beforeend", optionTemplate);
    });
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    pants.forEach(function (size) {
      let optionTemplate = `<option>${size}</option>`;
      formSelect[1].insertAdjacentHTML("beforeend", optionTemplate);
    });
  } else {
    formSelect[1].classList.add("form-hide");
  }
}

셔츠도 마찬가지로 shirts 라는 서버에서 보낸 데이터가 바뀔 때 마다 거기에 맞게 <option>이 생성되도록 만들어주었다.



object 자료 다룰 때 for in 반복문 가능

object 자료 갯수만큼 반복문을 돌리고 싶으면

let obj = { name : 'kim', age : 20 }

for (let keyTest in obj){
  console.log('안녕')
}

for in 반복문 쓰면 된다.
for in 반복문에 대해서 잘 모르니 아래 사이트를 통해 이해하고 넘어가자
for in 반복문


그렇다면 콘솔창에 '안녕'이 몇번 출력될까?

2번이 출력되는 것을 볼 수 있다.


for in 반복문 쓰면 object 자료 안에 있는 keyvalue를 다 출력해볼 수도 있다.
지금 keyTest라고 작명하는 부분은 반복문이 돌 때 마다 object자료 안에 있던 key값이 된다.

let obj = { name : 'kim', age : 20 }

for (let keyTest in obj){
  console.log(keyTest)
}


출력해보면 진짜로 name, age 잘 나온다.


keyTest 말고 실제 자료인 value를 출력하고 싶으면

let obj = { name : 'kim', age : 20 }

for (let keyTest in obj){
  console.log(obj[keyTest])
}

위와 같이 코드를 작성하면 value를 출력할 수 있다. 콘솔을 확인해보자

value값이 출력되는 것을 볼 수 있다.



그래서 반복문의 용도는 2개가 있는데

원래 코드 복사붙여넣기용으로 쓰는게 for 반복문이라 했는데
arrayobject 자료 전부 꺼내서 쓰고 싶을 때도 반복문을 쓰면 유용하다.
그래서
1. 코드복붙하고싶으면
2. array, object 자료 다 꺼내고 싶을 때
반복문 사용하면 유용하다!



arrow function 문법

함수 만드는 다른 문법이 있다. 특히 콜백함수만들 때 자주 쓰는 방법인데

let pants = [28, 30, 32];
pants.forEach(function(size){
  console.log(size)
});

// 위 함수를 아래 arrow function으로 바꿀 수 있다.

pants.forEach((size) => {
  console.log(size)
});

function 키워드 대신 => 화살표를 ( ) 우측에 부착해도 똑같이 함수만들 수 있다.
저걸 arrow function 이라고 한다.


pants.forEach( size => {
  console.log(this)
});

arrow function은 파라미터가 하나면 () 소괄호 생략해도 괜찮다.
함수 중괄호 안에 return 한 줄 밖에 없으면 { } 중괄호와 return 동시에 생략해도 괜찮다.
그래서 간결하니 콜백함수에 자주 사용하는 사람들이 있다.


let 함수 = function(){ console.log('안녕') }
let 함수 = () => { console.log('안녕') }

참고로 함수 이렇게 만들어쓰는 사람도 있다.
이럴 때도 arrow function이 가끔 보인다.
그냥 함수와 arrow function의 기능차이는 하나가 있는데
함수 안에서 this를 써야할 경우

  • 그냥 함수는 함수 안에서 this를 알맞게 재정의해준다.
  • arrow function은 함수 안에서 this를 재정의해주지 않고 바깥에 있던 this를 그대로 사용한다.
    그래서 이벤트리스너 콜백함수안에서 this를 써야하면 arrow function 쓰면 의도와 다르게 동작할 수도 있다.
    그런데선 사용하면 안된다!


전체코드

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous" />
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" type="text/css" href="./index.css" />
    <title>Level3</title>
  </head>
  <body>
    <!-- <div class="container mt-3">
      <div class="card p-3">
        <span class="product">상품명</span>
        <span class="price">가격</span>
      </div>
    </div> -->

    <form class="container my-5 form-group">
      <p>상품선택</p>
      <select class="form-select mt-2">
        <option>모자</option>
        <option>셔츠</option>
        <option>바지</option>
      </select>
      <select class="form-select mt-2 form-hide"></select>
    </form>

    <script src="./index.js"></script>
  </body>
</html>

index.js

// const product = document.querySelector(".product");
// const price = document.querySelector(".price");

// let car2 = { name: "소나타", price: [50000, 3000, 4000] };

// product.innerHTML = car2.name;
// price.innerHTML = car2.price[0];

const formSelect = document.querySelectorAll(".form-select");
let shirts = [95, 100, 105];
let pants = [28, 30, 32];

formSelect[0].addEventListener("input", handleSelect);

function handleSelect(e) {
  let value = e.currentTarget.value;

  if (value == "셔츠") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    shirts.forEach(function (size) {
      let optionTemplate = `<option>${size}</option>`;
      formSelect[1].insertAdjacentHTML("beforeend", optionTemplate);
    });
  } else if (value == "바지") {
    formSelect[1].classList.remove("form-hide");
    formSelect[1].innerHTML = "";
    pants.forEach(function (size) {
      let optionTemplate = `<option>${size}</option>`;
      formSelect[1].insertAdjacentHTML("beforeend", optionTemplate);
    });
  } else {
    formSelect[1].classList.add("form-hide");
  }
}

index.css

.form-hide {
  display: none;
}

0개의 댓글