본문 바로가기

DOM

DOM 기초(2) - Event, 코드 실습(Lotto)

728x90
반응형

1) Event

    1-1) Element에 직접 넣기
    1-2) DOM 속성으로 넣는 방법이 있음

    1-3) addEventListener

2) 코드 실습 - Lotto 번호 뽑기

 

 

 

 

1) Event

1-1) Element에 직접 넣기

브라우저(웹 페이지 상 render가 되는 영역) 기준으로 배울 예정!

 

다양한 이벤트('click', 'mouseover', 'mouseout')에 대해

그 중 필요한 이벤트가 발동하여야
특정함수가 호출되도록 할 수 있음!!

...js
function a() {
console.log('hello world');
}
...

 

 

< Element에 직접 넣기 >

<button onClick="console.log('hello world')">버튼</button>

<!-- 클릭 이벤트가 발동하여야 함수가 호출됨을 의미함!! -->

 


on[Event 이름]

  • onClick
  • onMouseout
  • onMouseover

 

 

 

 

1-2) DOM 속성으로 넣는 방법이 있음

  1. JS 해당 Element를 선택할 줄 알아야 함!
  2. 선택한 Element에 onclick 속성에 함수 선언을 대입함!
const btn = document.querySelector(".btn"); // "document.querySelector(".btn");" 자체는 참조 타입이다!!
console.log(btn);

btn.onclick = function () {
console.log("hello world!");
alert("hello world!");
}

const btn2 = document.querySelector(".btn");
console.log(btn2);

 

const btn = document.querySelector(".btn"); // "document.querySelector(".btn");" 자체는 참조 타입이다!!
console.log(btn);

btn.onclick = function () {
  console.log("hello world!");
  alert("hello world!");
};

// 재할당 역할(대입 연산자를 통해 값이 바뀐 것을 의미함)
btn.onclick = function () {
  console.log("hello world! 2");
};

const btn2 = document.querySelector(".btn");
console.log(btn2);
// html 문서 상에서 button 태그 등과 같이 태그 생성 시 해당 태그는 객체로 생성되고,
// querySelector 등을 사용했을 시 기존에 생성된 객체를 참조하게 된다!!

const person = {
  name: "sangbeom",
  run: function () {
    console.log(this.name + " 달린다!");
  },
};
person.run();

// 여기서 run 메서드의 값에 대해 재할당이 일어나 함수 호출 시 출력값이 바뀜!
person.run = function () {
  console.log(this.name + " 걷는다!");
};
person.run();

/*
function personRun() {
  console.log(" 걷는다!");
};

person.run = personRun() //해당 함수 호출을 통해 얻은 반환값(return) "undefined"가 할당(return 지시자가 생략되어 있어 default 값인 'undefined'를 반환 받음)되어 person.run() 호출 시 함수가 아니라는 typeError가 발생함!!
person.run = personRun // 함수 복사가 완료되어 추후 해당 함수 호출 시 정상 실행됨!!

person.run();
*/

 

 

 

1-3) addEventListener

// "addEventListener"는 속성에다가 함수값을 넣어버리면 함수를 하나 밖에 못 넣는 기존의 문제를 해결해주기 위해 등장함

// 해당 element에다가 복수의 이벤트를 넣을 수 있게 해 줌!!

/*
	Event
	1) on click
	2) mouseover
	3) mouseout
*/

element.addEventListener('event', 함수값)

 

// addEventListener
const btn = document.querySelector(".btn");

const btnHandler = function () {
  console.log("hello world!");
};
btn.addEventListener("click", btnHandler);

btn.addEventListener("click", function () {
  console.log("hello world!");
});

btn.addEventListener("click", function () {
  console.log("hello world! 2");
});

function listener(event, callback) {
  if (event === "click") {
    callback();
  }
}

/*
listener("click", function () {
  console.log("hello world!");
});
*/

function handler() {
  console.log("hello world!");
}

listener("click", handler);

 

const btn = document.querySelector(".btn");
const btn2 = document.querySelector(".btn2");

function handler() {
  console.log("hello world! 1");
}

function handler2() {
  console.log("hello world! 2");
}

btn.addEventListener("click", handler);
btn.addEventListener("click", handler2);
btn2.addEventListener("mouseover", handler2);

btn.removeEventListener("click", handler);

 

function listener(event, callback) {
  let obj = {
    name: "sangbeom",
  };
  if (event === "click") {
    callback(obj);
  }
}

function handler3(e) {
  console.log(e); // {name: 'sangbeom'}
  console.log("hello world!");
}

listener("click", handler3);

 

 

const btn = document.querySelector(".btn");
const btn2 = document.querySelector(".btn2");
const display = document.querySelector("#display");

function handler(e) {
  display.classList.remove("none");
  console.log(e.target); // target: 이벤트를 발동시킨 element를 말함!!
  console.log(e.type); // type: addEventListener의 첫 번째 인자값을 의미함!!
  console.log("hello world! 1");
  //   display.innerHTML = "이벤트 발동!";
  if (e.type === "click") {
    display.innerHTML = "마우스를 클릭했다!";
  } else if (e.type === "mouseover") {
    display.innerHTML = "마우스를 올렸다!";
  }
}

btn.addEventListener("click", handler);
btn2.addEventListener("mouseover", handler);

 

// event object: 데이터 타입(object)
function handler2(e) {
  // e.target : Element를 뜻함!!
  console.log(e.target);

  // e.target.style = "background: blue;";
  // e.target.style = "display: none;";
  e.target.classList.add("none");
}

display.addEventListener("click", handler2);

// console.dir(display);

 

display.className = "b box";
const text = "b box";
const classList = text.split(" "); // ['b', 'box']

console.log(display.classList);
display.classList[0] = "a";
console.log(display.classList); // 바로 위의 class값 변경사항(재할당)이 반영되지 않음!!

// .push()
display.classList.add("view");
console.log(display.classList); // ['b', 'box', 'view', value: 'b box view']

display.classList.remove("box");
console.log(display.classList); // ['b', 'view', value: 'b view']
*/

 

 

 

< 이벤트 삭제 >

const btn = document.querySelector('.btn');

btn.removeEventListener()

let a = 'hello world'
// Element.removeEventListener(이벤트명: string, 함수값: function)

 

 

< 이벤트 객체 >

function listener(event, callback) {
let obj = {
name: "sangbeom",
};
if (event === "click") {
callback(obj);
}
}

function handler3(e) {
console.log(e); // {name: 'sangbeom'}
console.log("hello world!");
}

listener("click", handler3);

 

 

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .a {
        background: red;
      }

      .b {
        background: blue;
      }

      .none {
        /* display: none; */
        opacity: 0;
      }

      .box {
        width: 100%;
        height: 50px;
      }
    </style>
  </head>
  <body>
    <div id="display" class="a box">1</div>
    <!-- <button onClick="alert('hello world!')">버튼</button> -->
    <button class="btn">버튼</button>
    <button class="btn2">버튼2</button>
    <script src="./public/js/index.js" type="text/javascript"></script>
  </body>
</html>

 

※ html과 css를 배운 이유는 js를 잘 다루기 위해서이다!!( 물론 사고력 또한 키우기 위해서이다! )

 

 

 

 

 

2) 코드 실습 - Lotto 번호 뽑기

 

lotto.js

// 쉬운 것부터 하나하나 구현하는 것이 좋음!!
// 1. 번호생성 버튼을 누르면 #lotto element를 보이게 하고 싶음
//    1.1 번호생성 버튼에다가 이벤트(click)를 넣자
//      1.1.1 번호생성 element를 선택해서 가져올 수 있어야 함 = querySelector를 사용할 수 있어야 한다는 의미
//      1.1.2 #lotto 선택해서 가져오기
// 2. 랜덤 숫자를 뽑아서 부여하는 것
//    2.1 랜덤 숫자(1 ~ 45)를 뽑는 것
//    2.2 랜덤 숫자를 부여
//      2.2.1 클릭할 때 랜덤 값 생성해보기
//      2.2.2 랜덤 값 6개 만들기
//      2.2.3 element 선택 >> querySelectorAll() 사용
//      2.2.4 각각 순서에 맞게 내용을 넣어주기

// 문제 확인하기!
// 1. 색깔이 안 바뀜
//    1.1 내가 랜덤으로 뽑은 숫자의 범위가 어디에 해당되는지를 알아야 함
//        (1~10, 11~20, 21~30, 31~40, 41~45)
//        1.1.1 12라는 숫자가 있을 때 1 ~ 10
//              9라는 숫자가 있을 때 1 ~ 10
//    1.2 input 1 ~ 45 >> 1 ~ 10 = a, 11 ~ 20 = b, 21 ~ 30 = c ...
//        className을 활용해서 처리하자
// 2. 로또는 중복값이 없어야 함
// 배열에서 추출 값 제거(splice 활용) >> if 문을 통해 이미 추출한 값이 나오면 다시 랜덤으로 숫자를 돌려 추출하도록 함
// 이 경우 전체 횟수는 기존의 6번만 돌리려던 것에서 다시 숫자를 추출한 만큼 전체 수행 횟수가 늘어남!

// 현재는 코드로서 문제가 있다!!

const btn = document.querySelector("#btn");
const lottoDisplay = document.querySelector("#lotto");
const lottoBox = document.querySelectorAll("#lotto > li");
let lottoNum = [];
for (let i = 1; i < 46; i++) {
  lottoNum.push(i);
}

function randomLotto() {
  const random = Math.floor(Math.random() * 45) + 1;
  // Math.floor(Math.random() * 45)는 0 ~ 44까지의 숫자를 랜덤하게 반환하는데
  // 우리가 뽑으려는 숫자의 범위는 1 ~ 45이므로 1을 위의 코드에 더해준다!!
  return random;
}

function randomFinal() {
  let temp = []; // 아래 for 문을 6번 반복하는 과정에서 if 문을 통해 중복값인지 검사한 뒤 중복값은 splice 메서드로 제거함과 동시에 for문 반복횟수를 다시 원래대로 초기화하여 중복값 비교를 다시 실행하여 겹치지 않는 값들만 push 메서드를 써서 추가한 배열(중복값을 제외한 6개 값이 들어간 최종 랜덤 숫자 추출 배열)을 만들기 위해 선언함!!
  for (let i = 0; i < 6; i++) {
    let randomNum = randomLotto(); // 랜덤 숫자 추출(뽑는 과정에서 중복값 발생할 수 있음)

    if (temp.length !== 0) {
      for (let j = 0; j < temp.length; j++) {
        if (temp[j] === randomNum) {
          temp.splice(j, 1);
          i--;
        }
      }
    }
    temp.push(randomNum);
  }
  return temp;
}

function between(num, min, max) {
  if (min <= num && num <= max) {
    return true;
  }
  return false;
}

// input 1 ~ 45
// 문제 (1 ~ 10) => a, (11 ~ 20) => b, (21 ~ 30) => c ...
// output : a || b || c || d || e
function getClassName(num) {
  if (between(num, 41, 45)) {
    return "e";
  }
  if (between(num, 31, 40)) {
    return "d";
  }
  if (between(num, 21, 30)) {
    return "c";
  }
  if (between(num, 11, 20)) {
    return "b";
  }
  if (between(num, 1, 10)) {
    return "a";
  }
}

function lottoHandler(e) {
  /*
  hard coding 내용
  const num1 = randomLotto();
  const num2 = randomLotto();
  const num3 = randomLotto();
  const num4 = randomLotto();
  const num5 = randomLotto();
  const num6 = randomLotto();

  console.log(num1);
  console.log(num2);
  console.log(num3);
  console.log(num4);
  console.log(num5);
  console.log(num6);

  const num1ClassName = getClassName(num1);
  const num2ClassName = getClassName(num2);
  const num3ClassName = getClassName(num3);
  const num4ClassName = getClassName(num4);
  const num5ClassName = getClassName(num5);
  const num6ClassName = getClassName(num6);

  lottoBox[0].innerHTML = num1;
  lottoBox[0].className = num1ClassName;
  lottoBox[1].innerHTML = num2;
  lottoBox[1].className = num2ClassName;
  lottoBox[2].innerHTML = num3;
  lottoBox[2].className = num3ClassName;
  lottoBox[3].innerHTML = num4;
  lottoBox[3].className = num4ClassName;
  lottoBox[4].innerHTML = num5;
  lottoBox[4].className = num5ClassName;
  lottoBox[5].innerHTML = num6;
  lottoBox[5].className = num6ClassName;
  */


  /*
  선형 검색(참고용 코드)
  function linearSearch(array, target) {
    const length = array.length;
    for (let i = 0; i < length; i++) {
      if (array[i] === target) {
        return i;
      }
    }
    return -1;
  }
  */


  // 위의 hard coding을 간략히 줄여서 표현한 코드(출력결과는 동일함)
  let num = randomFinal();
  for (let i = 0; i < 6; i++) {
    lottoBox[i].innerHTML = num[i];
    lottoBox[i].className = getClassName(num[i]);
  }

  lottoDisplay.classList.remove("none");
}
btn.addEventListener("click", lottoHandler);

 

 

lotto.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #lotto > li {
        display: inline-block;
        font-size: 40px;
        width: 80px;
        height: 80px;
        border-radius: 40px;
        text-align: center;
        line-height: 80px;
        margin: 30px;
        box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.3);
      }

      #lotto.none {
        display: none;
      }

      /* 1 ~ 10 */
      #lotto > li.a {
        background: yellow;
      }
      /* 11 ~ 20 */
      #lotto > li.b {
        background: blue;
      }
      /* 21 ~ 30 */
      #lotto > li.c {
        background: red;
      }
      /* 31 ~ 40 */
      #lotto > li.d {
        background: gray;
      }
      /* 41 ~ 45 */
      #lotto > li.e {
        background: green;
      }
    </style>
  </head>
  <body>
    <h1>로또번호 생성기</h1>
    <ul id="lotto" class="none">
      <li class="a">7</li>
      <li class="b">11</li>
      <li class="c">21</li>
      <li class="d">31</li>
      <li class="e">45</li>
      <li class="e">41</li>
    </ul>
    <button id="btn">번호 생성</button>
    <script src="./public/js/lotto.js" type="text/javascript"></script>
  </body>
</html>