반응형 데이터
반응형 데이터 ref
와 reactive
에 대하여
reactive와 ref
1. reactive
<h2>
객체나 배열과 같은 데이터를 반응형으로 만들려면 `reactive`를 사용해야한다
</h2>
<button v-on:click="increament">Click !! Count: {{ state.count }} </button>
setup(){
const state = reactive({
count: 0,
});
const increament = () => {
++state.count;
};
}

2. reactive - primitive
원시데이터(number, string)의 경우 reactive
로 감싸면 동작하지않는다
그이유는 object type만 받기때문이다.
reactive <type of Object>
let primitiveData = reactive('테스트데이터');
const increamentPrimitiveData = () => {
primitiveData = primitiveData + '!';
console.log(primitiveData);
};
<h2>원시데이터는 reactive를 사용하면 문제가 생긴다</h2>
<button @click="increamentPrimitiveData">
primitiveData = {{ primitiveData }} , 클릭하면 !가 붙는다.
</button>

console
테스트데이터!
테스트데이터!!
테스트데이터!!!
3. wrapping해서 reactive사용하여 primitive Data 사용
이를 해결하기 위해서는 Object형으로 한번더 감아서 선언해야한다.
let primitiveDataByObject = reactive({
value: '객체로 한번 더 감싼 원시데이터입니다',
});
const increamentPrimitiveDataByObject = () => {
primitiveDataByObject.value = primitiveDataByObject.value + '!';
};
<h2>그래서 객체로 사용해야한다.</h2>
<button @click="increamentPrimitiveDataByObject">
클릭하면 {{ primitiveDataByObject.value }} 에서 !가 붙습니다.
</button>

4. refs
결국 위와 같이 Wrapping을 이용한 Object
인 refs
가 나타난다
let refData = ref('refData입니다');
const increamentRefData = () => {
refData.value = refData.value + '!'; //value를 붙여야함
};
<h2>
이것을 간단하게 만든 것이 ref이다. ref의 내부를 보면 결국 ref는
object인것을 알 수 있다.
</h2>
<button @click="increamentRefData">
클릭하면 {{ refData }} 에서 !가 붙습니다. <!-- {{}} 안에는 value를 안붙어도 알아서 value가 붙은걸로 인식한다.-->
</button>

ref와 reative 동시사용
1. reactive의 object 필드값으로 ref를 사용
ref
변수를 reactive
의 필드값으로 사용하면 .value
를 붙이지 않아도 된다.
const count = ref(0);
const countState = reactive({
count, //key value가 서로 같으면 생략가능 = count: count,
});
count.value++;
count.value++;
countState.count++;
//countState.count.value++; error
console.log('ref를 reactive-object에서 사용할땐 value를 붙이지 않는다');
console.log('count.value', count.value);
console.log('countState.count.value', countState.count.value); //undefined가 뜬다
console.log('countState.count', countState.count);
console
ref를 reactive-object에서 사용할땐 value를 붙이지 않는다
count.value 3
countState.count.value undefined
countState.count 3
결국 ref
변수가 필드로 사용되건, 일반 변수가 필드로 사용되건 .value
가 사용하면 안된다.
cf) ref와 reactive type
console.log('count: ', count);
console.log('countState:', countState);

reactive
안에서의 property를 ref
로 선언했어도 countState.count
처럼 표현식으로 사용하면 반응형이 사라진다.
위에서 console.log(countState.count)
를 확인했을때 refImpl
과 관련된건 나타나지않은 것을 확인 할 수 있다.
하지만 {{ countState.count }}와 같이 템플릿 문법안에서는 정상적으로 반응형이 유지된다.
2. reactive의 array 필드값으로 ref를 사용
Array
의 원소값으로 ref
를 사용하면 value
를 사용해야한다
//Array의 원소값으로 ref를 넣을 때
const refData2 = ref('ref content');
const reactiveData2 = reactive([refData2]);
console.log(reactiveData2[0].value);
console.log(reactiveData2[0]); //ref로 반환
//Array의 원소값으로 일반 string을 넣을 때
const reactiveData2_1 = reactive(['hello']);
console.log('reactiveData2_1[0].value', reactiveData2_1[0].value);
console.log('reactiveData2_1[0]', reactiveData2_1[0]);

반응성
1. reactive의 필드값을 다른 곳에서 대입하여 사용하면 반응성을 잃는다
const reactiveData3 = reactive({
testData: 'hello',
testData2: 'World',
});
let normalData = reactiveData3.testData; //반응성이 없는 데이터 normalData
const function1 = () => {
normalData = normalData + '!';
console.log('normalData', normalData);
console.log('reactiveData3.testData', reactiveData3.testData);
}
const function2 = () => {
reactiveData3.testData = reactiveData3.testData + '!';
console.log('normalData', normalData);
console.log('reactiveData3.testData', reactiveData3.testData);
}
<h2>반응형객체의 필드를 변수명에 대입하여 사용하면 반응형이 먹히지않는다</h2>
<button @click="function1">reactiveData3.testData: {{ reactiveData3.testData }}, normalData: {{ normalData }} </button>
<button @click="function2">reactiveData3.testData: {{ reactiveData3.testData }}, normalData: {{ normalData }} </button>

function1 버튼을 4번 클릭시
normalData hello!
reactiveData3.testData hello
normalData hello!!
reactiveData3.testData hello
normalData hello!!!
reactiveData3.testData hello
normalData hello!!!
reactiveData3.testData hello
console
에는 정상적으로 !
가 추가된다

function2 버튼을 4번 클릭시
normalData hello!!!!
reactiveData3.testData hello!
normalData hello!!!!
reactiveData3.testData hello!!
normalData hello!!!!
reactiveData3.testData hello!!!
console
에는 정상적으로 !
가 추가된다

2. 반응성 유지:toRef
반응성을 유지하기위해서는 toRef
를 사용한다
const reactiveData4 = reactive({
testData: 'hello',
testData2: 'World',
});
let helloData = toRef(reactiveData4, 'testData'); //toRef를 쓰면 Ref형이된다.
const function3 = () => {
helloData.value += '!';
console.log('helloData.value', helloData.value);
console.log('reactiveData4.testData', reactiveData4.testData);
}
<h2>toRef를 사용하여 해결한다</h2>
<button @click="function3"> {{ reactiveData4.testData }} , {{ helloData }} </button>

ReadOnly
복제를 해서 사용할 경우
const original = reactive({
count: 0,
});
const copy = original; //필드값을 전달할때는 반응성을 잃지만 객체그대로 보내면 반응성 유지
const changeOriginal = () =>{
copy.count++;
}
<h2>readOnly 사용안할때</h2>
<button @click="changeOriginal"> {{ original }}, {{ copy }} </button>

readonly
const original = reactive({
count: 0,
});
const copy2 = readonly(original);
const changeOriginal2 = () =>{
copy2.count++;
}
<h2>readOnly 사용</h2>
<button @click="changeOriginal2">, </button>


댓글 쓰기