본문 바로가기

DOM

DOM 기초(7) - 숫자 증감기, 댓글(Create / Read) 구현

728x90
반응형

1) 코드 실습

    1-1) 숫자 증감기
    1-2) 댓글(Create / Read)

 

 

 

 

 

1) 코드 실습

1-1) 숫자 증감기

 

코드 설계

/*
Counter 예제

처음에는 "0"으로 값이 설정(초기화)되어 있어야 함
"+" 버튼을 생성해야 함
"-" 버튼을 생성해야 함

"+" 버튼을 누르면 1씩 증가하도록 이벤트를 걸어줘야 함
"-" 버튼을 누르면 1씩 감소하도록 이벤트를 걸어줘야 함

1. 화면 그리기(html 구성 작업)

2. 어떻게 구성할지 고민

3. 입력값이 무엇인지 살펴볼 계획
*/

// 첫번째 형태
const display = document.querySelector("#counter");
const incrementBtn = document.querySelector("#increment");
const decrementBtn = document.querySelector("#decrement");

      let num = 0;
      display.innerHTML = num;

      incrementBtn.addEventListener("click", function () {
        display.innerHTML = ++num;
      });
      decrementBtn.addEventListener("click", function () {
        display.innerHTML = --num;
      });

 

 

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>
  </head>
  <body>
    <h1>
      Value :
      <span id="counter"></span>
    </h1>
    <button id="increment">+</button>
    <button id="decrement">-</button>
    <script type="text/javascript">
      const display = document.querySelector("#counter");
      const incrementBtn = document.querySelector("#increment");
      const decrementBtn = document.querySelector("#decrement");

      let num = 0;
      display.innerHTML = num;

      function handler(e) {
        // e.target: e.target은 Element이기에 데이터 타입은 객체이다!!
        if (e.target.id === "increment") {
          ++num;
        } else {
          --num;
        }
        display.innerHTML = num;
      }

      // 바로 위의 if 조건문을 삼항연산자로 변형한 코드(출력결과는 동일함!!)
      // display.innerHTML = e.target.id === 'increment' ? ++num : --num;

      incrementBtn.addEventListener("click", handler);
      decrementBtn.addEventListener("click", handler);
    </script>
  </body>
</html>

 

 

+) index2.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>
  </head>
  <body>
    <ul>
      <li id="menu1">메뉴1</li>
      <li id="menu2">메뉴2</li>
      <li id="menu3">메뉴3</li>
      <li id="menu4">메뉴4</li>
      <li id="menu5">메뉴5</li>
    </ul>
    <script type="text/javascript">
      const ulElement = document.querySelector("ul");

      function handler(e) {
        console.log(e.target);
      }
      ulElement.addEventListener("click", handler);
    </script>
  </body>
</html>

 

 

 

 

1-2) 댓글(Create / Read)

※ 댓글 구현 목적 - "CRUD"를 연습하기 위함!!

1. 댓글을 입력할 수 있다. (Create)

  • 댓글 입력 폼에 내용을 입력한 뒤 'submit' 버튼을 누르면 리스트에 추가되도록 함
  • 만일 입력 폼이 비어있는 상태에서 'submit' 버튼을 누르면 경고 팝업을 띄움(alert or modal)
  • 댓글이 성공적으로 처리되면 입력 폼을 'reset'

 

 

2. 댓글을 리스트로 볼 수 있다. (Read)

  • 댓글 내용은 '아이디', '댓글내용', '날짜'로 표현함
  • 댓글 리스트는 최신순으로 나타냄(가장 최근의 댓글이 맨 상단으로 올라오도록 한다는 의미)
  • 댓글 총 갯수를 나타냄
  • 댓글 삭제를 위한 삭제 버튼을 생성함


3. 댓글을 수정할 수 있다. (Update)

  • 댓글 리스트에서 내용을 '클릭'하면 input box로 변경됨
  • input value 값의 경우, '클릭한 내용'을 유지함(내용 수정 시 기존의 내용을 일단 띄워주고 거기서 수정을 하도록 한다는 의미)
  • input 내용의 경우, 'enter'를 누르면 수정사항을 저장함


4. 댓글을 삭제할 수 있다. (Delete)

  • 해당 리스트의 삭제 버튼을 '클릭'하면 안내창을 띄우도록 함
  • 안내창에서 확인 버튼을 누르면 삭제를 진행함
  • 안내창에서 취소 버튼을 누르면 아무런 수정을 하지 않음

 


설명

기본적으로 CRUD는 작업 진행 시 'C(Create)'를 가장 먼저 작업함!
Create 작업 시 Read와 연관성이 높음!

데이터를 어떻게 저장하는지까지가 Create의 범위이다!!
즉, 리스트에 어떻게 뿌려질지 생각하면서 변수를 어떻게 넣을지 고려하는 것이 Create의 범위이다!!

 


Create 설명
Object, Array >> 변수 하나에 데이터를 여러 개 담을 수 있음!!

객체와 배열을 같이 사용해야 하는 상황(배열 안에 복수 개의 객체를 담은 형태)이다! >> 'Object[]'

리스트를 표현할 때는 배열이 좋고,
하나의 댓글에 내용을 표현할 시에는 객체가 좋음!
따라서 데이터 타입이 'Object[]'가 될 것 같음!!

const list = [
	{
		userid : 'web7722',
		comment : '내용을 입력할 공간',
		date : '2022-11-15'
	},
	{
		userid : 'web7722',
		comment : '내용을 입력할 공간',
		date : '2022-11-15'
	},
	{
		userid : 'web7722',
		comment : '내용을 입력할 공간',
		date : '2022-11-15'
	},
]

 

// 문제
// 학생을 객체로 표현하시오.

// 문제
// 학생 리스트를 만드시오.

const students = [];

const person = {
	name : '황상범',
	age : 27,
}

const person2 = {
	name : '장준영',
	age : 28,
}

students.push(person);
students.push(person2);

 

생성자 함수

function Person(name, age) {
	// this = {}
	this.name = name
	this.age = age
	// return this
}

const person1 = new Person('황상범', 27);
const person2 = new Person('장준영', 28);

students.push(person1, person2);

 

Class

class Person {
	constructor(name, age) {
		this.name = name
		this.age = age
	}
}

const person1 = new Person('황상범', 27);
const person2 = new Person('장준영', 28);

students.push(person1, person2);

 

 

Read 설명

어떤 데이터를 보여줄 것인지

const list = [
	{userid: 'web7722', content: '안녕하세요1', date: '2022-11-15'},
	{userid: 'web7722', content: '안녕하세요2', date: '2022-11-15'},
	{userid: 'web7722', content: '안녕하세요3', date: '2022-11-15'}
]

 

어떤 형태로 표현할 것인지

<ul class="comment-row">
	<li class="comment-id">web7722</li>
	<li class="comment-content">안녕하세요1</li>
	<li class="comment-date">2022-11-15</li>
</ul>
<ul class="comment-row">
	<li class="comment-id">web7722</li>
	<li class="comment-content">안녕하세요2</li>
	<li class="comment-date">2022-11-15</li>
</ul>
<ul class="comment-row">
	<li class="comment-id">web7722</li>
	<li class="comment-content">안녕하세요3</li>
	<li class="comment-date">2022-11-15</li>
</ul>

 

그리고 난 뒤 Javascript를 통해서

<ul>
	<li></li>
	<li></li>
	<li></li>
</ul>

 

아래와 같이 만들 수 있는가

const ul = document.createElement('ul');
const li1 = document.createElement('li');
const li2 = document.createElement('li');
const li3 = document.createElement('li');

ul.append(li1);
ul.append(li2);
ul.append(li3);

ul.setAttribute('class', 'comment-row');
li1.setAttribute('class', 'comment-id');
li2.setAttribute('class', 'comment-content');
li3.setAttribute('class', 'comment-date');

const obj1 = {};
const obj2 = {};
const obj3 = {};

obj2.name = 'sangbeom';
console.log(obj1.name); // undefined

 

<ul>
	<li></li>
	<li></li>
	<li></li>
</ul>

 

 

 

 

comment.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>
    <link rel="stylesheet" href="./public/css/comment.css" />
  </head>
  <body>
    <div>
      <ul class="comment">
        <li class="comment-form">
          <form id="commentFrm">
            <h4>
              댓글쓰기
              <span></span>
            </h4>
            <span class="ps_box">
              <input
                type="text"
                placeholder="댓글 내용을 입력해주세요."
                class="int"
                name="content"
              />
            </span>
            <input type="submit" class="btn" value="등록" />
          </form>
        </li>
        <li id="comment-list">
          <!-- const list = [ {userid: 'web7722', content: '안녕하세요1', date:
          '2022-11-15'}, {userid: 'web7722', content: '안녕하세요2', date:
          '2022-11-15'}, {userid: 'web7722', content: '안녕하세요3', date:
          '2022-11-15'} ] 
        createElement >>
        -->
          <!-- <ul class="comment-row">
            <li class="comment-id">web7722</li>
            <li class="comment-content">안녕하세요1</li>
            <li class="comment-date">2022-11-15</li>
          </ul>

          <ul class="comment-row">
            <li class="comment-id">web7722</li>
            <li class="comment-content">안녕하세요2</li>
            <li class="comment-date">2022-11-15</li>
          </ul>

          <ul class="comment-row">
            <li class="comment-id">web7722</li>
            <li class="comment-content">안녕하세요3</li>
            <li class="comment-date">2022-11-15</li>
          </ul> -->
        </li>
      </ul>
    </div>
    <script src="./public/js/comment.js" type="text/javascript"></script>
  </body>
</html>

 

 

comment.css

* {
  margin: 0;
  padding: 0;
}

ul,
li {
  list-style: none;
}

.comment {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  padding: 30px;
  width: 600px;
  margin: 0 auto;
}

.comment > li {
  margin-top: 20px;
}

.comment > li:nth-child(1) {
  margin: 0px;
}

.comment-row {
  display: flex;
  justify-content: space-between;
  flex-direction: row;
}

.comment-row {
  margin-top: 20px;
  width: 100%;
}

.comment-row > li:nth-child(2) {
  flex-shrink: 0;
  flex-grow: 1;
  padding-left: 25px;
  z-index: 1;
  width: 100%;
}

.comment-row > li:nth-child(2) {
  width: 85px;
}

.comment-form > form {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
}

.comment-form > form > h4 {
  width: 100%;
  margin: 14px 0 14px 0;
}

.comment-content {
  word-break: break-all;
  padding-right: 25px;
}

.ps_box {
  display: block;
  position: relative;
  width: 80%;
  height: 51px;
  border: solid 1px #dadada;
  padding: 10px 14px 10px 14px;
  background: #fff;
  box-sizing: border-box;
}

.ps_box > input {
  outline: none;
}

.int {
  display: block;
  position: relative;
  width: 100%;
  height: 29px;
  padding-right: 25px;
  line-height: 29px;
  border: none;
  background: #fff;
  font-size: 15px;
  box-sizing: border-box;
  z-index: 10;
}

.btn {
  width: 18%;
  padding: 18px 0 16px;
  text-align: center;
  box-sizing: border-box;
  text-decoration: none;
  border: none;
  background: #333;
  color: #fff;
  font-size: 14px;
}

.comment-delete-btn {
  display: inline-block;
  margin-left: 7px;
  cursor: pointer;
}

.comment-update-input {
  border: none;
  border-bottom: 1px solid #333;
  font-size: 16px;
  color: #666;
  outline: none;
}

 

 

comment.js

// input value console 찍기
// Read
const form = document.querySelector("#commentFrm");
const total = document.querySelector("h4 > span");
const commentList = document.querySelector("#comment-list");
const list = [];

function Comment(content) {
  this.userid = "web7722";
  this.content = content;
  this.date = "2022-11-15";
}

function totalRecord() {
  total.innerHTML = `(${list.length})`; // 템플릿 리터럴
  // total.innerHTML = "(" + list.length + ")"; // 바로 위의 코드를 "+" 연산자를 써서 문자열을 더해준 방식(실행 결과는 동일함!!)
}

function createRow(userid, content, date) {
  const ul = document.createElement("ul");
  const li1 = document.createElement("li");
  const li2 = document.createElement("li");
  const li3 = document.createElement("li");

  ul.append(li1);
  ul.append(li2);
  ul.append(li3);

  ul.setAttribute("class", "comment-row");
  li1.setAttribute("class", "comment-id");
  li2.setAttribute("class", "comment-content");
  li3.setAttribute("class", "comment-date");

  li1.innerHTML = userid;
  li2.innerHTML = content;
  li3.innerHTML = date;

  return ul;
}

// 해당 drawing 함수 코드는 비효율적임 >> 그렇기에 react를 배우는 것임!!
function drawing() {
  commentList.innerHTML = "";
  // for 문을 반대로 돌림으로써 원래 의도한대로 댓글이 가장 최신 것이 맨 상단에 올라오도록 처리함
  // 만일 아래 코드와 달리 for 문을 정방향으로 돌리게 된다면 최신 댓글이 맨 아래에 쌓이게 되는 구조가 형성됨
  for (let i = list.length - 1; i >= 0; i--) {
    // console.log(list[i].userid, list[i].content, list[i].date); // Object
    const row = createRow(list[i].userid, list[i].content, list[i].date);
    commentList.append(row);
  }
}

function submitHandler(e) {
  // 여기서 "submit" 버튼의 경우, 누를 시 url 주소가 바뀌며 웹 페이지 render가 다시 진행되기에 화면이 바뀌는, 즉 다시 웹 페이지가 load되기에 해당 함수가 동작하지 않는 것처럼 보임!!
  // 따라서 자바스크립트를 통해 해당 submit 기능, 즉 form element의 기능을 막아야 하므로 "e.preventDefault();"를 사용함!!
  e.preventDefault();
  
  // 여기사 e.target은 form element를 의미함!!
  const input = e.target.content;
  // console.log(e.target); // Object(form Element가 들어감!!)
  // console.log(e.target.content) // Object(input Element가 들어감!!)
  if (input.value === "") {
    alert("내용을 넣고 등록해주시기 바랍니다!");
    return;
  }

  // console.log(input.value); // console.log(e.target.content.value);
  const instance = new Comment(input.value);
  list.push(instance);

  totalRecord();

  // const ulElement = createRow(input.value);
  // commentList.append(ulElement);

  drawing();
  e.target.reset();
}

form.addEventListener("submit", submitHandler);