목차
목차1. Vue 2회1. Computed 속성과 Watch1-1. Computed 속성1-2. 캐싱 된다는 computed의 장점 by todos 예제1-3. 객체의 다른 속성 변경시, 반응하지 않아 렌더링 효율 좋다! by user 예제1-4. getter와 sertter를 통한 css관리 by fullName 예제1-5. watch 기본 사용법1-6. 참조형 데이터에서의 deep watch 2. 클래스와 스타일 바인딩2-1. 다양한 방식으로 class 지정하기2-2. 배열 리터럴로 클래스 지정하기2-3. 인라인 방식으로 클래스 지정하기
1. Vue 2회
1. Computed 속성과 Watch
1-1. Computed 속성
- 과정
표현식을 여러번 사용하기
→ methods를 통해 가독성 증가
→ computed를 통해 성능최적화
- computed 특징
- 함수가 아닌 data로 취급 된다. (
double()
⇒double
) - 계산된 값은 캐싱된다. (4번의 연산 ⇒ 1번의 연산)
double 예제 코드
- 차례대로
표현식, methods 방식, computed 방식
<div id="app"> <h1>{{count}}</h1> <h1>{{count * 2}}</h1> <h1>{{double_methods()}}</h1> <h1>{{double_computed}}</h1> <h1></h1> </div> <script> const App = { data() { return { count: 3, }; }, methods: { double_methods() { return this.count * 2; }, }, computed: { double_computed() { return this.count * 2; }, }, }; ... </script>
1-2. 캐싱 된다는 computed의 장점 by todos 예제
흐름
created
→ fetch
→ data.todos
→computed
→ {{todo.title}}
→ 캐싱활용 복사
created
라이프사이클에서fetch(/jsonPlaceholders/todos)
로200개의 todos
를 받아와 todos data에 값 할당
- v-for를 통해 todo.title 출력하기
- 소문자인 title을 대문자로 바꿔주기 (
많은 부하가 걸리는 작업
을 의미) computed
의upperTodos()
함수로 구현(bymap
,toUpperCase()
)
- 해당 html을 복사하여, 400개의 todos를 출력하도록 해도, 캐싱된 upperTodos를 사용하기 때문에 추가 계산이 필요 없음
todos 코드
<div id="app"> <ul> <li v-for="todo in upperTodos">{{todo.title}}</li> </ul> <ul> <li v-for="todo in upperTodos">{{todo.title}}</li> </ul> </div> <script> const App = { data() { return { todos: [], }; }, methods: {}, computed: { upperTodos() { return this.todos.map((todo) => ({ ...todo, title: todo.title.toUpperCase() })); }, }, created() { fetch("https://jsonplaceholder.typicode.com/todos") .then((res) => res.json()) .then((res) => { console.log(res); this.todos = res; }); }, }; const app = Vue.createApp(App).mount("#app"); </script>
1-3. 객체의 다른 속성 변경시, 반응하지 않아 렌더링 효율 좋다! by user 예제
user data
→ computed-dobleAge()
→ user.name 변경 → 추가 age계산 없음- 객체 타입인 user data중 computed의 함수가 user의 age속성만을 이용한다면, user의 다른 속성인 name, email 등에서 변경이 발생하여도 계산이 다시 일어나지 않는다.
- 즉 변경된 속성과 관련있는 부분만이 새로 계산되므로, 렌더링 최적화가 되어있음을 확인
user코드
<div id="app"> <h1>{{user.age}}</h1> <h1>{{doubleAge}}</h1> <h1>{{upperName}}</h1> </div> <script> const App = { data() { return { user: { name: "Outwater", age: 28, email: "kocon135@gmail.com", }, }; }, methods: {}, computed: { doubleAge() { console.log("Double!!"); return this.user.age * 2; }, upperName() { console.log("Upper!!"); return this.user.name.toUpperCase(); }, }, }; const app = Vue.createApp(App).mount("#app"); </script>
1-4. getter와 sertter를 통한 css관리 by fullName 예제
data 및 fullName 선언 → console에서 fullName에 다른 값 할당 → 화면 변화 없음 & 재출력시도 이전 이름 그대로
- fullName함수는,
data들(firstName, lastName)의 조합
으로 이루어져있다는 사실 주목 - 의존되어 있는 값이 변해야 computed값이 변경된다.
- setter를 통해, 중간에 값을 가로채어, setter 동작 시에 원하는 로직,동작 추가 가능
- data들을 각각 변경하여 computed 값이 변경되도록 설정
fullName 코드
<div id="app"> <h1>{{fullName}}</h1> <h1>{{firstName}}</h1> <h1>{{lastName}}</h1> </div> <script> const App = { data() { return { firstName: "Insoo", lastName: "Seo", }; }, methods: {}, computed: { fullName: { get() { return this.lastName + " " + this.firstName; }, set(newValue) { console.log(newValue); const names = newValue.split(" "); this.firstName = names[0]; this.lastName = names[names.length - 1]; }, }, }, }; const app = Vue.createApp(App).mount("#app"); </script>
1-5. watch 기본 사용법
감시하고 싶은 data를 watch에 등록하고, 해당 data의 변화가 있을 경우 watch 함수가 실행되어 특정 동작을 수행할 수 있다.
watch에 등록할 수 있는 data는 반드시 반응형 데이터(reactive)여야 한다.
- computed에서 등록한 data도 watch 가능
- watch함수의 인자는 각각 변경된Value, 변경전Value를 의미
firstName(newValue, oldValue)
watch 예시 코드
const App = { data() { return { firstName: "Insoo", lastName: "Seo", }; }, methods: {}, computed: { fullName: { get() { return this.lastName + " " + this.firstName; }, set(newValue) { console.log(newValue); const names = newValue.split(" "); this.firstName = names[0]; this.lastName = names[names.length - 1]; }, }, }, watch: { firstName(newValue, oldValue) { console.log("watch: ", this.firstName, newValue); }, fullName(){ console.log("watch ", this.fullName) } }, }
1-6. 참조형 데이터에서의 deep watch
- user data선언 → user데이터 watch → data속성 변경 → 감지실패 → handler,deep 적용 → data속성 변경 → 감지성공
- 배열데이터에도 적용해보기
- 객체 data의 속성만을 변경했을 경우, watch를 통해 변경을 감지할 수 없다!
handler()
,deep:true
옵션을 통해 객체데이터의 속성이 변경되어도 계속 감시하도록 설정 가능
immediate:true
를 통해, 초기화 시에도 watch로 추적가능
객체 및 배열의 속성변경 감지 예시 코드 by user, fruit
<div id="app"> <button @click="capitalize">클릭</button> <h1>{{user.name}}</h1> <h1 v-for="f in fruits">{{f}}</h1> </div> <script> const App = { data() { return { user: { name: "insoo", gender: "men" }, fruits: ["Apple", "Banana", "Cake"], }; }, methods: { capitalize() { this.fruits.forEach((fruit, idx) => { this.fruits[idx] = fruit.toUpperCase(); }); }, }, computed: {}, watch: { user: { handler() { console.log("watch: ", this.user); }, deep: true, }, fruits: { handler(newValue) { console.log("watch ", newValue); }, deep: true, immediate: true, }, }, };
2. 클래스와 스타일 바인딩
2-1. 다양한 방식으로 class 지정하기
0. msg data → title class 및 style 지정
1. v-bind:class 삼항연산자로 적용
2. 객체리터럴 방식으로 데이터기반 클래스 적용 → key value값 같도록하여 생략하기
→ 띄어쓰기로 class 구분하여 하나의 데이터 속성으로 여러개의 클래스 적용하기
3. classObject 형식의 data로 클래스 지정하기
→ classObject는 계산된 데이터로 만들어야함 → computed를 통해 classObject만들기
- v-bind:class 삼항연산자로 클래스 적용
<h1 v-bind:class="active ? 'active' : ''" class="title"> {{ msg }} </h1>
- 객체 리터럴 방식의 데이터 기반 클랙스 적용
<h1 :class="{active:active}" class="title"> {{msg}} </h1> // key-value 같다면 생략가능 <h1 :class="{active}" class="title"> {{msg}} </h1>
// 기호가 들어가는 class명의 경우 '' 콤마를 통해 string값을 명시해주어야한다. <h1 :class="{'title--small' : small}" class="title">{{msg}}</h1> // '' 콤마안에서 띄어쓰기를 통해 여러개의 클래스를 하나의 데이터 속성으로 적용 가능 <h1 :class="{'title--small active' : active}" class="title">{{msg}}</h1>
- 객체형식의 data로 클래스 지정하기
<h1 :class="classObject" class="title">{{msg}}</h1> const App = { data() { return { msg: "Hello Outwater", ..., classObject: { "title--small": true, active: true, }, }; },
주의
computed data는 함수형으로 작성
..., computed: { classObject() { return { "title--small": this.small, active: this.active, }; }, }, ...
2-2. 배열 리터럴로 클래스 지정하기
- 배열의 문자열을 통해 class 직접 등록하기
- ‘active’ , ‘title’ 클래스 등록
<h1 :class="['active', 'title']">{{msg}}</h1>
- data를 동적으로 연결하여 class 등록
data() { return { msg: "Hello Outwater", active: "active", title: "title", }; }, <h1 :class="[active, title]">{{msg}}</h1>
- method를 통해 동적으로 class 변경하기
@click
→changeTitle()
→data변경(title→ ‘title—small’)
→클래스 변경(title→ ‘title—small’)
<h1 :class="[active, title]" @click="changeTitle">{{msg}}</h1> const App = { data() { return { msg: "Hello Outwater", active: "active", title: "title", }; }, methods: { changeTitle() { this.title = "title--small"; }, },
2-3. 인라인 방식으로 클래스 지정하기
- 탬플릿 리터럴을 통한 인라인 스타일 적용
- method연결하여 style 동적으로 변경
- 템플릿 리터럴을 객체리터럴로 변경
- 하나의 요소에 여러개의 메소드 등록하기
- computed data (
styleObject()생성
)
- snakeCase와 camelCase 사용
- 여러개의 styleObject 적용하기
- 배열리터럴 방식으로 적용
- style =”[styleA, styleB]”