์
๋ฐ์ดํธ:
๋๊ตฐ๊ฐ ์ด ๊ธฐ๋ฅ์ ํ์๋ก ํ๋ ๊ฒฝ์ฐ ์ ์ ํ ๊ถ๊ณ ์ ๋ชจ๋ ๊ฒ์ ํฌํจํ์ฌ vue-nonreactive ๋ก ์ถ์ํ์ต๋๋ค.
Vue์ ๊ด์ฐฐ ๋ฐ ๊ฑท๊ธฐ๋ฅผ ๋นํ์ฑํํด์ผ ํ๋ ๋น์ผ๋ฐ ๋ชจ๋ธ์ด ์์ต๋๋ค. ์๋ ๊ด๋ จ ์์์ ์กฐํํ ์ ์๋๋ก ์บ์์ ์ก์ธ์คํ ์ ์๋ ์์ ๋ชจ๋ธ์ ๋๋ค. ์ด๋ก ์ธํด ์บ์์ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์๋๊ณ (์๋ง๋ ๋นํจ์จ์ ์) ๋ค๋ฅธ ์ฝ๋์์ ์ถ๊ฐ ์ํธ ์์ฉ์ด ๋ฐ์ํฉ๋๋ค. ํ์ฌ ์บ์์ ๋๋ฏธ ๊ด์ฐฐ์๋ฅผ ์ค์ ํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋ญ๊ฐ ๋น์ทํ...
import get from 'http';
import Resource from 'resource';
new Vue({
data: { instance: {}, },
ready() { this.fetch(); },
methods: {
fetch() {
const Observer = Object.getPrototypeOf(this.instance.__ob__).constructor;
get('/api/frobs')
.then(function(data) {
// initialize Resource w/ JSON document
const resource = new Resource(data);
// Protect cache with dummy observer
resource.cache.__ob__ = new Observer({});
this.instance = resource;
});
},
},
});
์ด๊ฒ์ ์๋ํ์ง๋ง
Observer
ํด๋์ค๋ฅผ ์ง์ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฏ๋ก ์ด๋ฏธ ๊ด์ฐฐ๋ ๊ฐ์ฒด๊ฐ ํ์ํฉ๋๋ค.์ ์:
Vue์ ๊ด์ฐฐ/๋ณดํ์ ๋ช
์์ ์ผ๋ก ๋นํ์ฑํํ๋ ๊ณต์ ๋ฐฉ๋ฒ์ ์ถ๊ฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์๊ณผ ๊ฐ์...
const someThing = {
nestedThing: {},
};
// make entire object non-reactive
Vue.nonreactive(someThing);
// make nested object non-reactive
Vue.nonreactive(someThing.nestedThing);
vm.$set('key.path', someThing);
๊ณ ๋ ค ์ฌํญ:
``` js
vm.$set('a', Vue.nonreactive({});
//์ ๋ค๋ฅด๋ค..
vm.$set('์', {
someKey: Vue.nonreactive({}),
});
```
``` js
// ์ค๋ฅ
Vue.nonreactive(vm.$data.a)
// ์ ํจํ
Vue.nonreactive(_.clone(vm.$data.a));
```
๊ทํ์ ๊ฒฝ์ฐ์๋ Object.freeze()
๊ฐ ์๋ํ์ง ์์ต๋๊น? v1.0.18๋ถํฐ ์ง์๋ฉ๋๋ค.
data
์ ๊ฐ์ฒด/๋ฐฐ์ด์ ๋ํ ๊ด์ฐฐ์ ๊ฑด๋๋ฐ์ด์ผ ํ๋ ๊ฒฝ์ฐ Object.freeze()
๋ฅผ ์ฌ์ฉํ์ญ์์ค.data
์ ์ก์ธ์คํ๊ธฐ ์ํด this
. created()
hook์ this
์ ๊ฐ๋จํ ๋ถ์ด๋ฉด ์ ํ ๊ด์ฐฐ๋์ง ์์ต๋๋ค.Object.freeze
๋ ์ฌ๊ธฐ์์ ์๋ํ์ง ์์ต๋๋ค. ์บ์๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์
๋ฐ์ดํธ๋ฉ๋๋ค.๊ทธ๋ฐ ๋ค์ ๋ชจ๋ธ ๋์์ธ์ ์ฌ๊ณ ํด์ผ ํ ๋์ ๋๋ค. ์ ๊ทธ๋ฐ ๊ฒ๋ค์ ๊ด์ฐฐํ ๋์ ์๋์ ๋ดํฌํฉ๋๊น?
์บ์๋ ๊ด๋ จ ๋ฆฌ์์ค๋ฅผ ๋์ ์ผ๋ก ์กฐํํ๋ ๋ฐ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
์๋ฅผ ๋ค์ด Author
๋ฐ Post
๋ชจ๋ธ์ด ์์ ์ ์์ต๋๋ค. ์์ฑ์ ๋ชจ๋ธ์ ๊ฒ์๋ฌผ ๋ชจ๋ธ์ ๋ํด posts
๋ผ๋ ๋๋ค ๊ด๊ณ๋ฅผ ์ ์ํฉ๋๋ค. ์ด ์บ์์๋ ๊ด๊ณ ๋ฐ์ดํฐ์ ๊ด๋ จ ์ปฌ๋ ์
์ด ํฌํจ๋ฉ๋๋ค.
author.posts๋ฅผ ํธ์ถํ๋ฉด ์บ์์์ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ต๋๋ค.
์๋์ ์ผ๋ก Vue๋ ์์ฒด ์ํ ๋ณ๊ฒฝ ๋ฉ์ปค๋์ฆ์ด ์๋ ๋ณต์กํ ๊ฐ์ฒด๋ฅผ Vue ์ธ์คํด์ค์ data
๋ฃ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค. Vue ์ธ์คํด์ค์ ๊ด์ฐฐ๋ ๋ฐ์ดํฐ๋ก ์์ ์ํ ๋ง ๋ฃ์ด์ผ ํฉ๋๋ค. ์ด ์ํ๋ ์ํ๋ ๋๋ก ์กฐ์ํ ์ ์์ง๋ง ์ด๋ฌํ ์กฐ์์ ๋ด๋นํ๋ ๊ฐ์ฒด๋ Vue ์ธ์คํด์ค ์ํ์ ์ผ๋ถ๊ฐ ์๋์ด์ผ ํฉ๋๋ค.
์ฒซ์งธ, ๋ช ํํ ์ง๋ฌธ - ์์ ์ํ ๋ ์ ํํ ๋ฌด์์ ์๋ฏธํฉ๋๊น? ๋ ๊ฐ์ง ์ ํ์ ์ํ๊ฐ ์์ต๋๋ค.
ํ์ง๋ง ์ด์จ๋ :
๊ณต์ ํด. ๋ชจ๋ธ์ ํ์คํ '๋ณต์ก'ํ๋ฏ๋ก ์ด ์์ฒญ์ ํ์ฌ ๋ชจ๋ฒ ์ฌ๋ก์ ์๋ฐฐ๋ฉ๋๋ค. ๋ํ ๋ด ์ด๊ธฐ ์๋ ๊ทธ๋ค์ง ์ข์ง ์์ต๋๋ค. ๊ด์ฐฐ์ ๋นํ์ฑํํ๋ ๋ฐ ํจ๊ณผ๊ฐ ์์์ต๋๋ค. ์ด๊ฒ์ ๊ฐ๋ฅํ ์ฌ์ฉ๋ฒ์ด ์๋ ํ์ฌ ์ค์ ์ ๋ ์ ๋ํ๋
๋๋ค.
<!-- layout -->
<post :post="post"></post>
<author :author="author" ><author>
<comments :comments="comments"></comments>
import post from 'components/post';
import author from 'components/author';
import comments from 'components/comments';
/* post = {
* template: '...'
* props: ['post'],
* data: () => {collapsed: false},
* ...
* }; */
new Vue({
el: 'body',
data() {
instance = postStore.fetch({include: ['author', 'comments.author']})
Vue.nonreactive(instance.cache)
return {post: instance, },
},
components: {
post,
author,
comments,
},
...
});
๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌ์ฑ ์์๋ฅผ ๋ ์ด์์์ ๋ฐฐ์นํ๊ณ ๊ด๋ จ ๊ตฌ์ฑ ์์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ฐ์ธ๋ฉํ๋ ๋ถ๋ชจ ๋ทฐ๊ฐ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ปจํ ์คํธ๋ง๋ค ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์์ ๊ตฌ์ฑ ์์๋ ์์ฒด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, _user์_ ๋๊ธ ๋ชฉ๋ก๊ณผ _post์_ ๋๊ธ ๋ชฉ๋ก.
๋ชจ๋ธ์ ๊ด๋ จ ๊ฐ์ฒด๊ฐ ์ค์ฒฉ๋์ง ์๊ณ ( {post: {author: {}, comments: []}}
) ๋์ ์บ์์์ ์กฐํ๋๋ค๋ ์ ์ ์ ์ธํ๊ณ ๋ ์๋นํ '๋ฉ์ฒญํ' ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, post.comments[2].author
๋ post.author
์ ๋์ผํ ๊ฐ์ฒด์ผ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์์ฑ์ ๊ฐ์ฒด์ ๋ณต์ฌ๋ณธ์ด ์ฌ๋ฌ ๊ฐ ์๋ ๋์ ์บ์์์ ์กฐํ๋ ๋ณต์ฌ๋ณธ ํ๋๋ง ์์ต๋๋ค. ์์ ๋ด์ฉ์๋ ๋ณํ์ด ์์ต๋๋ค. ๋ชจ๋ ๋ฐ์ดํฐ๋ ์ด๊ธฐ ๊ฐ์ ธ์ค๊ธฐ์์ ๋ง๋ค์ด์ง๋๋ค.
๋ํ ์์ฒญ์ด ๋ ์ด์ ๊ด๋ จ์ด ์๋ค๋ ๊ฒ์ ์๋์ง๋ง ๋์์ '๋น๊ณต๊ฐ' ๊ฐ์ฒด ๊ตฌ์ฑ์์ ๊ด์ฐฐํ์ง ์๋ ๊ฒ์ผ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์ ํ ๋จ์ผ ๋๋ ์ด์ค ๋ฐ์ค์ด ์๋ ๊ตฌ์ฑ์์ผ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ๋จ์ ์ ๋ณ๊ฒฝ ์ฌํญ์ ๊นจ๋ ๊ฒ์ ๋๋ค.
๋๊ตฐ๊ฐ ์ด ๊ธฐ๋ฅ์ ํ์๋ก ํ๋ ๊ฒฝ์ฐ ์ ์ ํ ๊ถ๊ณ ์ ๋ชจ๋ ๊ฒ์ ํฌํจํ์ฌ vue-nonreactive ๋ก ์ถ์ํ์ต๋๋ค.
@rpkilby ๊ณต์
@rpkilby ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํ๊ณ ๊ด์ฐฐ ๊ฐ๋ฅ/๋ฐ์์ฑ์ ์ ๊ฑฐํฉ๋๋ค.
var newObj = JSON.parse(JSON.stringify(obj))
"์ํ" ๋ฐฐ์ด์ ์ ์งํ๊ณ vuex์์ ์ํ ๊ธฐ๋ก ๊ฐ์ฒด๋ฅผ ๊ตฌํํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ์ ๋ง ์ ์ฉํฉ๋๋ค.
ํธ์ง : ์ด ์๋ฃจ์ ์ ์ ๊ฒฝ์ฐ์๋ง ํด๋น๋์์ต๋๋ค. ํน์ ์์ ์ ์์ฑ ๊ฐ์ ๋ณต์ฌ๋ณธ๋ง ํ์ํ ๊ฐ์ฒด๊ฐ ์์์ต๋๋ค. ์ฐธ์กฐ, ๋์ ์ ๋ฐ์ดํธ ๋ฑ์ ์ ๊ฒฝ ์ฐ์ง ์์์ต๋๋ค.
์ง๊ธ ๋น์ฅ ๊ฐ์ฒด๋ฅผ ๋๊ฒฐํ๋ ๊ฒ์ ์ฅ๊ธฐ์ ์ธ ํด๊ฒฐ์ฑ
์ด ์๋๋๋ค. [Vue-nonreactive]๋ Vue๋ฅผ ์ข
์์ฑ์ผ๋ก ๊ฐ์ง๊ณ ์๋๋ฐ, ์ด๋ ๊ณง์ฅ ์์ผ๋ก ๋์๊ฐ๋ ์ผ์ ๊ดํด์๋ ๊ณผ๋ํฉ๋๋ค. instance.__ob__ !== false
์ ๊ฐ์ ๊ฐ๋จํ ์ฝ๋ ํ์ธ์ผ๋ก ์ถฉ๋ถํ์ง ์์๊น์? ์ด๋ ๊ฒ ํ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์บ์์ ๊ฐ์ ํญ๋ชฉ์ด ๊ด์ฐฐ๋์ง ์๋๋ก ํ ์ ์์ต๋๋ค.
class Unobservable {
construtor() {
Object.defineProperty(this, '__ob__', {
enumerable: false, configurable: false,
writable: false, value: false,
});
}
}
์ด๊ฒ์ ๋๋ถ๋ถ Vue ์์ฉ ํ๋ก๊ทธ๋จ์์ ์ฌ์ฉ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฌธ์ ์ ๋๋ค(์ ์ด๋ ์ ์๊ฒ๋).
Vue์ 1๋ ๋ฒจ ๋ฐ์ดํฐ ๊น์ด๋ง ๊ฐ์(defineProperty to)ํ๋๋ก ์ง์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
์ ๊ฒฝ์ฐ๋ data.curObj
๋ณ๊ฒฝ๋์์ ๋ Vue๊ฐ ์๋ฆผ์ ๋ฐ๊ธฐ๋ฅผ ์ํฉ๋๋ค.
๊ทธ๋ฌ๋ curObj.position
, curObj.rotation
๋ฑ์ ์ฌ์ฉํ์ง ๋ง์ญ์์ค.
Object.freeze
๋ฅผ ์ฌ์ฉํ์ง๋ง ์ด ๊ฒฝ์ฐ three.js๊ฐ ๊ฐ์ฒด์ ๊ฐ์ ํ ๋นํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์๋๋ฅผ ํด์ผ ํ๋์?
(์ค์ ๋น์ทํ ๊ณณ์์ ํ์ด์)
data () {
return {
wrapper: Object.freeze({
actual: [bigData]
})
}
},
methods: {
operation () {
this.wrapper = Object.freeze({
actual: [newBigData]
})
}
}
// core/observer/watch.js
function _traverse (val: any, seen: ISet) {
let i, keys
const isA = Array.isArray(val)
if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
return
}
// ...
// core/observer/index.js
export function observe (value: any, asRootData: ?boolean): Observer | void {
if (!isObject(value) || value instanceof VNode) {
return
}
let ob: Observer | void
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
observerState.shouldConvert &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value)
}
// ...
> curObj PerspectiveCamera {uuid: "BD3C14DF-8C2B-4B96-9900-B3DD0EAC1163", name: "PerspectiveCamera", type: "PerspectiveCamera", parent: null, children: Array(0),ย โฆ}
> Lodash.isPlainObject(curObj) false
> Vue.isPlainObject(curObj) true
Object.isExtensible
( Object.freeze
) ์ธ์ ์ฌ์ฉ์๊ฐ ๊ด์ฐฐ์ ๋นํ์ฑํํ๋ ๋ค๋ฅธ ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์์ต๋๊น?๊ตฌ์กฐํ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
var newObj = { ...obj };
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํฉ๋๋ค. isPlainObject ๋ฉ์๋๊ฐ false๋ฅผ ๋ฐํํ๋๋ก ํฉ๋๋ค.
/**
* Makes an object and it's children unobservable by frameworks like Vuejs
*/
class Unobservable {
/**
* Overrides the `Object.prototype.toString.call(obj)` result
* <strong i="6">@returns</strong> {string} - type name
* <strong i="7">@see</strong> {<strong i="8">@link</strong> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag}
*/
get [Symbol.toStringTag]() {
// Anything can go here really as long as it's not 'Object'
return 'ObjectNoObserve';
}
}
>> Object.prototype.toString.call(new Unobservable());
"[object ObjectNoObserve]"
์๋
ํ์ธ์ ์ฌ๋ฌ๋ถ, ์๋ต์์ ์์ด๋ฒ๋ฆฐ ํ ๊ฐ์ง ํฌ์ธํธ๋ ์๋ ์ฃผ์์ ๋ฐ์ดํฐ๊ฐ ์์ํ ์ํ ๊ฐ ์๋๋ผ๋ ๊ฒ์
๋๋ค. ์ ๊ฒฝ์ฐ์๋ ๊ด๊ณ ์กฐํ ์บ์์ ๋ํ ๊ฐ์ธ ์ฐธ์กฐ๊ฐ ์๋ ๋ชจ๋ธ ์ธ์คํด์ค๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด article
๋ author
๋๋ comments
์กฐํํ ์ ์์ต๋๋ค. article.author
ํธ์ถํ๋ฉด ์ด๋ ํด๋น ๊ด๊ณ ์บ์์ ๋ํ ๋์ ์์ฑ ์กฐํ์ด๋ฉฐ ๋จ์ํ ์์ฑ ์ก์ธ์ค๊ฐ ์๋๋๋ค. ๊ณ ๋ คํด์ผ ํ ๋ช ๊ฐ์ง ์ฌํญ:
๋ช ๊ฐ์ง ์ ์์ ๋ํ ์๋ต์ผ๋ก:
๋์ ์ ์ผํ ๋นํ:
Vue-nonreactive๋ Vue๋ฅผ ์ข ์์ฑ์ผ๋ก ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ์ด๋ ์ง์ ์ ์ธ ์ผ์ ํ ๋ ์ง๋์น๊ฒ ๋ง์ต๋๋ค.
์ด๊ฒ์ด ์ ๋์ ์ผ์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ด๋ฏธ Vue๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ํ๋ฌ๊ทธ์ธ์ Vue์๋ง ํด๋น๋ฉ๋๋ค. ๋ด๊ฐ ํ๋ฆฌ์ง ์์๋ค๋ฉด ๋๋ถ๋ถ์ ๋น๋ ๋๊ตฌ๋ ์ค๋ณต ์ข ์์ฑ์ด ์๋ ๋ฒ๋ค์ ๋ง๋ค์ง ์์ ๋งํผ ์ถฉ๋ถํ ๋๋ํฉ๋๋ค. ์ด์จ๋ ์ด๊ฒ์ ์ณ์ง ์์ต๋๋ค . ๊ฐ๋ฐ ์ข ์์ฑ์ ์์ง๋ง ๋ฐํ์ ์ข ์์ฑ์ ์์ต๋๋ค.
์ด์จ๋ , ์ด ๊ฒ์๋ฌผ์ด ์ฝ๊ฐ์ ๊ด์ฌ์ ์ป์ ๊ฒ์ ์๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ์ด๋ฌํ ๋ค๋ฅธ ์๋ฃจ์ ์ค ์ผ๋ถ๋ ๋ค๋ฅธ ๋ค์ํ ๊ฒฝ์ฐ์ ์๋ํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค. ๋๋ ๋จ์ํ ๋ด ์๋ ์๊ฒฌ์ ์๊ตฌ ์ฌํญ๊ณผ ์ ์ ์ฌํญ์ด ๊ทธ ๊ฒฝ์ฐ์ ์ ํฉํ ๋์์ด ์๋ ์ด์ ๋ฅผ ๊ฐ์กฐํ๊ณ ์ถ์ต๋๋ค.
๊ทธ๋์ ์ต๊ทผ์ ์ด ๋ฌธ์ ๋ฅผ ์ ํ๊ณ Vue์ ๊ด์ฐฐ ๋ ผ๋ฆฌ๋ฅผ ๋จ๋ฝ์ํค๋ ํจ์ฌ ์ฌ์ด ๋ฐฉ๋ฒ์ด ์์์ ๋ฐ๊ฒฌํ์ต๋๋ค. _๊ตฌ์ฑํ ์ ์๋ ์์ฑ์ผ๋ก ์ ์._
๋ฐฐ๊ฒฝ
๋ด ์์ฉ ํ๋ก๊ทธ๋จ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ ํ๊ณ ๋ฐ์์ฑ ์์คํ ์ ์ง์ํ์ง ์๋ ํด๋์ค ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(OpenLayers)์ ํจ๊ป ์์ ํด์ผ ํฉ๋๋ค. ํ๋๋ฅผ ๊ตฌ๋ถ๋ฆฌ๋ ค๊ณ ํ๋ฉด ๋๋ฌด ๋ง์ ๋ํต์ด ๋ฐ์ํ์ต๋๋ค. ๋ฐ๋ผ์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ ์ผํ ์คํ ๊ฐ๋ฅํ ์๋ฃจ์ ์ OpenLayers๊ฐ ์ํ๋ ๋ฐฉ์์ผ๋ก ์์ ์ ์ํํ ์ ์๋๋ก ํ๊ณ ์ ๊ฐ Vue๊ฐ ์ด๋ฌํ ๋์ฐํ๊ฒ ์ค์ฒฉ๋ uber ๊ฐ์ฒด๋ก ๋ ๋ฉ์ง๊ฒ ์๋ํ๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ์ฐพ๊ธฐ ์ ์ ๋ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฝ 3๊ธฐ๊ฐ์ ๋จ(๊ฐ์ฅ ํฐ ๋ฐ์ดํฐ ์ธํธ์์)์ ์ฌ์ฉํ๊ณ ์์๋๋ฐ, ์ด ๋ชจ๋ ๊ฒ์ด Vue๊ฐ ์ด๋ฌํ ๊ฐ์ฒด๋ฅผ ๋ฐ์ํ์ผ๋ก ๋ง๋ค๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค. ๋ํ ๋ก๋ฉํ ๋ ์๋๊ฐ ์ ๋ง ๋๋ ธ์ต๋๋ค. ๋๋ Vue-nonreactive๋ฅผ ์๋ํ๊ณ ๋์์ด ๋์์ง๋ง ์ฐ๋ฆฌ๋ฅผ ์ฝ 1๊ธฐ๊ฐ๋ก ์ค์์ต๋๋ค. Vue๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด 350๋ฉ๊ฐ ์ ๋์์ต๋๋ค.
ํด๊ฒฐ์ฑ
๋ฐ์ํ์ง ์์ผ๋ ค๋ ๊ฒ์ configurable: false
๋ก ํ์ํ๋ฉด ๋ฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํฉ๋๋ค.
Object.defineProperty(target, 'nested', { configurable: false });
(์ด๋ ๊ฒ ํ๋ฉด nested
์์ฑ์ด ์ค์ง๋๊ณ ๋ชจ๋ ์์ฑ์ด ๊ด์ฐฐ๋์ง ์์ต๋๋ค.)
๊ทธ๊ฒ ๋ค์ผ! Vue ์ข ์์ฑ์ด ์์ผ๋ฉฐ ํ๋ฆผ์์ด ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฅ ํฐ ๋ฐ์ดํฐ ์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ 200๋ฉ๊ฐ๋ก ์ค์์ต๋๋ค. ๊ฐ๋จํ๊ณ ์ฌ์ฐ๋ฉฐ Vue ์ธก์์ ๋ฌธ์ ๋ณ๊ฒฝ๋ง ํ๋ฉด ๋ฐ์์ด ์๋ '๊ณต์' ๋ฐฉ์์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
ํฅ๋ฏธ๋กญ์ต๋๋ค - ํ์คํ ์คํ ๊ฐ๋ฅํ ๋์์ฒ๋ผ ๋ณด์ ๋๋ค.
๊ด์ฐฐ ๋ฐ์์ ์ผ์์ ์ผ๋ก ์ผ์ ์ค์งํ๊ณ ๋์ค์ ์ผ์ ์ค์ง๋ฅผ ํด์ ํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋๋ ์ํ ๊ฐ์์๊ฐ ์๋๋ฐ, ๊ทธ ์์์ ์ ์ฒด ๋ฐ์ดํฐ ์ค๋น๊ฐ ์๋ฃ๋ ํ์๋ง DOM ์ ๋ฐ์ดํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๊ณ ์ถ์ง ์์ ๊ฑฐ๋ํ ๊ฐ์ฒด๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
@intijk ์ ํํ์ง ์์ต๋๋ค. ๋น์ ์ด ๋ฌด์์ ํ๋ ค๋์ง์ ๋ฌ๋ ค ์์ต๋๋ค. Vue๋ ๊ฒฐ๊ตญ ์ํ๋ฅผ ์ ์ฉํด์ผ ํ๋ฏ๋ก ๊ณ์ฐํ๋ ๋์ ๋จ์ํ ์ผ์ ์ค์งํ๋ ๊ฒ์ ๋ณ๋ก ๋์์ด ๋์ง ์์ต๋๋ค. ๋์ ์ค๊ฐ ์ํ๋ฅผ ๊ฑด๋๋ฐ๊ณ ์ต์ข ์ํ๋ง ์ ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ์ ๊ฐ์ฒด๋ก ์์ํ ๋ค์ ๋ง์ง๋ง์ ํด๋น ๊ฐ์ฒด๋ฅผ ํ ๋นํฉ๋๋ค.
์๋ฅผ ๋ค์ด(์์ฌ ์ฝ๋):
doUpdate()
{
const state = _.cloneDeep(this.myState);
// Do intermediate state updates
this.myState = state;
}
(๊ฐ์ฒด ๋ฐ์์ฑ์ ๋ํ ์ผ๋ฐ Vue ์ฃผ์ ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค.)
๋ด ์ถ์ฒ์ ์์ configurable
ํธ๋ฆญ์ ์ฌ์ฉํ์ฌ ๋ฐ์ํ ํ์๊ฐ ์๋ ํฐ ๊ฐ์ฒด์ ์น์
์ ๊ฑด๋๋ฐ๋ ๊ฒ์
๋๋ค. ๋ชจ๋ ๊ฒ์ด ๋ฐ์ํด์ผ _ํด์ผ ํ๋ ๊ฒฝ์ฐ vuex
์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
@Morgul ์ด๋ฏธ ์ค๋ซ๋์ ์ด ํธ๋ฆญ์ ์ฌ์ฉํ์ง๋ง ์ฌ์ค์ ๋ ์ด์ ์ด ํธ๋ฆญ์ ์ฌ์ฉํ๊ณ ์ถ์ง ์๋ค๋ ๊ฒ์
๋๋ค.
์ ๊ฒฝ์ฐ์๋ ๋ฐ์ดํฐ ๊ฐ์ฒด๊ฐ 2M์์ 100M ์ฌ์ด์ ํฌ๊ธฐ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ์ด๋ฌํ ๊ฐ์ฒด์ ๋ํด ๊น์ ๋ณต์ฌ๋ฅผ ์ํํ๋ ๊ฒ์ ๋งค์ฐ ๊ณ ํต์ค๋ฝ์ต๋๋ค.
@intijk Vue๋ฅผ ๋ฐ์ธ๋ฉํ ๋ฌด์ธ๊ฐ์ ๋ํด ์์ฒญ๋๊ฒ ๋ณต์กํ๊ฒ ๋ค๋ฆฝ๋๋ค. ์ฌ๊ธฐ์ ์ฌ์ฉ ์ฌ๋ก๋ ๋ฌด์์ ๋๊น?
@๋ชจ๊ตด
์ผ์ด์ค๊ฐ ๋ณต์กํ๋ค๊ณ ์๊ฐํ์ง ์๊ณ ์ผ์ด์ค ์์ฒด๊ฐ ๋จ์ํ๊ณ ๋ฐ์ดํฐ๊ฐ ํฝ๋๋ค. ๋คํธ์ํฌ๊ฐ ์ธ๋ฑ์ฑ๋ ์๊ฐํ ๋ก๊ทธ ํ์ผ์ ๋ก๋ํ ๋๋ง๋ค ์ด๋ฅผ ํ์ํ ์๊ฐํ ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค.
๊ณ์ฐ๋ ์์ฑ ๋ด์์ ๋น๋ฐ์์ฑ ํ๋๋ฅผ ์ ์ํ๋ ๊ฒ์ ๋ํด ์๊ฐํ๋ ์ฌ๋์ด ์์ต๋๊น? ๋ด ์ฒซ ๋ฒ์งธ ์์ด๋์ด๋ ๋ฐฐ์ด์ ๋ํ ํ ๋น์ ๋น ๋ฐ์์ฑ์ ๋ฌ๋ ค ์์ต๋๋ค ...
template: '<div v-html="markdown.render(input, env)"></div>',
props: ['id', 'input'],
computed: {
env: function() { return { reactive:this.id, non_reactive:[] } },
markdown: function() { return Markdown },
},
// within markdown.render():
env.non_reactive[0] = internal_data;
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ ํํ ์์ฒด ๋ฌธ์ํ๋์ง ์์ต๋๋ค :-)
์๋ค ์. ๋ฐฉ๊ธ ์ด ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๊ณ rpkilby์ ๋ฌธ์ ์ ๋งค์ฐ ์ ์ฌํ ๋ฌธ์ ์ ์ง๋ฉดํ๊ณ ์์์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋ด ํ๋ก์ ํธ๋ JSON ๊ฐ์ฒด์์ ์ผ๋ จ์ Vue ๊ฐ์ DOM(๋๋ vnode๋ผ๊ณ ํจ)์ ๊ตฌ์ฑํฉ๋๋ค. ์ด JSON ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ Android ์ฑ์ ๊ตฌ์ฑํ๊ฒ ์ต๋๋ค. ์ด์จ๋ ์ด JSON ๊ฐ์ฒด๋ ํฌ๊ธฐ๊ฐ ์ปค์ Vue์์ ์ด JSON์ ์ฌ์ฉํ๋ฉด Vue์์ ๊ด์ฐฐ๋ฉ๋๋ค. ๋๋ rpkilby์ Morgul์ ๋ฐฉ์์ ์๋ํ์ง๋ง ์๋ํ์ง ์์ต๋๋ค. (BTW ์ ๋ ํ์ ์ํด ์์ง๋ง ์ผ๋ถ ์ฌ๋๋ค์ Vue์ ์ต์ํ์ง ์์ ์ ์์ผ๋ฉฐ ์๋ง๋ JSON์ด ๊ด์ฐฐ๋๊ณ Vue ๋ฒ์ ์ 2.5.16์
๋๋ค. ). Vue ํธ๋๋ฒ์ค์์ ์ด ์์
์ ์ํํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค.
๊ธฐ๋ฅ _traverse (๋ฐ, ๋ณธ) {
var i, ํค;
var isA = Array.isArray(๋ฐ);
if ((!isA && !isObject(val)) || Object.isFrozen(val) || VNode์ val instance
|| (๋ฐ && ๋ฐ['__vueNonReactive__'])) {
๋ฐํ
}
...
๋ณด์๋ค์ํผ "val && val['__vueNonReactive__']"๋ฅผ ์ถ๊ฐํ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ JSON์ ๋ฃจํธ ๋
ธ๋๋ก "__vueNonReactive__ = true"๊ฐ ๋๋๋ก JSON ๊ฐ์ฒด๋ฅผ ์์ ํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค.
์ด๊ฒ์ด ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ๊ฐ๋ฐ์๊ฐ ๊ฐ์ฒด์ ์์ฑ์ ๊ตฌ์ฑํ์ฌ ๊ฐ์ฒด๋ฅผ Vue์์ ๊ด์ฐฐํ๋๋ก ๊ตฌ์ฑํ ์ง ์ฌ๋ถ๋ฅผ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๋ Vue์ ์๋ก์ด ๊ธฐ๋ฅ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๊น?(Object.freeze๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ๊ฐ์ฒด๋ก ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ๋ชจ๋ ์ํฉ์ ๋ง์ถ ์ ์์)
์ด๊ฒ์ ๊ณ ๋ คํ์ญ์์ค https://github.com/vuejs/vue/blob/v2.5.16/src/core/observer/index.js#L121
set val._isVue = true
๋ vue ๊ด์ฐฐ ์ ์ฐจ์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค.
์ค๋ ์ ๋ Vue๊ฐ mapbox-gl์ ๋งต ์ธ์คํด์ค๋ฅผ ๊ด์ฐฐํ ํ ์ด์ํ ์ผ์ด ๋ฐ์ํ์ฌ ๋งต์ด ๊ฐ๋ฒผ์์ง๋ ๊ฒฝ์ฐ๋ฅผ ๋ง๋ฌ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋งต ์ธ์คํด์ค๋ vue ์ธ์คํด์ค ๊ฐ์ ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค. map._isVue = true
์ถ๊ฐํ ํ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค.
+1 ๊ณต์์ ์ผ๋ก ์ง์ํฉ๋๋ค. ๊ตฌ์ฑ ์์์์ ๋ฐ์์ฑ์ด ํ์ํ์ง ์์ ํฐ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ์ฌ์ฉํ์ง ์๋ ๋ฐ์์ฑ์ ๋นํ์ฑํํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ฒด ํฌ๊ธฐ๊ฐ 800MB์์ 43MB๋ก ์ค์ด๋ญ๋๋ค.
ํธํ์ฑ ๋ฌธ์ ๋ก @magicdawn ์๋ฃจ์
์ ์ฌ์ฉํ๊ณ ์์ง๋ง @Mechazawa ๊ฐ ์ฌ๊ธฐ์์ ๊ฐ์ฅ ์ข์ ์๋ฃจ์
์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
__ob__
์ configurable
๋ฅผ false ๋ก ์ค์ ํ๋ ์๋ฃจ์
์ ๊ฒฝ์ฐ ์ค์ __ob__
๋ฅผ ์ค์ ํ๋ ค๊ณ ํ ๋ Vue๊ฐ ์ถฉ๋ํฉ๋๋ค.
Vue ๋ณ์๋ฅผ ๋น๋ฐ์ํ์ผ๋ก ๋ง๋ค ์ ์๋ Vue ํ๋ฌ๊ทธ์ธ์ ๋น๋ํ์ต๋๋ค(beforeCreate ํํฌ ์ฌ์ฉ).
์ด๊ฒ์ vue-nonreactive - @rpkilby ๋ณด๋ค ๊นจ๋ํฉ๋๋ค. ์ด ์ฃผ์์ ์ฐธ์กฐํ์ญ์์ค. ๊ทํ์ ์๋ฃจ์ ์ Vue์ ๋ค์ ๋ฒ์ ์์ ์๋ํ์ง ์์ต๋๋ค.
๋ณ์๋ฅผ ๋น๋ฐ์ํ์ผ๋ก ๋ง๋๋ ๋ฐฉ๋ฒ์ Vue-Static ์ ์ฐธ์กฐํ์ธ์.
<script>
export default {
static() {
return {
map: null,
};
},
mounted() {
this.map = new mapboxgl.Map({...}); /* something heavy */
},
};
</script>
์๋ ํ์ธ์ @samuelantonioli - vue-static์ด ์ฝ๊ฐ ๋ค๋ฅธ ์์ ์ ์ํํ์ฌ ์ ์ฒด ๊ฐ์ฒด์ ๋ํ ๋ฐ์์ฑ์ ๋นํ์ฑํํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋์กฐ์ ์ผ๋ก, vue-nonreactive๋ ๋จ์ผ ์์ฑ์ ๋ํ ๊ด์ฐฐ์ ๋นํ์ฑํํ๋ฉด์ ๋๋จธ์ง ๊ฐ์ฒด๋ ๋ฐ์ ์ํ๋ก ์ ์งํ ์ ์์ต๋๋ค.
์ฆ, ์๋๊ฐ ์ฝ๊ฐ ๋ค๋ฅธ ๊ฒ ๊ฐ์ต๋๋ค. ์ ์ ์์ฑ์ ๋ณ๊ฒฝ ์ฌํญ์ ๊ด์ฐฐํ์ง ์์ง๋ง ํ ํ๋ฆฟ์ผ๋ก ๋ ๋๋งํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. ๋น๋ฐ์์ฑ ์์ฑ์ ๊ด์ฐฐํ๊ฑฐ๋ ๋ ๋๋งํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๋ด ๋ชจ๋ธ ์ธ์คํด์ค์๋ ๊ด๋ จ ๊ฐ์ฒด ์กฐํ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ๊ฐ์ฒด ์บ์์ ๋ํ ์ฐธ์กฐ๊ฐ ์์ต๋๋ค. instance
๋ฐ ๊ด๋ จ instance.author
์ ๊ด์ฐฐ/๋ ๋๋งํ๊ณ ์ถ์ง๋ง instance._cache
๋ ์๋๋๋ค.
new Vue({
data() {
const instance = postStore.fetch({include: ['author', 'comments.author']})
Vue.nonreactive(instance._cache)
return {post: instance, },
},
...
});
์ด๋ ์ชฝ์ด๋ , ๋จธ๋ฆฌ๋ฅผ ๋ค์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋ค์ ๋ฒ์ ์์ ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ณ ๊ด์ฐฐ์/ํ๋ก์ ์์ฑ์ ์์ผ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
@LinusBorg - ์คํ ๋ถ๊ธฐ๊ฐ ํ์๋์ง ์์ต๋๋ค. ๋ค์ ๋ฒ์ ์ ๊ฐ๋ฐ์ ์ด๋์์ ์งํ๋๋์?
์ฐ๋ฆฌ๋ ์์ง ๊ฐ๋ /์คํ ๋จ๊ณ์ด๊ณ ์์ง ๋ถ๊ธฐ๋ฅผ ๊ฒ์ํ์ง ์์์ต๋๋ค. ์ด๊ฒ์ ๋ํ ์ง์งํ ์์ ์ 2.6 ์ ๋ฐ์ดํธ๊ฐ ์ถ์๋๊ธฐ ์ ์๋ ์์๋์ง ์์ ๊ฒ์ ๋๋ค. vue-cli 3.0์ด ๊ณง ์ถ์๋๊ธฐ๋ฅผ ํฌ๋งํ๋ ํ์ ์์ฒด์ ์ผ๋ก ์ฝ๊ฐ์ ์์ ์ด ํ์ํ ๊ฒ์ ๋๋ค.
์ ๋ฐ์ดํธํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
๋ฐ๋ผ์ ES6 ํ๋ก์๊ฐ ๋์ ๋๋ฉด ๋ฌธ์ ๊ฐ ๋์ผํ ๋ฒ์์ ์๋์ง ํ์ ํ ์ ์์ต๋๋ค. ๋ด ์์ฉ ํ๋ก๊ทธ๋จ์์ ๋๋ ๊ทธ๊ฒ๋ค์ ๋ง์ด ์ฌ์ฉํ๋ฉฐ vue์ ํ์ฌ ๊ด์ฐฐ์ ๋ํ ์ค๋ฒ ํค๋ ๋ ์ค๋ฒ ํค๋๊ฐ ํจ์ฌ ์์ ๋ณด์ ๋๋ค. ์ ๋ง๋ ์ธ๋ถ ์ฌํญ์์์ ๊ฒ์ ๋๋ค.
Vue-Static
์ ๋ํ ๋ฌธ์ ๋ ์ค๋ณต๋๋ ๋๋์ด ๋ ๋ค๋ ๊ฒ์
๋๋ค. ๋๋ JS ๋ชจ๋์์ ๋ด ๊ฐ์ฒด๋ฅผ ๋น๋ํ๊ณ ๊ทธ๋ฅผ ๊ฐ์ ธ์จ ๋ค์ ๊ณ์ฐ๋ ํจ์์์ ๊ทธ์ ๊ฐ์ ๋ฐํํ ์ ์์ต๋๋ค. ๊ด์ฐฐ๋์ง ์๊ธฐ ๋๋ฌธ์ ๊ณ์ฐ๋ ํจ์์ ๊ฐ์ด ๋ค์ ๊ณ์ฐ๋์ง ์๋ ๊ฒ์ ์ค์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ด vue ๊ตฌ์ฑ ์์์์ ๋น์ฆ๋์ค ๋
ผ๋ฆฌ ์ ํ ์์
์ ์ํํ์ง ์๊ธฐ ๋๋ฌธ์ ํจ์ฌ ๋ ๋์ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ์
๋๋ค.
์ด์จ๋ ์์ฑ์ ๊ตฌ์ฑ ๋ถ๊ฐ๋ฅ์ผ๋ก ์ค์ ํ๋ ๋ด ํธ๋ฆญ์ ์ฌ์ ํ โโ๋ฌธ์ ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ๊ฐ์ฅ ๋ ์นจ์ต์ ์ด๊ณ Vue์ ์์กดํ์ง ์๋ ๋ฐฉ๋ฒ์
๋๋ค. ES ํ๋ก์์ ์ค๋จ๋ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํ ์ด์ ๋ ์์ต๋๋ค. ์ฌ์ ํ ๊ตฌ์ฑํ ์ ์๋ ์์ฑ์ ๊ด์ฐฐํ๊ณ ์ถ์ง ์์ ๊ฒ์
๋๋ค. ๋ด๊ฐ ์์ ํ ํ๋ฆด ์๋ ์์ง๋ง __ob__
๊ฐ ์ฌ๋ผ์ง๋ค๋ ๊ฒ์ _์๊ณ _... ์ฐ๋ฆฌ๋ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์์ฑ์ ๋ํ ๊ฒ์ฌ์ ๋ํด ์์ง ๋ชปํฉ๋๋ค.
๋ํ 8๊ฐ์ ์ด์ ํ๋ก๋์ ์ฝ๋์์ ์ฑํผ์ธ์ฒ๋ผ ์๋ํ์ต๋๋ค. ;) (@samuelantonioli์ ๋น์ทํ ๋ฌธ์ ๊ณต๊ฐ์ด ์์ต๋๋ค. Vue๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ 2.4๊ธฐ๊ฐ๋ก ํ์ฅํ์ง ์๊ณ ๋ Vue ๋ด๋ถ์์ ์์ ํด์ผ ํ๋ OpenLayers ๋งต์ด ์์ต๋๋ค...)
๋์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ชจ๋์ ๊ฐ์ ธ์ค๊ณ ๊ณ์ฐ๋ ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ Vue-Static์ด ํ์ํ์ง ์์ต๋๋ค. ์ง์๋ค์ด ์ดํดํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ๊ฒ ๊ฐ๋ฅด์น ์ ์๋ ํจํด์ด ํ์ํ์ต๋๋ค. import-module-and-use-computed-properties ํจํด์ ๊ทธ๋ ๊ฒ ๋ช ํํ IMO๊ฐ ์๋๋๋ค.
์ฝ๊ฐ OT: ES6 ํ๋ก์๊ฐ ์ข์ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ์ ํ์ง๋ง ๋ธ๋ผ์ฐ์ ํธํ์ฑ์ ๋ํด ๋ช ๊ฐ์ง ์ฐ๋ ค๊ฐ ์์ต๋๋ค(IE11 ์ดํ์์๋ ์ง์ํ์ง ์์). ๋ธ๋ผ์ฐ์ ์๊ตฌ ์ฌํญ์ด ๋ ์๊ฒฉํ ํ๋ก์ ํธ์ Vue๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํธํ์ฑ ๋ ์ด์ด/์ผ๋ถ ์ ํ์ ํด๋ฆฌํ์ด ์๋์ง ์ฌ๋ถ์ ๊ด์ฌ์ด ์์ต๋๋ค.
Vue์ 1๋ ๋ฒจ ๋ฐ์ดํฐ ๊น์ด๋ง ๊ฐ์(defineProperty to)ํ๋๋ก ์ง์ํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
์ด ์์ด๋์ด์ ๋ํด +1, Vue๋ฅผ ์ธ๋ถ Graphic lib(์ผ๋ฐ์ ์ผ๋ก ๋ค์ค ์์ค์ ์ค์ฒฉ๋ ํฐ ๊ฐ์ฒด๊ฐ ์์)์ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์กฐํํ๋ ๊ฒ์ด ๋ ์ฌ์ธ ๊ฒ์ ๋๋ค.
์ผ๋ถ ์์ฑ๋ง ๋ฐ์ํ์ผ๋ก ์ง์ ํ๋ ๊ฒ์ ์ด๋ป์ต๋๊น?
์ฌ๊ธฐ์ ๋ถ๋ช
ํ ๊ฒ์ ๋์ณค์ ์๋ ์์ง๋ง this.propertyName = { /* ์ฌ๊ธฐ์ ํฐ ๊ฒ์ ์ฌ์ฉ */ };
Mounted() ํํฌ์์ ๊ด์ฐฐ๋์ง ์๋ ์์ฑ์ ๊ฐ๋ ๊ฒ์ ๋ํ ์๋ฃจ์
์ด ์๋๋๊น?
์๋ ํ์ธ์ @vlahanas์ ๋๋ค. https://github.com/vuejs/vue/issues/2637#issuecomment -403630456์ ์ฐธ์กฐ
_isVue
๋ฅผ ์ค์ ํ๋ฉด vue-devtool์ด ์ถฉ๋ํ๋ฏ๋ก ์ด ๊ธฐ๋ฅ์ ๋์ ์ฌ์ฉํ์ญ์์ค.
export default function setIsVue(val) {
if (!val) return
Object.defineProperty(val, '_isVue', {
value: true,
enumerable: false,
configurable: true,
})
// vue-devtool
// https://github.com/vuejs/vue-devtools/blob/c309065c57f6579b778341ea37042fdf51a9fc6c/src/backend/index.js#L616
// ๅ ไธบๆ _isVue ๅฑๆง
if (process.env.NODE_ENV !== 'production') {
if (!val.$options) {
Object.defineProperty(val, '$options', {
value: {},
enumerable: false,
configurable: true,
})
}
if (!val._data) {
Object.defineProperty(val, '_data', {
value: {},
enumerable: false,
configurable: true,
})
}
}
return val
}
๊ทธ๊ฒ์ ์์ ์์์ ๊ธธ์ ์์์ง๋ง ์์ฑ์ ๊ตฌ์ฑ ๋ถ๊ฐ๋ฅ์ผ๋ก ํ์ํ๋ ๊ฒ์ ์ค์ ๋ก ์์ ์ฒ๋ผ ๋ณด์ ๋๋ค.
Object.keys(scene).forEach((key)=>{
Object.defineProperty(target, 'nested', { configurable: false });
});
THREE.Scene
๋ฅผ ์ ๋ฌํ ํ์๊ฐ ์์ง๋ง ๋ฌธ์ ๊ทธ๋๋ก ์ ์ฒด ์ฅ๋ฉด ๊ทธ๋ํ๊ฐ ๊ด์ฐฐ ๊ฐ๋ฅ ํญ๋ชฉ์ ์๋ง์ด ๋๋ ๊ฒ์ ์ํ์ง ์์ ๋ ์ ๋ง ์ข์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์๋ณธ ๊ฐ์ฒด๋ฅผ ๊ณ์ ์ ๋ฌํ ์ ์์ผ๋ฉฐ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ํ ์ ์์ต๋๋ค. ์๋ฒฝํ!
์ฌ์ ํ ๋ฌธ์ ์
๋๋ค.
๋น๋ฐ์ํ์ผ๋ก ์ ์งํ๋ ค๋ ์์ฑ์ ์ค์ฒฉ๋ ์์ค์ด ๋ง์ด ํฌํจ๋ ๊ฐ์ฒด๊ฐ ์์ต๋๋ค.
๋ด๊ฐ ์ฌ์ฉํ๋๋ผ๋
๊ทธ๊ฒ์ ์์ ์์์ ๊ธธ์ ์์์ง๋ง ์์ฑ์ ๊ตฌ์ฑ ๋ถ๊ฐ๋ฅ์ผ๋ก ํ์ํ๋ ๊ฒ์ ์ค์ ๋ก ์์ ์ฒ๋ผ ๋ณด์ ๋๋ค.
Object.keys(scene).forEach((key)=>{ Object.defineProperty(target, 'nested', { configurable: false }); });
THREE.Scene
๋ฅผ ์ ๋ฌํ ํ์๊ฐ ์์ง๋ง ๋ฌธ์ ๊ทธ๋๋ก ์ ์ฒด ์ฅ๋ฉด ๊ทธ๋ํ๊ฐ ๊ด์ฐฐ ๊ฐ๋ฅ ํญ๋ชฉ์ ์๋ง์ด ๋๋ ๊ฒ์ ์ํ์ง ์์ ๋ ์ ๋ง ์ข์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์๋ณธ ๊ฐ์ฒด๋ฅผ ๊ณ์ ์ ๋ฌํ ์ ์์ผ๋ฉฐ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ํ ์ ์์ต๋๋ค. ์๋ฒฝํ!
๋๋
์ด๊ฒ์ ๊ณ ๋ คํ์ญ์์ค https://github.com/vuejs/vue/blob/v2.5.16/src/core/observer/index.js#L121
setval._isVue = true
๋ vue ๊ด์ฐฐ ์ ์ฐจ์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค.์ค๋ ์ ๋ Vue๊ฐ mapbox-gl์ ๋งต ์ธ์คํด์ค๋ฅผ ๊ด์ฐฐํ ํ ์ด์ํ ์ผ์ด ๋ฐ์ํ์ฌ ๋งต์ด ๊ฐ๋ฒผ์์ง๋ ๊ฒฝ์ฐ๋ฅผ ๋ง๋ฌ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋งต ์ธ์คํด์ค๋ vue ์ธ์คํด์ค ๊ฐ์ ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค.
map._isVue = true
์ถ๊ฐํ ํ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค.
์ค์ฒฉ๋ ๊ฐ์ฒด์ ์์ฑ์ ๋ฐ์ํ์ด ๋ฉ๋๋ค.
์ฌ๊ท ์ ์ผ๋ก ์๋ํ์ง๋ง Maximum call stack size exceeded
๋ ๋ง์ ์ง์ฐ์ด ๋ฐ์ํฉ๋๋ค.
@Mitroright ์ฌ๊ท ์ ์ผ๋ก์ด ์์ ์ ์ํํด์ผํ์ง๋ง ์ ๊ทผ ๋ฐฉ์์ด ์ ํํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ๋ Vue๊ฐ ๋ฐฐ์ด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์
๋๋ค. ๋จ์ํ geoJsonData
์์ฑ์ ๊ตฌ์ฑ ๋ถ๊ฐ๋ฅ์ผ๋ก ํ์ํ๋ ๊ฒ์ ์๋ํ์ง ์์ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์๋ํ์ญ์์ค.
function makeArrayNonConfigurable(objects)
{
objects.forEach((obj) =>
{
Object.keys(obj).forEach((key) =>
{
Object.defineProperty(obj, key, { configurable: false });
});
});
}
์ฐ๋ฆฌ๋ ํ ๋จ๊ณ๋ง ์งํํฉ๋๋ค. ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ํด์ผ ํ ์ ๋ถ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. Vue๋ ์ค์ฒฉ๋ ๊ฐ์ฒด ์์ฑ์ ์ฐพ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ตฌ์ฑํ ์ ์๋ ๊ฒ์ผ๋ก ํ์๋ ์์ฑ์์ ๋ฐฐ์ด ๋ด๋ถ์ ๊ฐ์ฒด๋ฅผ ๋ณด๋ ๊ฒ ๊ฐ์ผ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด์ 10,000๊ฐ์ ๊ฐ์ฒด๋ฅผ ํตํด ์ด ๋ฐฐ์ด์ ์ฒ์ ํต๊ณผํ ๋ ๋ช ์ด ์ ๋ ํ์ ๋๋ค๊ณ ๋งํ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ์ด ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ ๋น์ฉ์ ์ผ๋ถ๋ก ๊ฐ์ฃผํด์ผ ํฉ๋๋ค. ์์งํ ๋งํด์, ๋๋ ๊ทธ ๊ฐ์ฒด๋ฅผ ํด๋์ค์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค(์ ๋ ์์ฑ์์์ ํ๋ก์๋ฅผ ๋ฐํํ๋ ํด๋์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค). ๊ทธ๋ฐ ๋ค์ ์์ฉ ํ๋ก๊ทธ๋จ์ ์๋ช ๋์ ํ ๋ฒ ์ด์ ๋ก๋ํ๋ ๊ฒฝ์ฐ ๊ณ ์ ID๋ก ํด๋น ๊ฐ์ฒด๋ฅผ ์บ์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ธฐ๊ฐ. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ค์ ๋ก ๋์์ธ ์ธ๋ถ ์ฌํญ์ด๋ฉฐ ๊ทํ์ ๋ฌธ์ ์ ์ ํํ ๊ด๋ จ์ด ์์ต๋๋ค.
์ฌ๊ธฐ์์ ํด๊ฒฐ์ฑ
์ ์ฐพ์์ต๋๋ค.
https://medium.com/@deadbeef404/tell -vue-js-to-stop-wasting-time-and-render-faster-7c3f7d2acaab
๊ฐ๋จํ ๋งํด์ ์ ํธ๋ฆฌํฐ ๊ธฐ๋ฅ์ ๋ง๋์ญ์์ค.
import Vue from 'vue';
const Observer = (new Vue()).$data.__ob__.constructor;
export function makeNonreactive(obj) {
obj.__ob__ = new Observer({});
}
์๋
ํ์ธ์ @Mitoright์
๋๋ค. ์ฐธ๊ณ ๋ก ์ด ๊ธฐ์ฌ๋ vue-nonreactive
๋ํด ์ค๋ช
ํ๊ณ ์์ต๋๋ค. ์ฐจ์ด์ ์ ์ฝ๋๋ฅผ ํ๋ฌ๊ทธ์ธ์ผ๋ก ์ฌ์ฉํ ์ง( vue-nonreactive
) ๋์ฐ๋ฏธ ํจ์๋ก ์ฌ์ฉํ ์ง ์ฌ๋ถ์
๋๋ค. ๋ํ vue-nonreactive
๋ ์ด ๋ฌธ์ ์ค๋ช
์๋จ์ ์
๋ฐ์ดํธ ์ค๋ฅธ์ชฝ์ ์ธ๊ธ๋์ด ์์ต๋๋ค.
vue-devtool์ด ๋ค์ ์ ๋ฐ์ดํธ๋๋ฉด์ https://github.com/vuejs/vue/issues/2637#issuecomment -434154442๊ฐ vue-devtool์ ๋ค์ ์ถฉ๋ํ๊ฒ ๋ง๋ญ๋๋ค.
vue-nonreactive
๊ฐ์ ์๋ฃจ์
์ ์ ์ํฉ๋๋ค ๐
__ob__
์ด๊ฑฐํ ์ ์๋๋ก ํ๋ ค๋ฉด defineProperty
vue-free.js
import Vue from 'vue'
const Observer = new Vue().$data.__ob__.constructor
function prevent(val) {
if (val) {
// Set dummy observer on value
Object.defineProperty(val, '__ob__', {
value: new Observer({}),
enumerable: false,
configurable: true,
})
}
return val
}
// vue global
Vue.VUE_FREE = prevent
// window
global.VUE_FREE = prevent
// default export
export default prevent
๊ทธ๋ฆผ ๋๋ ์ด๊ฒ์ ๋ํ 2 ์ผํธ์ ํด๊ฒฐ์ฑ ์ ์ค ๊ฒ์ ๋๋ค.
๋ํ Freeze ๊ฐ๋
๊ณผ ๊ฐ์ง ๊ด์ฐฐ์๋ฅผ ๋ชจ๋ ๊ตฌํํ๋ ์ ์ฌํ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ๋ด ๋ฐ์ดํฐ๋ ์๋ฒ์์ ๊ฐ์ ธ์ค๊ณ ์ฌ๊ท์ ์ธ TreeNode ์๋๋ฆฌ์ค์
๋๋ค. ๋ด ํ๋ก์ ํธ๋ ์ด ๊ฒฝ์ฐ์๋ vuex๋ฅผ ์ฌ์ฉํ์ฌ ๋ณธ ๋ฌธ์ ์ ๋ ์ด์ด๋ฅผ ์ถ๊ฐํ์ต๋๋ค. ๋๋ vues object.keys ๋ฃจํ๋ก ์ธํด ์ง์์ ์ผ๋ก Maximum call stack size exceeded
๋ฅผ ๋ฐ์์ต๋๋ค. ๋๋ Freeze๋ฅผ ์๋ํ๊ณ ๊ฐ์ง VNode ๋ด๋ถ์ ๋ฐ์ดํฐ๋ฅผ ์ค์ ํ์ง๋ง ๋ ๋ค ์ฌ๊ท ๋ฌธ์ ๋ฅผ ๋ง์ง ๋ชปํ๋ ๊ฒ ๊ฐ์์ต๋๋ค.
๋๋ ๋ง์นจ๋ด ๋ค๋ก ๋ฌผ๋ฌ์์ ๊ณ ์ ์ ์ธ Revealing Module Pattern์ ์ฌ์ฉํ์ฌ "๋น๋ฐ์์ฑ" ์์ฑ์ ๊ฐ์์ต๋๋ค.
์ด๊ฒ์ ํด๋์ค(ES6/typescript)์ด์ง๋ง ์ผ๋ฐ vue์๋ ๋์ผํ๊ฒ ์ ์ฉ๋ ์ ์์ต๋๋ค.
import { first, forEach } from 'lodash';
export class TreeNode {
internalRefsInstance: () => { getParent: () => TreeNode; setParent: (parent: TreeNode) => void; getChildNodes: () => TreeNode[]; setChildNode: (childNode: TreeNode) => number; };
get visitedDate(): string | undefined {
return this._visitedDates.get(this.id) || undefined;
}
isSelectedTreeNode: boolean = false;
showSubheader: boolean = false;
showHelp: boolean = false;
treeNodeIconName: string = 'empty';
childTreeNodeCount: number = 0;
constructor(public id: string,
public componentName: string,
private _visitedDates: Map<string, string>,
public isActive: boolean = true,
public nextFlow?: string,
public prevFlow?: string,
parent: TreeNode | undefined = undefined) {
//invoke the internal refs module to create our static instance func to get the values from
this.internalRefsInstance = this.nonReactiveModule();
this.internalRefsInstance().setParent(parent);
}
nonReactiveModule = () => {
let _parent: TreeNode | undefined = undefined;
let _childNodes: TreeNode[] = [];
const _getParent = (): TreeNode | undefined => {
return _parent;
};
const _setParent = (parent: TreeNode | undefined): void => {
_parent = parent;
};
const _getChildNodes = (): TreeNode[] => {
return _childNodes || [];
};
const _setChildNode = (childNode: TreeNode): number => {
if (!_childNodes) {
_childNodes = [];
}
_childNodes.push(childNode);
return _childNodes.length;
};
const returnObj = {
getParent: _getParent,
setParent: _setParent,
getChildNodes: _getChildNodes,
setChildNode: _setChildNode,
};
return () => { return returnObj; };
}
getParent(): TreeNode | undefined {
return this.internalRefsInstance().getParent();
}
getChildNodes(): TreeNode[] {
return this.internalRefsInstance().getChildNodes();
}
setChildNode(childFlow: TreeNode): void {
this.childTreeNodeCount = this.internalRefsInstance().setChildNode(childFlow);
}
clone(parent: TreeNode | undefined = undefined): TreeNode {
const newInstance = new TreeNode(this.id, this.componentName, this._visitedDates, this.isActive, this.nextFlow, this.prevFlow, parent);
newInstance.showHelp = this.showHelp;
newInstance.showSubheader = this.showSubheader;
newInstance.isSelectedTreeNode = this.isSelectedTreeNode;
forEach(this.getChildNodes(), (flow: TreeNode) => {
newInstance.childTreeNodeCount = newInstance.internalRefsInstance().setChildNode(flow.clone(newInstance));
});
return newInstance;
}
setVisitedDates(visitedDates: Map<string, string>): void {
this._visitedDates = visitedDates;
forEach(this.getChildNodes(), (flow: TreeNode) => {
flow.setVisitedDates(visitedDates);
});
}
setAsSelected(setParent: boolean = true, setAllFirstChildren: boolean = true): void {
this.isSelectedTreeNode = true;
if (setAllFirstChildren) {
const firstChildFlow = first(this.getChildNodes());
if (firstChildFlow) {
firstChildFlow.setAsSelected(false, true);
}
}
if (setParent && this.getParent()) {
this.getParent()!.setAsSelected(setParent);
}
}
resetSelected(resetChildren: boolean = true): void {
this.isSelectedTreeNode = false;
if (resetChildren) {
forEach(this.getChildNodes(), (flow: TreeNode) => {
flow.resetSelected(resetChildren);
});
}
}
}
๋ด ๊ฒฝ์ฐ์๋ Computed๊ฐ ์๋ํ์ง ์์์ต๋๋ค. ์๋ํ๋ฉด ๋๋ ์ฌ์ ํ ์ ์ฒด ๊ฐ์ฒด๊ฐ ํ์ํ๊ณ ๊ณ์ฐ๋ ๊ฒ์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ ๋์๊ฒ ๋ณด๋ด๋ ํธ๋ค๋ฌ๊ฐ ํ์ํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ ์ด๋ ๊น์ ๊ฐ์์๊ฐ ๊ณ์ฐ๋ ๋ถ๋ถ ์งํฉ ๊ฒฐ๊ณผ์ ๋ํด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํ๊ณ ์๋ค๋ฉด.
๋๋ ์ด๊ฒ์ ๋ค์ ์์ค์ผ๋ก ๋์ด์ฌ๋ฆฌ๋ฉด ํ๋ก์ธ์ค ์๋๋ฅผ ๋์ด๊ธฐ ์ํด ์ฃผ์ ๋ ๋น์ฌ๊ท ๋์ฐ๋ฏธ ๋๋ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๋ง๋๋ ๊ฒ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ์ฉํ ํผ๋๋ฐฑ์ด ์์ผ๋ฉด ์ข์ต๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ์ด๋ฏธ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ ๊ฐ์ต๋๋ค.
https://github.com/vuejs/vue/issues/4384 ์์ ๋ชจ๋ ์ธ๋ถ ์ ๋ณด๋ฅผ
์๋
ํ์ธ์, ์ ๋ ํนํ ์ด ์ด์ ๋ฌธ์ ๋ฅผ ์์ง ๋ชปํด์ #10265๋ฅผ ๋ง๋ค์์ต๋๋ค.
Vue๊ฐ Proxy๋ฅผ ์ฌ์ฉํ ๋ ๋ฏธ๋์ ๋๋นํ๊ณ Vue์ ํธํ๋๋๋ก ์กฐ์ธํ๋ ์๋ฃจ์
์ด ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค.
Object.defineProperty
๋ฅผ configurable: false
Object.defineProperty
์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ ์๋ํฉ๋๋ค(๊ทธ๋ฌ๋ ๊ธฐ์กด setter/getter๊ฐ ์๋ ์์ฑ์ด ๋ฐ์ํ๋ ๊ฒ์ ๋ฐฉ์งํ์ง๋ ์์ต๋๋ค).
์ด ๊ธฐ์ ์ Vue 3์์ ๊ณ์ ์ฌ์ฉํ ์ ์์ต๋๊น?
๊ฐ์ฌ ํด์
@colin-guyon configurable: false
๋ ์๋ง๋ ์๋ํ์ง ์์ ๊ฒ์
๋๋ค. ํนํ https://github.com/vuejs/vue-next/blob/d9c6ff372c10dde8b496ee32f2b9a246edf66a35/packages/reactivity/src#/reactive59t ๊ฐ ์๋ ๊ฒ ๊ฐ๊ธฐ ๋๋ฌธ์
๋๋ค.
์๋ก ์ ์๋ Vue.observable
์ฒ๋ผ ์์ฑ์ด ๋ฐ์ ๊ฐ์ฒด์ ์ค์ ๋๋ฉด ํด๋น _new_ ๊ฐ์ด ์ค์ผ๋์ง ์๊ณ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค. ๋์ _getter_๋ ์ด์ ๋ํ ๋ฐ์ ํ๋ก์๋ฅผ ๋ฐํํ๊ณ ์บ์์ ์์ง ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ ์๋ก ๋ง๋ญ๋๋ค.
๋คํ์ค๋ฌ์ด ์์์ _that_ ๋ฐ์์ฑ ํ๋ก์์์ ๋ง์ ์์ ์ ์ํํ์ง ์๋ ํ ๊ด์ฐฎ์ ๊ฒ์ ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ํธ๊ทธ ๋๋ ์ํธ ์ด์ฉ์ฑ์ด ์ฐ๋ ค๋๋ ๊ฒฝ์ฐ ๊ฐ์ฒด๊ฐ ๋ฌด์์ด๋ ๊ฐ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค. ๊ฑฐ๋ํ ๋ฐ์ดํฐ ๋ชจ์์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ ์ธ๋ถ ๊ฐ์ฒด์ ๋ํด ๋ฐ์์ฑ์ด ์ ์ฉ๋์ด์ผ ํ๋ ๋์์ ์์ธกํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. โ ๊ทธ๊ฒ์ ๋ํด _์๋ฌด๊ฒ๋_ ๊ฑด๋๋ฆฌ์ง ์์ต๋๋ค. ์ด๋ฐ ์๋ฏธ์์ Vue 3.x๋ ์ค์ ๋ก ์ด ๊ธฐ๋ฅ์ด ์ ์ฉํ ์ ์๋ ๋ง์ ๊ฒฝ์ฐ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
ํ์ฌ vue-next
์ฝ๋๋ ํ์ฌ ๋ฒ์ ์ Vue์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฐ์ํ์์ ๊ธฐํธ ํค๋ฅผ ์ ์ธํ๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
์ด๊ฒ์ ๊ณ ๋ คํ์ญ์์ค https://github.com/vuejs/vue/blob/v2.5.16/src/core/observer/index.js#L121
setval._isVue = true
๋ vue ๊ด์ฐฐ ์ ์ฐจ์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค.์ค๋ ์ ๋ Vue๊ฐ mapbox-gl์ ๋งต ์ธ์คํด์ค๋ฅผ ๊ด์ฐฐํ ํ ์ด์ํ ์ผ์ด ๋ฐ์ํ์ฌ ๋งต์ด ๊ฐ๋ฒผ์์ง๋ ๊ฒฝ์ฐ๋ฅผ ๋ง๋ฌ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋งต ์ธ์คํด์ค๋ vue ์ธ์คํด์ค ๊ฐ์ ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค.
map._isVue = true
์ถ๊ฐํ ํ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค.
_isVue
๊ฐ ์ฌ์ค์ด๊ณ ๊ฐ์ฒด๊ฐ Vue ๊ตฌ์ฑ ์์ ์ธ์คํด์ค๋ผ๊ณ ์๊ฐํ์ง๋ง ๊ทธ๋ ์ง ์๊ธฐ ๋๋ฌธ์ Vue ๊ฐ๋ฐ ๋๊ตฌ๊ฐ ๋์ฒญ์ ๋ฌผ๋ฆด ๋๊น์ง ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
์ฌ๊ฐํ ๋ถ์์ฉ ์์ด ๋ด๊ฐ ๋ณธ ์ ์ผํ ํดํน์ vue-nonreactive
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ OP์ ์ ๊ทผ ๋ฐฉ์์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์ด์ ๋ํ V3์ ๋์ฒด ์๋ฃจ์ ์ด ์์ต๋๊น?
@ HunderlineKshallowRef,shallowReactive,markRaw
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
data
์ ๊ฐ์ฒด/๋ฐฐ์ด์ ๋ํ ๊ด์ฐฐ์ ๊ฑด๋๋ฐ์ด์ผ ํ๋ ๊ฒฝ์ฐObject.freeze()
๋ฅผ ์ฌ์ฉํ์ญ์์ค.data
์ ์ก์ธ์คํ๊ธฐ ์ํดthis
.created()
hook์this
์ ๊ฐ๋จํ ๋ถ์ด๋ฉด ์ ํ ๊ด์ฐฐ๋์ง ์์ต๋๋ค.