๐ ๋ชฉ์ฐจ
- Introduction
- reactive
- readonly
- isProxy
- isReactive
- isReadonly
- toRaw
- markRaw
- shallowReactive
- shallowReadonly
- Conclusion
- Reference
๐ Introduction
์๋ ํ์ธ์. ์ค๋์ vue3์ ์๋ก์ด reactive apis์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ํด๋น ์ฝ๋๋ ์ฌ๊ธฐ์ ํ์ธํ ์ ์์ต๋๋ค.๐
๐ reactive
reactive
๋ deep-copy
๋ object๋ฅผ ๋ฐํํฉ๋๋ค.
import { reactive } from 'vue';
export default {
name: 'App',
setup() {
const obj = reactive({ count: 0 });
const copy = obj.count;
const onClickButton = () => {
console.log(obj.count === copy.count); // false โญ๏ธ
};
return {
obj,
onClickButton,
};
},
};
</script>
์์ ์ฝ๋์ฒ๋ผ reactive๋ deep-copy๋ object๋ฅผ returnํฉ๋๋ค. ๋ฐ๋ผ์ obj.count์ copy.count๋ ์๋ก ๋ค๋ฅธ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๐ readonly
readonly
๋ object๋ฅผ readonly proxy๋ก ๋ deep-copy
object๋ฅผ ๋ฐํํฉ๋๋ค.(reactive, plain, ref ๋ชจ๋ ์ ์ฉ ๊ฐ๋ฅ)
import { readonly, reactive } from 'vue';
export default {
setup() {
const state = reactive({ count: 0 });
const readOnlyState = readonly(state);
const readOnlyCopy = readOnlyState.count;
const onClickPlus = () => {
state.count++;
readOnlyState.count++; // warning !!! โญ๏ธ
console.log(readOnlyState.count === readOnlyCopy); // false โญ๏ธ
};
return {
state,
readOnlyState,
onClickPlus,
};
},
};
์ ์ฝ๋์์ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ readonly
๋ฅผ ๋ฐ๊ฟ์ฃผ๊ฒ ๋๋ฉด warning์ ๋ฐ์ ์ํต๋๋ค. ๋ํ deep-copy๋ฅผ ์ง์ํ๊ธฐ ๋๋ฌธ์ readOnlyState.count์ readOnlyCopy์ ๊ฐ์ ์๋ก ๋ค๋ฆ
๋๋ค.
๐ isProxy
isProxy
๋ ํด๋น ๊ฐ์ฒด๊ฐ reactive
์ธ์ง readonly
์ธ์ง ํ๋ณํ๋ ํจ์ ์
๋๋ค.
import { readonly, reactive, isProxy } from 'vue';
export default {
setup() {
const state = reactive({ count: 0 });
const readOnlyState = readonly(state);
const readOnlyCopy = readOnlyState.count;
const onClickPlus = () => {
state.count++;
readOnlyState.count++; // warning !!!
console.log(readOnlyState.count === readOnlyCopy); // false
};
const onClickCheck = () => {
console.log('isProxy(state) -> reactive', isProxy(state)); // true
console.log('isProxy(readOnlyState) -> readonly', isProxy(readOnlyState)); // true
console.log('isProxy(readOnlyCopy)', isProxy(readOnlyCopy)); // false
};
return {
state,
readOnlyState,
onClickPlus,
onClickCheck,
};
},
};
๐ isReactive
isReactive
๋ isProxy
์๋ ๋ค๋ฅด๊ฒ reactive
๋ก ๋ง๋ค์ด์ง ๊ฐ์ฒด์ธ์ง ํ๋ณํฉ๋๋ค.
export default {
setup() {
const state = reactive({ count: 0 });
const readOnlyState = readonly(state);
const readOnly = readonly({ count: 0 });
const readOnlyCopy = readOnlyState.count;
const onClickCheckReactive = () => {
console.log('isReactive(state)', isReactive(state)); // true โญ๏ธ
console.log('isReactive(readOnlyState)', isReactive(readOnlyState)); // true โญ๏ธ
console.log('isReactive(readOnly)', isReactive(readOnly)); // false
console.log('isReactive(readOnlyCopy)', isReactive(readOnlyCopy)); // false
};
return {
state,
readOnlyState,
onClickCheckReactive,
};
},
};
์ด๋ ๊ฒ ๊ฐ์ด ๋์ค๊ฒ ๋ฉ๋๋ค. ์ ๊ธฐํ๊ฑด reactive
๊ฐ์ฒด๋ฅผ readonly
๊ฐ์ฒด๋ก ๋ฐ๊พธ์ด์ฃผ๋๊ฑด ์ฌ์ ํ true
๊ฐ์ด ๋์ค๊ฒ ๋ฉ๋๋ค.
๐ isReadonly
isReadonly
๋ ๊ฐ์ฒด๊ฐ readonly proxy์ธ์ง๋ฅผ ์๋ ค์ค๋๋ค.
export default {
setup() {
const state = reactive({ count: 0 });
const readOnlyState = readonly(state);
const readOnly = readonly({ count: 0 });
const readOnlyCopy = readOnlyState.count;
const onClickCheckReadonly = () => {
console.log('isReadonly(state)', isReadonly(state)); // false
console.log('isReadonly(readOnlyState)', isReadonly(readOnlyState)); // true
console.log('isReadonly(readOnly)', isReadonly(readOnly)); // true
console.log('isReadonly(readOnlyCopy)', isReadonly(readOnlyCopy)); // false
};
return {
state,
readOnlyState,
onClickCheckReadonly,
};
},
};
๐ toRaw
toRaw
ํจ์๋ reactive
๋ readonly
๊ฐ์ฒด๋ฅผ ๋ค์ ์์ํ๋ก ๋ณต๊ตฌํด ์ค๋๋ค.
export default {
setup() {
const state = reactive({ count: 0 });
const readOnly = readonly({ count: 0 });
const rawState = toRaw(state);
const copyRawStateCount = rawState.count;
const rawReadOnly = toRaw(readOnly);
const copyRawReadOnlyCount = rawReadOnly.count;
const onClick = () => {
// true โญ๏ธ
console.log('rawState.count === copyRawStateCount', rawState.count === copyRawStateCount);
// true โญ๏ธ
console.log('rawReadOnly.count === copyRawReadOnlyCount', rawReadOnly.count === copyRawReadOnlyCount);
};
return {
onClick
}
}
}
toRaw๋ก ๋ฐํ๋ ๊ฐ์ฒด๋ deep-copy
๊ฐ ๋์ง ์๋๊ฒ์ ์ ์ ์์ต๋๋ค.
๐ markRaw
markRaw
๋ reactive
ํ๊ฒ ํ๊ฑฐ๋ readonly
๊ฐ์ proxy๋ฅผ ์ฌ์ฉ ๋ชปํ๊ฒ ํฉ๋๋ค. ๋ฐํ ๊ฐ์ ๊ฐ์ฒด์
๋๋ค.
import { reactive, readonly, markRaw, isProxy } from 'vue';
export default {
setup() {
const foo = markRaw({});
const state = reactive(foo);
const readOnly = readonly(foo);
const onClick = () => {
console.log('isProxy(state)', isProxy(state)); // false โญ๏ธ
console.log('isProxy(readOnly)', isProxy(readOnly)); // false โญ๏ธ
};
return {
onClick
}
}
}
markRaw
๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๋ทฐ ์ปดํฌ๋ํธ๋ ๋ณต์กํ ํด๋์ค๋ฅผ reactiveํ์ง ์๊ฒ ๋ง๋ญ๋๋ค.
- ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ๋ํด proxy conversion์ ๋ง์ ํผํฌ๋จผ์ค๋ฅผ ๋์ ๋๋ค.
ํ์ง๋ง ์ด๋ฐ ์ํ์ฑ์ ๊ฐ์ง๊ณ ์๊ธด ํฉ๋๋ค.(Identity hazards)
const foo = markRaw({
nested: {}
})
const bar = reactive({
// foo๋ markRaw์ด์ง๋ง ๋ด๋ถ๋ ๊ทธ๋ ์ง ์์ต๋๋ค. โญ๏ธ
nested: foo.nested
})
console.log(foo.nested === bar.nested) // false
๐ shallowReactive
shallowReactive
๋ reactive๋ฅผ ์ง์ํ์ง๋ง deep reactive conversion์ ์ง์ํ์ง ์์ต๋๋ค.
import { shallowReactive, isReactive } from 'vue';
export default {
setup() {
const state = shallowReactive({ foo: 0, nested: { bar: 2 } });
const onClick = () => {
console.log('isReactive(state', isReactive(state)); // true
console.log('isReactive(state.foo)', isReactive(state.foo)); // false
console.log('isReactive(state.foo.nested)', isReactive(state.foo.nested)); // false
};
return {
onClick
};
}
};
๐ shallowReadonly
shallowReadonly
๋ readonly๋ฅผ ์ง์ํ์ง๋ง shallowReactive
์ ๋ง์ฐฌ๊ฐ์ง๋ก deep readonly conversion์ ์ง์ํ์ง ์์ต๋๋ค.
import { shallowReadonly, isReadonly } from 'vue';
export default {
setup() {
const state = shallowReadonly({ foo: 1, nested: { bar: 2 } });
const onClick = () => {
console.log('isReadonly(state)', isReadonly(state)); // true
console.log('isReadonly(state.foo)', isReadonly(state.foo)); // false
console.log('isReadonly(state.foo.nested)', isReadonly(state.foo.nested)); // false
};
return {
onClick
};
}
};
๐ Conclusion
์ค๋์ basic reactivity apis์ ๋ํด ์์๋ณด์์ต๋๋ค. ๊ทธ๋ผ ๋ค์ ํฌ์คํ ์์ ๋ง๋์~ ๐ค๐ป
๐ Reference
'Vue Study' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Vue3 - teleport (0) | 2020.11.08 |
---|---|
Vue3 - Provide/Inject (0) | 2020.11.04 |
Vue3 - LifeCycle (0) | 2020.10.30 |
Vue3 - computed and watch (0) | 2020.10.28 |
Vue3 - Refs (0) | 2020.10.27 |