Vue

Vue의 패턴은 MVVM패턴이다.
Controller의 역할을 ViewModel이 한다.
FormComponent
index.html
<form v-on:submit.prevent="onSubmit">
<input type="text" v-model="query" v-on:keyup="onKeyup"
placeholder="검색어를 입력하세요" autofocus>
<button v-show="query.length" v-on:click="onReset" type="reset"
class="btn-reset"></button>
</form>
Vue는 Html에서 View의 역할을 한다.(세상에나)
Model의 데이터를 받거나 이벤트를 발생시키는 것들이..
하나씩 살펴보면
<form>
v-on
v-on : submit.prevent=Vue객체의 메소드
특정 돔 이벤트를 지정하고 돔 이벤트가 발생시에 Vue객체의 메소드를 실행시킨다.
addEventListener나 on(돔이벤트)의 역할을 함
위 같은 경우에는
폼 태그의 submit이벤트 발생시에
preventDefault()를 발동하고
Vue 객체의 onSubmit()을 실행시킨다.
<input>
V-model
v-model = Vue객체의 프로퍼티 data의 프로퍼티
Vue객체의 데이터(모델)과 바인딩 시키는 역할을 한다.
v-on:keyup
인풋에 키보드입력시마다 onKeyup()실행
<button>
v-show
v-show="query.length"
Boolean타입을 받으며
결과가 True일때는 display가 show로
아닐 시에는 hide가 됨
v-on:click="onReset"
index.html
<div v-if="submitted">
<div v-if="searchResult.length">
<ul>
<li v-for="item in searchResult">
<img v-bind:src="item.image"> {{item.name}}
</li>
</ul>
</div>
<div v-else>
{{query}} 검색어로 찾을수 없습니다
</div>
</div>
폼태그 아래의 SearchResult부분
v-if
Boolean타입을 받으며
True일시에만 해당 태그가 존재함
v-if="submitted"
검색어가 제출되었을때만 아래 div가 존재
v-if="searchResult.length"
검색 결과가 존재 할 때만 해당 div가 존재
아닐시에는
v-else의 div가 존재
v-for
배열타입을 받고 태그를 반복해서 생성
v-for="item in searchResult"
searchResult의 모든 배열인자들을 item으로 정의하고 반복 실행
{{Model}}
모델을 불러낼 때
이에 따른 속성들은 각각 이러함
app.js
import SearchModel from './models/SearchModel.js'
new Vue({
el: '#app',
data: {
query: '',
submitted: false,
searchResult: []
},
methods: {
onSubmit(e) {
this.search()
},
onKeyup(e) {
if (!this.query.length) this.resetForm()
},
onReset(e) {
this.resetForm()
},
search() {
SearchModel.list().then(data => {
this.submitted = true
this.searchResult = data
})
},
resetForm() {
this.query = ''
this.searchResult = []
this.submitted= false
}
}
})
Vue객체를 생성후에 파라미터로
1.el <= 적용할 element (이 때 자식 노드들까지 모두 적용됨)
2. data
3.methods
data
query
input의 value를 컨트롤 하기 위해 사용할 예정
submitted
제출 전 후를 컨트롤 하기 위해서 사용
searchResult
모델에서 데이터를 담을 배열
methods
onSubmit()
Form의 submit시 실행되는 함수
search()를 실행
serach()
SearchModel.list().then(...)
모델에서 Promise 함수로 받은 데이터를
seachResult에 담음
(이는 곧 렌더링 하기 위함)
onKeyup()
query가 비었을 때(input의 value가 없을 때)
resetForm()실행
onReset()
리셋버튼 클릭시에
resetForm()실행
resetForm()
this.query를 초기화 하고(input의 value)
this.searchResult를 초기화하고(렌더링할 요소를 없애고)
this.submitted을 false로 전환(검색하기 이전)
TapComponent
<div v-else>
<ul class=tabs>
<li
v-for="tab in tabs"
v-bind:class="{active: tab == selectedTab}"
v-on:click="onClickTab(tab)"
>
{{tab}}
</li>
</ul>
<div v-if="selectedTab === tabs[0]">
추천 검색어 목록
</div>
<div v-else>
최근 검색어 목록
</div>
</div>
검색어가 없을 시에 실행
v-for
vue속성키중 tabs배열을 차례로 가져와 li태그 생성
v-bind:class
class를 사용하는데 vue 키가 필요해서 사용
tab이 selectedTab과 같은 경우의 li태그는 active로 클래스를 바꿈
v-on:click
onClickTab(tab)을 실행
파라미터는
타겟의 벨류값
onClickTab(tab){
this.selectedTab = tab
onClickTab은
this.selectedTab을 바꿈
KeywordComponent
<div v-if="selectedTab === tabs[0]">
<div v-if="keywords.length">
<ul class="list">
<li
v-for="(item,index) in keywords"
v-on:click="onClickKeyword(item.keyword)"
>
<span class="number">{{index+1}}</span>
{{item.keyword}}
</li>
</ul>
</div>
keywords의 length가 존재 할 경우에
ul태그를 실행
v-for="(item,index) in keywords"
v-for에 index를 위와 같은 방식으로 추가할 수 있음
fetchKeyword(){
KeywordModel.list().then(data => {
this.keywords = data
},
모델의 데이터를 받음
HistoryComponent
<div v-if="historys.length">
<ul class="list">
<li v-for="(item, index) in historys"
v-on:click="onClickHistory(item.keyword)">
<span class="number">{{index + 1}}</span> {{item.keyword}}
<span class="date">{{item.date}}</span>
<button class="btn-remove" v-on:click.stop="OnClickRemoveHistory(item.keyword)" >
</button>
</li>
</ul>
</div>
v-on:click.stop
button은 li태그 자식태그라서 이벤트 버블링이 생긴다(onClickHistory도 실행)
보통은
stopPropagation()메소드를 이용하지만
Vue에서는 .stop으로 버블링을 해결한다.