Skip to content

Instantly share code, notes, and snippets.

@secf4ult
Last active February 23, 2021 10:32
Show Gist options
  • Save secf4ult/fe94b410534af37c560915e292bc68fe to your computer and use it in GitHub Desktop.
Save secf4ult/fe94b410534af37c560915e292bc68fe to your computer and use it in GitHub Desktop.
Simple Vue reactivity.
const targetMap = new WeakMap()
let activeEffect = null
function track(target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()))
}
let dep = depsMap.get(key)
if (!dep) {
depsMap.set(key, (dep = new Set()))
}
dep.add(activeEffect)
}
function trigger(target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) return
let dep = depsMap.get(key)
if (dep) {
dep.forEach((effect) => effect())
}
}
function reactive(target) {
const handler = {
get(target, key, receiver) {
let result = Reflect.get(target, key, receiver)
// track
if (activeEffect) {
track(target, key)
}
return result
},
set(target, key, value, receiver) {
let oldValue = target[key]
let result = Reflect.set(target, key, value, receiver)
if (oldValue !== result) {
// trigger
trigger(target, key)
}
return result
},
}
return new Proxy(target, handler)
}
function effect(eff) {
activeEffect = eff
activeEffect()
activeEffect = null
}
function ref(raw) {
const r = {
get value() {
if (activeEffect) track(r, 'value')
return raw
},
set value(newVal) {
if (raw !== newVal) {
raw = newVal
trigger(r, 'value')
}
},
}
return r
}
let product = reactive({ price: 5, quantity: 2 })
let salePrice = ref(0)
let total = 0
effect(() => {
total = salePrice.value * product.quantity
})
effect(() => {
salePrice.value = product.price * 0.9
})
console.log(
`Before updated total (should be 10) = ${total} salePrice (should be 4.5) = ${salePrice}`
)
product.quantity = 3
console.log(
`After updated total (should be 15) = ${total} salePrice (should be 4.5) = ${salePrice}`
)
product.price = 10
console.log(
`After updated total (should be 30) = ${total} salePrice (should be 9) = ${salePrice}`
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment