reactive()
함수를 사용할 수 있습니다.<template>
<div>
<button v-on:click="state.count++">Click {{ state.count }}</button>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
const state = reactive({
count: 0,
});
return {
state,
};
},
};
state
가 아닌 state.count
로 출력하는 이유는 state
객체가 가지고 있는 속성이기 때문에 .
을 이용해 count
를 접근해야 한다.메서드로 빼보자
<template>
<div>
<button v-on:click="increment">Click {{ state.count }}</button>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
const state = reactive({
count: 0,
});
const increment = () => {
state.count++;
};
return {
state,
increment,
};
},
};
<template>
<div>
<button v-on:click="increment">Click {{ state.count }}</button>
<br /><br />
<button v-on:click="increment">Click {{ state.deep.count }}</button>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
const state = reactive({
count: 0,
deep: {
count: 0,
},
});
const increment = () => {
state.count++;
state.deep.count++;
};
return {
state,
increment,
};
},
};
reactive
함수는 객체나 배열과 같은 레퍼런스 타입을 반응형 객체로 만들 수 있다.<template>
<div>
<p>{{ message }}</p>
<!-- 반응형 동작 확인 -->
<button v-on:click="addMessage">Click!</button>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
// const는 상수기 때문에 let으로 변경
let message = reactive("Hello Vue!");
const addMessage = () => {
message = message + "!";
};
return {
message,
addMessage,
};
},
};
여기서 중요한 부분🚨
reactive함수
- 객체나 배열 레퍼런스 타입(Reference type = 참조타입)을 반응형으로 만듦
ref함수
- string, number, boolean 프리미티브 타입(Primitive type = 원시타입)을 반응형으로 만듦
콘솔로 찍어보면
import { reactive } from "vue";
export default {
setup() {
// const는 상수기 때문에 let으로 변경
let message = reactive("Hello Vue!");
const addMessage = () => {
message = message + "!";
};
console.log("message", message);
console.log("message", typeof message);
return {
message,
addMessage,
};
},
};
message
가 string으로 보인다. JavaScript는 값 자체를 변경하기 때문이다. 템플릿의 message
와 선언한 message
의 값이 메모리에 둘다 저장되어야 하지만 값을 변경해버리기 때문에 당연한 결과다.하지만 리액티브 함수로 프리미티브 타입을 다룰 수 있다. 이미 약속된 속성을 선언하고 그 안에 선언하면된다.
<template>
<div>
<p>{{ message.value }}</p>
<!-- 반응형 동작 확인 -->
<button v-on:click="addMessage">Click!</button>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
// const는 상수기 때문에 let으로 변경
// 이렇게 약속된 속성을 사용하면 된다.
// 그리고 속성을 연결해줘야하니 .value가 붙는다
let message = reactive({
value: "Hello Vue!",
});
const addMessage = () => {
message.value = message.value + "!";
};
console.log("message", message.value);
console.log("message", typeof message.value);
return {
message,
addMessage,
};
},
};
ref()
함수를 제공한다.
ref()
함수는 프리미티브 타입의 반응형 데이터를 만들 때 사용하는 함수다.reactive()
함수는 객체타입에만 동작한다. 그래서 기본타입(number, string, boolean)을 반응형으로 만들고자 할 때ref()
메소드를 사용할 수 있다.ref()
메소드는 변이가능한 객체를 반환하는데 이 객체 안에는value
라는 하나의 속성만 포함되어 있고value
값은ref()
메소드에서 매개변수로 받는 값을 갖고 있다. 이 객체는 내부의value
값에 대한 반응형 참조(reference) 역할을 한다. 그래서ref()
함수다.
import { ref } from "vue";
export default {
setup() {
const count = ref(0);
console.log(count.value); //0
count.value++;
console.log(count.value); //1
return {
ref,
};
},
};
ref()
함수를 넣으면 어떻게 될까?import { reactive, ref } from "vue";
export default {
setup() {
//ref -> Object
const count = ref(0);
const state = reactive({
count,
});
console.log(count.value);
console.log("state.count", state.count);
//ref -> Array
const message = ref("hello");
const arr = reactive([message]);
console.log("arr[0]", arr[0].value);
return {};
},
};
<template>
<div>
<p>author: {{ author }}</p>
<p>title: {{ title }}</p>
</div>
</template>
import { reactive } from "vue";
export default {
setup() {
const book = reactive({
author: "Vue Team",
year: "2020",
title: "Vue 3 Giude",
descriprtion: "당신은 읽습니다.",
price: "무료",
});
const { author, title } = book;
return { author, title, book };
},
};
author
, title
의 경우에는 수정 아이콘이 보이지 않는다. 이유는 구조분해 할당을 하게 되면 author
, title
변수에 속성이 재할당 되었다고 보면된다. 그래서 반응성을 잃어버린 그냥 스트링이된다. console.log(typeof author);
로 속성을 찍어보면toRef
와 toRefs
다.import { reactive } from "vue";
export default {
setup() {
const book = reactive({
author: "Vue Team",
year: "2020",
title: "Vue 3 Giude",
descriprtion: "당신은 읽습니다.",
price: "무료",
});
const { author, title } = toRefs(book);
return { author, title, book };
},
};
toRefs
를 사용하게되면 book에 있는 속성과 구조 분해된 상태가 서로 동기화가 된다. book에 있는 속성을 변경하면 구조분해 할당된 부분도 변경이된다. 그리고 구조분해 할당이 아닌 객체에서 하나만 가져오고 싶다면 toRef
를 사용하면된다.import { reactive, toRef } from "vue";
export default {
setup() {
const book = reactive({
author: "Vue Team",
year: "2020",
title: "Vue 3 Giude",
descriprtion: "당신은 읽습니다.",
price: "무료",
});
const author = toRef(book, "author");
const title = toRef(book, "title");
return { author, title, book };
},
};
reactive
) 객체에서 속성을 가져오고 싶을때는 사용하면된다.Provide/Inject
로 주입된 반응형 객체를 갖고 있을 때, 우리는 그것이 주입된 곳에서는 해당 객체가 변이되는걸 막고자 할 것입니다. 이렇게 하려면 원래 객체에 대한 읽기 전용 프록시를 생성하면된다.import { reactive, readonly } from "vue";
export default {
setup() {
//원본의 반응형 객체
const original = reactive({
count: 0,
});
//복사본
const copy = readonly(original);
//이렇게 복사본을 변경하려고하면 경고가 뜬다.
copy.count++;
original.count++;
console.log(original.count);
console.log(copy.count);
return {
original,
copy,
};
},
};
ref
와 함께 .value
를 사용해야 하는 것은 Javascript의 언어 제약으로 인한 단점이다.(프리미티브 타입을 레퍼런스 타입으로 다루기 때문이다.) 그러나 compile-time transforms
을 사용하면 적절한 위치에 .value
를 자동으로 추가하여 개선할 수 있다.