빵 입니다.

Class를 사용한 함수형 프로그래밍, Todo 만들기 본문

프론트엔드/TODO 만들기

Class를 사용한 함수형 프로그래밍, Todo 만들기

bread-gee 2019. 3. 14. 15:23

기능 정의

  • Todo 입력
  • Todo 수정
  • Todo 삭제
  • Todo Total 갯수 체크
  • Todo 완료 갯수 체크
  • Todo 미완료 갯수 체크

ES2015 버전에 class가 도입되었다.

이름은 클래스(Class)이지만나 다른 OOP 언어의 클래스와는 다르다.

자바스크립트의 class 는 함수의 prototype을 기반으로 동작한다.

그렇지만 함수로 작성하기에 번거로운 문법적 요소들이 많은 부분 개선되었다.


함수에서 함수 자체가 new 연산자와 결합했을때 생성자 역할을 하지만, class는 명시적인 constructor가 존재한다.

함수로 상속을 구현시 상위 함수의 prototype 을 직접 연결해줘야 하지만, class 는 extends 를 사용함으로써 보다 편리하게 상속을 지원한다.

클래스에서 인스턴스를 생성하려면 반드시 new 연산자를 이용해 constructor(생성자)를 호출해야 한다.

constructor는 인스턴스를 생성하고 클래스 프로퍼티를 초기화하기 위한 메서드이다.

constructor 내부에 선언한 클래스 속성들은 클래스의 인스턴스를 가리키는 this를 바인딩한다.

클래스 속성은 클래스가 생성할 인스턴스의 프로퍼티가 되며, 클래스의 인스턴스를 통해 클래스 외부에서 언제나 참조할 수 있다.(public)

constructor는 부모 클래스의 constructor 를 호출하기 위해 super 키워드를 사용할 수 있다.



HTML

        

Todo

    CSS

    @charset "UTF-8";
    @import url(//fonts.googleapis.com/earlyaccess/jejugothic.css);
    
    .todo_wrap{width:300px; margin:0 auto;}
    .todo_wrap h1{text-align:center;}
    .input_wrap{background:red;}
    .input_wrap:after{content:""; display:block; clear:both;}
    .input_wrap input{box-sizing:border-box; float:left; width:231px; height:40px; outline:0 none; border:1px solid #999; text-indent:5px;}
    .input_wrap input:focus{border-color:#03cf5d;}
    .input_wrap button{box-sizing:border-box; float:left; width:70px; height:40px; margin-left:-1px; outline:0 none; border:1px solid #03cf5d; background:#03cf5d; color:#fff;}
    .input_wrap button:hover{cursor:pointer;}
    
    .todo_list{list-style-type:none; margin:0; padding:30px 0;}
    .todo_list li{line-height:30px; font-family:'Noto Sans KR', sans-serif; font-size:13px;}
    .todo_list li input{vertical-align:middle;}
    .todo_list li label{vertical-align:middle; cursor:pointer;}
    .todo_list li button{box-sizing:border-box; width:20px; height:20px; outline:0 none; border:0 none; background:#ffffff; line-height:20px; color:red; vertical-align:middle; cursor:pointer; transition:background-color 0.5s ease;}
    .todo_list li button:hover{background:#03cf5d;}
    .todo_list .complete{text-decoration:line-through;}
    
    .todo_count{}
    .todo_count>span{position:relative; display:inline-block; width:30%; font-size:12px; text-align:center;}
    .todo_count>span>strong{position:relative; top:1px; display:inline-block; color:#1aaf5c;}
    

    JAVASCRIPT

    const src   = `
        

    Todo

      {{#each todoArray}}
    • {{/each}}
    {{totalCnt}} 완료 {{comCnt}} 미완료 {{incomCnt}}
    `; class Todo{ constructor(template, container){ this.todoArray = []; this.container = document.querySelector(container); this.template = Handlebars.compile(template); this.container.addEventListener("click", this.onCreateItem.bind(this)); this.container.addEventListener("keypress", this.onCreateItem.bind(this)); this.container.addEventListener('change', this.onChangeStatus.bind(this)); this.container.addEventListener('click', this.onDeleteItem.bind(this)); this.updateView(); } addArray(title){ this.todoArray.push({ title: title, id: Date.now(), chkState: false }); this.updateView(); } change(id, chkState){ this.todoArray.find(todo => todo.id === id).chkState = chkState; this.updateView(); } remove(id){ this.todoArray = this.todoArray.filter(todo => todo.id != id); this.updateView(); } onCreateItem(e){ if(e.target.id === 'btnAdd' || e.which === 13){ let txtInput = document.querySelector('#txtInput'); if( txtInput.value ){ this.addArray(txtInput.value); }else{ alert('할 일을 입력해주세요.'); } } } onChangeStatus(e){ if(e.target.type === 'checkbox'){ let id = +e.target.id; let chkState = e.target.checked; this.change(id, chkState); } } onDeleteItem(e){ if(e.target.name === 'btnDelete'){ let id = +e.target.dataset.id; this.remove(id); } } updateStatusBar(){ let totalCnt = this.todoArray.length; let comCnt = this.todoArray.filter(todo => todo.chkState).length; let incomCnt = this.todoArray.filter(todo => !todo.chkState).length; return { totalCnt, comCnt, incomCnt }; } updateView(){ this.container.innerHTML = this.template(Object.assign({ todoArray: this.todoArray }, this.updateStatusBar() )); } } let app = new Todo(src, '#todoWrap');


    CODEPEN 확인

    https://codepen.io/bread_gee/pen/qvpeQY

    반응형
    Comments