const template = ` <div class="saying"> <h2 class="saying__title">{%=o.title%}</h2> <p class="saying__message">{%=o.message%}</p> <span class="saying__speaker">{%=o.speaker%}</span><br> <button class="saying__change" type="button">{%=o.button%}</button> </div> `; class Saying { constructor() { this.wrapper = $('#app'); this.template = template; this.pubsub = $({}); } on(/* events [, selector ] [, data ], handler */) { this.pubsub.on.apply(this.pubsub, arguments); } off(/* events [, selector ] [, handler ] */) { this.pubsub.off.apply(this.pubsub, arguments); } render(data) { // 이 로직만으론 UI의 형태를 가늠하기 힘들다. this.wrapper.html(tmpl(template, { title: data.title, message: data.message, speaker: data.speaker, button: data.button })); // 이벤트 처리를 위해 DOM을 셀렉팅한다. this.wrapper.find('button').on('click', this.onClick.bind(this)); } change(saying) { // 상태를 바꾸기 위해 DOM을 셀랙팅한다. // 마찬가지로 UI의 형태를 가늠하기 힘들다. this.wrapper.find('.saying__message').text(saying.message); this.wrapper.find('.saying__speaker').text(saying.speaker); } onClick() { this.pubsub.trigger('change'); } } const saying = new Saying(); saying.render({ title: '오늘의 명언', message: '언제나 현재에 집중할수 있다면 행복할것이다.', speaker: '파울로 코엘료', button: '바꾸기' }); saying.on('change', function() { saying.change({ message: '많은 사람이 재능의 부족보다 결심의 부족으로 실패한다.', speaker: '빌리 선데이' }); });
// ------------------------------------- // // Style of App // ------------------------------------- // #app { width: 340px; } // ------------------------------------- // // Style of Saying // ------------------------------------- // $module: 'saying'; .#{$module} { background: #fff; border: 1px solid #ededed; padding: 10px; &__title { margin: 0; } &__message { margin: 5px 0; } &__speaker { font-size: 14px; color: #808080; } }
<div id="app"></div>