본문 바로가기

FrontEnd/VanillaJs

[Frontend] VanillaJS vs Vue.js (2)

내용이 많아서 나눠서 해야 할 것 같다.


여튼

Form과 Tab 컴포넌트를 끝내고


Keyword History Result 가 남음


KeywordView.js

KeywordView.render = function (data = []) {
this.el.innerHTML = data.length ? this.getKeywordsHtml(data) : this.messages.NO_KEYWORDS
this.show()
this.bindClickEvent()
return this
}

KeywordView.getKeywordsHtml = function (data) {
return data.reduce((html, item, index) => {
html += `<li data-keyword="${item.keyword}"><span class="number">${index + 1}
</span>${item.keyword}</li>`
return html
}, '<ul class="list">') + "</ul>"
}

KeywordView.bindClickEvent = function() {
Array.from(this.el.querySelectorAll('li')).forEach(li => {
li.addEventListener('click', e => this.onClickKeyword(e))
})
}

KeywordView.onClickKeyword = function (e) {
const {keyword} = e.currentTarget.dataset
this.emit('@click', {keyword})
}

export default KeywordView


render()

데이터에 따른 렌더링을함

데이터가 있을시에는 getKeywordHtml을 실행하고 아니면

데이터가 없음을 알림

이외에 show()와

bindEventClickEvent()를 실행


getKeywordsHtml()

데이터를 받아 렌더링 할 내용을 리턴

data는 배열형태를 띄고

reduce함수를 사용


배열.reduce((누적값, 현잿값, 인덱스, 요소) => { return 결과 }, 초깃값);


reduce는 배열을 계속 누적한다.

이 때 초기값은

<ul class="list">가 되는 것이고

누적되는 것은 html

html은

<li data-keyword="data의 첫번째 키워드일 것"> <span class="number">인덱스일것+1</span> 첫번째 키워드일것 </li>

.

.

.

마지막 키워드일것

으로 누적되고 마지막에 html을 출력하는 형식이다.


bindClickEvent()


이벤트 바인딩된 것


onClickKeyword()


1. keyword에 => 현재 엘리멘트의 데이터셋을 저장

(li태그에 data-keyword라고 작성했는데 이는 곧

li태그에 keyword라는 데이터셋 형태의 객체를 저장하라 라는 말인듯)


콘솔로그한 결과


2. 클릭 이벤트 에밋 (키워드 클릭시에 발생하는 것들(리랜더링 같은거)) 



HistoryView.js

const HistoryView = Object.create(KeywordView)

HistoryView.messages.NO_KEYWORDS = '검색 이력이 없습니다'

HistoryView.getKeywordsHtml = function (data) {
return data.reduce((html, item) => {
html += `<li data-keyword="${item.keyword}">
${item.keyword}
<span class="date">${item.date}</span>
<button class="btn-remove"></button>
</li>`
return html
}, '<ul class="list">') + "</ul>"
}

HistoryView.bindRemoveBtn = function () {
Array.from(this.el.querySelectorAll('button.btn-remove')).forEach(btn => {
btn.addEventListener('click', e => {
e.stopPropagation()
this.onRemove(btn.parentElement.dataset.keyword)
})
})
}

HistoryView.onRemove = function (keyword) {
this.emit('@remove', {keyword})
}

export default HistoryView


객체 상속을 View가 아닌 KeywordView에서 받은모습


getKeywrodHtml()

KeywordView에서 상속


bindRemoveBtn()

각각의 버튼 태그를 클릭하면 onRemove메소드 발생

이때 파라미터는 btn을 감싸는 li태그


onRemove()

@remove를 에밋


ResultView.js

ResultView.render = function (data = []) {
console.log(tag, 'render()', data)
this.el.innerHTML = data.length ? this.getSearchResultsHtml(data) : this.messages.NO_RESULT
this.show()
}

ResultView.getSearchResultsHtml = function (data) {
return data.reduce((html, item) => {
html += this.getSearchItemHtml(item)
return html
}, '<ul>') + '</ul>'
}

ResultView.getSearchItemHtml = function (item) {
return `<li>
<img src="${item.image}" />
<p>${item.name}</p>
</li>`
}

export default ResultView

render()

 값이 있으면 getSearchResultHtml()결과값 출력

아니면 에러메세지를 렌더링


getSearchResultsHtml()

html을 누적

이때 data의 모든 내용들로

getSearchItemHtml()을 실행


getSearchItemHtml은 다음을 출력