2) vue 공식 문서 보면서 메모 1
vue 공식 문서는 한국어로 번역이 잘 되어 있는 편이다. 어려운 부분은 건너뛰고 순서대로 보면서 추가적으로 메모한 부분을 정리했다. 따로 적어두지 않은 부분도 일단 다 중요한 것 같다.
폴더 세팅
공식문서는 ‘Vue 인스턴스‘부터 보기 시작했다.
간단하게 바로 cdn을 이용해서 실습하기로 한다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
뷰를 가져오면 생성자 함수로 (new Vue()
) 뷰 객체를 만들 수 있다. 인스턴스가 결과로 나온다.
vscode에서 라이브 서버로 확인할 수 있다.
반응형 데이터는 data에 정의가 되어 있어야 한다.
data에 객체로 바로 값을 쓰면 안되고 무조건 함수로 만들어야 한다. 인스턴스를 복제해서 사용할 때 문제가 생기기 때문이다. 함수로 만들어서 사용하면 실행될 때마다 새롭게 값이 만들어져 메모리에 할당된다.
Vue인스턴스 ~ 리스트 렌더링
lifecycle
뷰 인스턴스의 생애 주기. 라이프사이클에서 생성될 때, 마운트될 때, 데이터 변경 될 때, 파괴될 때 실행되어야 할 로직을 추가해줄 수 있다.
반응형 데이터가 바뀔 때 해당하는 부분은 beforeupdate, updated 이다.
destroy되면, 즉 인스턴스가 파괴되면 반응성을 가질 수 없는 상태가 된다.
virtual DOM
가상의 HTML구조.
데이터가 바뀔 때 버추얼 돔의 역할: 가짜 HTML구조가 만들어지고 진짜 HTML구조와 비교한다. 비교해서 다른 부분만 갱신한다.
템플릿 문법
보간법.
- HTML속성이면 ⇒ v-bind:style=”myStyle”
- 컨텐트면 ⇒ {{ myStyle }}
v-once: 한 번만 반응성을 가진다. 메모리 사용 down
v-html: xss취약점이 있지만 내가 만든 건 신뢰할 수 있으니깐 괜찮다. 외부 데이터 가져올 때 (ex. 댓글) 주의해야 한다.
computed
계산된 데이터를 만들어 주는 옵션. 캐싱 기능도 있다. 정의된 데이터를 활용해서 반응성이 있다. 그래서 계산된 데이터도 다시 계산된다. 계산 기능은 메소드로 쓸 수도 있지만 캐싱을 생각하면 computed가 더 적합할 수도.
getter, setter 는 vuex에서 유용하다(심화 기술)
<style>
.active {
color: salmon;
}
</style>
<div id="app">
<div :class="{ active: msg }">
</div>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
msg: 'Hello Vue?!'
}
},
computed: {
reversedMsg: {
// Getter 값을 얻는 용도
get() {
return this.msg.split('').reverse().join('')
},
// Setter 값을 지정하는 용도
set(value) {
this.msg = value
}
}
}
})
</script>
watch
정의된 데이터를 감시한다. 변경이 있으면 처리해야 할 로직을 작성하면 된다. (쓸 일이 별로 없다고 한다)
<div id="app">
<div>{{ reverseMsg() }}</div>
<div>{{ msg.split('').reverse().join('') }}</div>
<div>{{ reversedMsg }}</div>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
msg: 'Hello Vue?!'
}
},
computed: {
reversedMsg() {
return this.msg.split('').reverse().join('')
}
},
watch: {
msg() {
console.log('msg 변경됨!!')
},
reversedMsg() {
console.log('reversedMsg changed!!')
}
},
methods: {
reverseMsg() {
return this.msg.split('').reverse().join('')
}
}
})
</script>
클래스와 스타일 바인딩
<style>
.color-red { color: salmon; }
</style>
<div id="app">
<div v-bind:[attrname]="msg">Hello Vue?!</div>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
msg: 'color-red',
attrname: 'class'
}
}
})
</script>
조건부 렌더링
v-if, v-else-if, v-else 는 바로 다음 형제 요소로 있어야함. 중간에 뭐가 끼어 있으면 안되고 붙어 있어야 한다.
여러 요소를 한 번에 v-if를 적용할 때 요소를 <template>
으로 감싸고 여기에 v-if를 쓴다. 최종 렌더링 결과에는 포함되지 않는다.
- v-if: 일반적으로 사용하면 된다. lazy..
- v-show: 자주 바뀌어야 하는 요소에 쓰자. (요소를 처음부터 렌더링하고,
display: none
으로 보이고 안보이게 한다)
v-show부분 한국어 버전 잘려 있어서 원본은 여기서 보자.
https://vuejs.org/v2/guide/conditional.html#v-show
v-cloak
https://kr.vuejs.org/v2/api/#v-cloak
v-cloak 속성은 잠깐 붙어있다가 화면에 렌더링 되면 사라진다. 뷰가 최적화 되기 전에 잠깐 깜빡임이 있을 수도 있기 때문에 통상 display: none
을 추가 한다.
[v-cloak] {
display: none;
}
리스트 렌더링
v-for. 통상 배열을 사용하지만 객체도 가능하다.
key속성을 같이 사용해야 한다. key는 해당 리스트 내에서 고유한 값이면 된다.(다른 리스트까지 포함해서 고유값을 비교하지는 않음) 화면에 나타나는 것이랑 관련있지는 않지만 vue를 위해 써 주어야 한다.
<style>
ul {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 70px;
}
ul li {
border: 1px solid salmon;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div id="app">
<h1></h1>
<ul>
<li v-for="item in news.list" :key="item.name">
<img :src="item.logo" :alt="item.name">
<div></div>
</li>
</ul>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
news: {
title: '전체 언론사',
list: [
{ name: '한겨레', logo: 'URL' },
{ name: '세계일보', logo: 'URL' },
{ name: 'SBS', logo: 'URL' },
{ name: '동아일보', logo: 'URL' },
{ name: '일간스포츠', logo: 'URL' },
{ name: '스포츠조선', logo: 'URL' },
{ name: 'KBS', logo: 'URL' },
]
}
}
}
})
</script>
배열 변경 감지
변이 메소드를 사용하면 변경이 감지 된다. 인덱스로 배열에 직접 설정하면 감지 안된다(반응성이 없다)
this.$set
으로 하면 변경 감지 된다.
<div id="app">
<button @click="pushFruit">Click me!</button>
<ul>
<li v-for="fruit in fruits" :key="fruit.id">
</li>
</ul>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
fruits: [
{ id: 'f1', name: 'Apple' },
{ id: 'f2', name: 'Banana' },
{ id: 'f3', name: 'Cherry' },
{ id: 'f4', name: 'Mango' }
]
}
},
methods: {
pushFruit() {
// this.fruits.push({ id: 'f5', name: 'Orange' })
// this.fruits[4] = { id: 'f5', name: 'Orange' }
this.$set(this.fruits, 4, { id: 'f5', name: 'Orange' })
console.log(this.fruits)
}
}
})
</script>
객체 변경 감지
this.$set
= Vue.set
<div id="app">
<button @click="addProp">Click me!</button>
<ul>
<li v-for="(value, key, index) in user" :key="key">
{{ index + 1 }} - {{ key }}: {{ value }}
</li>
</ul>
</div>
<script>
// Vue 인스턴스
const vm = new Vue({
el: '#app',
data() {
return {
user: {
name: 'JOHN',
age: 85,
email: 'the@gmail.com',
// isValid: undefined // 선언해둔다.
}
}
},
methods: {
addProp() {
this.$set(this.user, 'isValid', true) // 이 속성을 반응성으로 추가할 것이다 - 데이터, 속성명, 값
// this.user.isValid = true
console.log(this.user)
}
}
})
</script>
Leave a comment