벨로그 아프지 마시고
Vue 2일차 Computed, Watch 그리고 클래스와 스타일 동적 바인딩
자바스크립트 데이터의 불변성과 가변성, vite 포트 설정, JSON에는 주석이 안된다.
슬슬 어려워지는 VUE 2일차
computed는 캐싱이라는 기능을 통해서 기억을 한다. 반복적으로 출력해도 연산을 낭비하지 않는다.
아래의 코드에서 double을 단순히 메서드에서 출력한다면 연산을 4번 해야한다. 하지만 computed를 사용하면 연산된 값을 캐싱을 통해서 기억하고 있기 때문에 반복해서 사용해도 전체 연산은 1번밖에 하지 않는다.
<body>
<div id="app">
<!-- 이중 중괄호 구문에서 `보간`하고 있다. -->
<h1>{{ count }}</h1>
<!-- 표현식을 여러번 작성했다. -->
<!-- 단순해서 문제가 없지만 복잡하다면 효율적인 코드는 아니다. 그때 사용하는 것이 함수 -->
<!-- <h2>{{ count * 2 }}</h2> -->
<!-- 위 코드를 아래와 같이 고칠 수 있다. -->
<!-- <h2>{{ double() }}</h2> << 메서드에서 쓴거는 이렇게 써야한다. -->
<h2>{{ double }}</h2>
<h2>{{ double }}</h2>
<h2>{{ double }}</h2>
<h2>{{ double }}</h2>
</div>
<script>
const App = {
data() {
return {
count: 3,
};
},
computed: {
// 여기의 double()은 데이터로 취급되지 더 이상 함수가 아니다.
double() {
return this.count * 2;
},
},
// methods: {
// double() {
// return this.count * 2;
// },
// },
};
const vm = Vue.createApp(App).mount("#app");
</script>
실전 created 사용, 그리고 computed에서의 데이터 가공
// created는 애플리케이션이 생성된 직후, DOM접근은 불가능 하지만 위에 있는
// todos데이터에는 접근이 가능한 상태이다.
created() {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((result) => {
console.log(result);
this.todos = result;
});
},
// 캐싱 기억해라!
computed: {
upperTodos() {
return this.todos.map((todo) => ({
...todo,
title: todo.title.toUpperCase(),
}));
},
계산된 데이터는 의존하는 데이터에만 포커싱을 한다. 예를 들어 아래와 같은 코드에서 this.user.age를 조작한다고 하면 전체 객체를 바꾸는 것이 아닌 해당 데이터만 바꾸는 방식으로 진행된다.
const App = {
data() {
return {
user: {
name: "Leon",
age: 22,
email: "123@abc.com",
},
};
},
computed: {
// 계산된 데이터는 의존하는 데이터에만 포커싱을 할 수 있다.
// 관리하고 이해하기 용이하다.
doubleAge() {
console.log(`Double!`);
return this.user.age * 2;
},
upperName() {
return this.user.name.toUpperCase();
},
},
};
computed 함수는 따로 바꿀 수 없다. 일반적인 할당 연산자로는 변경이 불가능하고 setter의 개념으로 접근해서 바꿔줄 수 있다.
computed: {
// 아래와 같은 방식이 아니라 객체처럼 선언해서 지정해야 한다.
// fullName() {
// // 이건 일종의 getter이다
// return `${this.firstName} ${this.lastName}`;
// },
// 이렇게 객체처럼 선언해서 getter, setter을 따로 선언 해주어야한다.
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(newValue) {
// console.log(newValue); // Jacob Smith
const names = newValue.split(" ");
this.firstName = names[0];
this.lastName = names[names.length - 1]; // 만약 middleName이 있다고 하면 그걸 없애겠지?
// this.lastName = names[1];
},
},
},
상태의 변경을 감시하고 특정 동작을 수행하는 데 사용하는 watch 문법
아래와 같이 사용할 수 있다.
watch: {
// 이미 선언해서 사용하는 반응형 데이터여야한다.
firstName(newValue, oldValue) {
// 파라미터로 변한 값을 감지할 수 있다.
console.log(newValue);
console.log("watch:", newValue, oldValue);
},
fullName() {
console.log("watch:", this.fullName);
},
},
하지만 객체나 배열 구조를 감지할 때는 위와 같은 방식으로는 감지가 불가능하고 deep이라는 키워드를 사용해야한다.
또한 immediate 키워드는 변경 뿐만 아니라 초기화 되었을 때(최초 실행에서)도 실행된다.
watch: {
// 속성만 바꾸면 watch 옵션이 모르고, 전체 데이터를 바꿔주어야 감시 로직이 동작한다.
// 그때 사용하는 옵션이 deep이다.
// user(newValue, oldValue) {
// console.log(newValue, oldValue);
// },
user: {
handler(newValue, oldValue) {
console.log(newValue, oldValue);
},
deep: true,
},
// 아래와 같이만 선언하면 감지가 안된다.
// fruits(n, o) {
// console.log(this.fruits);
// },
// 이렇게 선언해서 deep:true를 선언해줘야 감지가 된다.
fruits: {
handler(n, o) {
console.log(this.fruits);
},
deep: true,
immediate: true,
},
},
HTML태그에 클래스와 스타일을 지정할 때 VUE의 바인드를 이용해서 동적으로 데이터를 바인딩 해줄 수 있다.
다만 값을 동적으로 바꿀 때 methods를 통해 값을 바꾸고 단순히 연결하는 것이 아니라 계산된 데이터를 연결해야하기 때문에 computed에 함수를 선언해서 클래스/스타일에 연결하는 방식으로 사용한다.
<div id="app">
<button @click="toggle">Toggle</button>
<!-- 아래와 같이 클래스를 적용하는 방식도 있다. -->
<!-- 객체 데이터에서 속성과 값의 이름이 같으면 생략 가능 -->
<!-- 아래와 같이 클래스 추가 가능, 따옴표 주의, 띄어쓰기 사용 가능 -->
<h1 :class="classObject" class="title">{{ msg }}</h1>
</div>
<script>
const App = {
data() {
return {
msg: "Hello Vue!",
active: false,
small: true,
// 하지만 이러한 방식은 메서드로 갱신하는데
// 반응형 데이터를 기준으로 계산된 데이터로 만들어야한다.
// classObject: {
// active: false,
// "title--small color--orange": true,
// },
};
},
computed: {
classObject() {
return {
active: this.active,
"title--small color--orange": this.small,
};
},
},
methods: {
toggle() {
this.active = !this.active;
this.small = !this.small;
},
},
};
const vm = Vue.createApp(App).mount("#app");
</script>
스타일도 위 방식과 동일하고 특이한 점은 카멜케이스에서 대쉬케이스로 알아서 바꿔준다는 점이다.
<body>
<style></style>
<div id="app">
<!-- 카멜케이스에서 대쉬케이스로 알아서 바꿔준다 -->
<!-- <h1 :style="{ color, backgroundColor }">Hello Vue!</h1> -->
<h1 :style="[titleStyleObject, styleObject]">Hello Vue!</h1>
</div>
<script>
const App = {
data() {
return {
styleObject: {
color: "royalblue",
backgroundColor: "orange",
},
titleStyleObject: {
fontSize: "40px",
fontWeight: "bold",
color: "brown",
},
};
},
computed: {},
methods: {},
};
const vm = Vue.createApp(App).mount("#app");
</script>
</body>
어제 강의 수강 중 궁금한 점이 생겨서 일차적으로 1,2차 팀원들에게 공유해서 해결해보려 했으나 해결되지 않아 담당 강사님이신 영웅님께 질문을 드렸다.
나도 그렇고 우리의 주된 의심은 VUE의 가상 돔이 원인이지 않을까 하는 생각을 가지고 있었는데 막상 영웅님의 답변은 뜻밖이였다.
자바스크립트의 현상에 관한 문제였고 참조형과 원시형에 대한 이해가 없음에도 불구하고 왜 저런 현상이 발생하는 지는 그렇구나 정도로 이해는 됐다. 하지만 영웅님이 추가적으로 언급해주신 자바스크립트 데이터의 불변성과 가변성
에 대해서 학습하고 확실히 이해하고 짚고 넘어가고자 한다.
10ms의 순발력.... 보통 200~250ms 순발력이 나오는데 분발해야겠다(?)
개발 환경에서 즉석으로 모바일과 태블릿, 맥북에서 확인하려고 로컬 네트워크에서 개발 환경을 즉시 접속하고자 하였다. 기존에 Default 설정은 5173인가..? 포트로 열리던데 내부 로컬 네트워크에서 접속을 하려 하니 포트가 안 열렸는지 TIMEOUT이 발생했다.
해결 방법은 2가지이다. 해당 포트의 권한을 설정해서 로컬 네트워크 접속을 허용하던가 그냥 이미 잘 사용하고 있는 3000번 포트로 열어버리는 것이다.
나는 후자를 선택했고 검색을 해본 결과 package.json
에 script
에서 기존에 dev 코드를 "dev":"vite --host 0.0.0.0 --port 3000"
으로 바꿔주어서 해결했다.
그리고 이 과정에서 안 것인데...
나는 항상 혹시를 대비해서 이전의 코드를 주석처리 하는 경우가 많다. 근데 JSON에서는 주석이 안되더라... 부끄럽지만 처음 알았다.
여전히 일정관리에 어려움을 겪고 있다. 더 이상 입사지원서도 내지 않고 있는데 이미 진행하고 있는 일정들에서 많은 어려움이 있다. 요즘은 그래서 뭔가 벽에 막힌 듯 일정량의 공부만 하고 그 이상을 진행하지 못하는데 어찌 해결할지 고민이다. 더 해야 실력이 늘 것 같은데..
오늘은 또 다가온 생일이였는데 생일을 체감한건 가족들과의 저녁식사 시간이였다. 몇 가지 선물이 택배로 왔는데 아직 뜯지도 못하고 상자채로 쌓여있다. 특히 모니터는 얼렁 뜯어서 쓰고 싶은데 시간이 없다..
쉽지 않지만 내일도 화이팅🔥
TIL 작성 소요시간 약 32분