Skip to content

Instantly share code, notes, and snippets.

@probil
Created June 24, 2018 16:53
Show Gist options
  • Save probil/700be7c74f9a7fc5ab575837c15cc458 to your computer and use it in GitHub Desktop.
Save probil/700be7c74f9a7fc5ab575837c15cc458 to your computer and use it in GitHub Desktop.
Simple implementation of Vue reactivity system (computed properties)
import makeReactive from './makeReactive';
let data = {
data: {
price: 5,
quantity: 2
},
computed: {
total() {
return this.price * this.quantity
},
totalWithTax() {
return this.total * 0.2 + this.total;
}
},
};
makeReactive(data);
console.log('Total', data.total);
console.log('Total with tax', data.totalWithTax);
data.quantity = 1;
console.log('Total', data.total);
console.log('Total with tax', data.totalWithTax);
// === Expects vue-like object:
// {
// data: {
// <key>: <simple_value>
// },
// computed: {
// <key>: <fn>
// },
// }
export default obj => {
let target = null;
class Dep {
constructor() {
this.subscribers = []
}
depend() {
if (target && !this.subscribers.includes(target)) {
this.subscribers.push(target)
}
}
notify() {
this.subscribers.forEach(sub => sub())
}
}
Object.keys(obj.data).forEach(key => {
let internalValue = obj.data[key];
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return internalValue
},
set(newVal) {
internalValue = newVal;
dep.notify()
}
});
});
function watcher(myFunc) {
target = myFunc;
target();
target = null
}
Object.keys(obj.computed).forEach(key => {
const fn = obj.computed[key].bind(obj);
let internalValue = fn();
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.depend();
return internalValue
},
set(newVal) {
internalValue = newVal;
dep.notify();
}
});
watcher(() => {
obj[key] = fn();
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment