반응형 데이터
반응형 데이터 refreactive에 대하여

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;
  };
}
image
누르면 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>
image
클릭해도 무반응



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>
image
클릭해면 !가 붙는다



4. refs

결국 위와 같이 Wrapping을 이용한 Objectrefs가 나타난다

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



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);
image
ref와 reactive를 콘솔에 찍었을때



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]); 
image
ref와 reactive를 콘솔에 찍었을때



반응성

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>
image
아무것도 클릭안한 처음상태



function1 버튼을 4번 클릭시

normalData hello!
reactiveData3.testData hello
normalData hello!!
reactiveData3.testData hello
normalData hello!!!
reactiveData3.testData hello
normalData hello!!!
reactiveData3.testData hello

console에는 정상적으로 !가 추가된다

image
값이 전부 반응이 없다.



function2 버튼을 4번 클릭시

normalData hello!!!!
reactiveData3.testData hello!
normalData hello!!!!
reactiveData3.testData hello!!
normalData hello!!!!
reactiveData3.testData hello!!!

console에는 정상적으로 !가 추가된다

image
클릭하면 반응성데이터에만 !가 붙는다



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>
image
클릭하면 모든 데이터에 !가 붙는다



ReadOnly

복제를 해서 사용할 경우

const original = reactive({
  count: 0,
});
const copy = original; //필드값을 전달할때는 반응성을 잃지만 객체그대로 보내면 반응성 유지
const changeOriginal = () =>{
  copy.count++;
}
<h2>readOnly 사용안할때</h2>
<button @click="changeOriginal"> {{ original }}, {{ copy }} </button>
image
클릭하면 모든 데이터가 반응한다



readonly

const original = reactive({
  count: 0,
});
const copy2 = readonly(original);
const changeOriginal2 = () =>{
  copy2.count++;
}

<h2>readOnly 사용</h2>
<button @click="changeOriginal2">, </button>
image
클릭하면 데이터에 반응이 없다.



image
아래와 같은 경고문이 뜬다



댓글 쓰기