observer pattern 을 활용해 vue.js 의 computed 속성 구현
observer pattern 을 활용해 vue.js 의 comptued 속성 구현
- person 객체에 age 속성이 있다.
- person 의 age 에 종속성을 가지는 status compted 함수가 있다.
status 함수는 age 가 18을 넘으면 adult, 안 넘으면 minor 를 리턴한다 - person.age 가 변경되면 status 함수를 호출할 필요 없이 자동으로
status 값이 변경되도록 하고 싶다.(종속성 대상의 변화 추적)
1. reactive.js
const { DependencyTracker } = require('./dependency');
module.exports = {
reactive: (obj, key, v) => {
// Person 의 property 에 종속성을 가지는 computed 함수 리스트
let deps = [];
Object.defineProperty(obj, key, {
get: () => {
// dep 에 종속성 등록이 필요한 함수가 있고 Person 에 종속성 등록이 안되어 있으면 등록한다.
if (DependencyTracker.target && deps.indexOf(DependencyTracker.target) === -1) {
deps.push(DependencyTracker.target);
}
return v;
},
set: nv => {
v = nv;
for (const dep of deps) {
// 종속성이 등록된 computed 함수를 호출한다.
dep();
}
}
});
}
}
2. computed.js
const { DependencyTracker } = require('./dependency');
module.exports = {
computed: (obj, key, f, cb) => {
const dependencyUpdate = () => {
const value = f();
cb(value);
}
}
Object.defineProperty(obj, key, {
// computed function 이 call 되면 종속성 추가 과정을 진행한다.
get: () => {
DependencyTracker.target = dependencyUpdate;
// Person.age 의 getter 를 호출, 호출된 getter 에서 computed 함수 status 의 종속성을 등록한다.
const value = f();
// 종속성을 등록하고 빠짐
DependencyTracker.target = null;
return value;
},
set: () => {
console.warn('nope');
}
}
}
3. dependency.js
module.exports = {
// 종속성 추적기, computed 함수를 객체 property 에 종속하도록 한다.
DependencyTracker: {
// 종속성 등록이 필요한 computed 함수
target: null
}
}
4. main.js
const { reactive } = require('./reactive');
const { computed } = require('./computed');
const person = {};
reactive(person, 'age', 16);
reactive(person, 'country', 'Brazil');
// Person.age 에 종속성을 가지는 computed function 'status' 추가
// status 함수는 person.age(종속성 대상) 의 변화 추적이 필요하다.
// person.age 가 변경되면 status 하무를 호출하지 않아도 자동으로 변경
computed(
person,
'status',
() => {
if (person.age > 18) {
return 'Adult';
} else {
return 'Minor';
}
},
v => console.log('CHANGED, The person's status is now: ' + v);
);
console.log('Current age: ' + person.age);
console.log('Current status: ' + person.status);
// change age
console.log('change age');
person.age = 22;
// change country. Note that status update doesn't trigger
console.log('change country');
person.country = 'Chile';