Skip to content

Instantly share code, notes, and snippets.

@Jinjiang
Created May 13, 2020 06:44
Show Gist options
  • Save Jinjiang/f795b943d4315a42077b7261caf25187 to your computer and use it in GitHub Desktop.
Save Jinjiang/f795b943d4315a42077b7261caf25187 to your computer and use it in GitHub Desktop.
A cheatsheet for Vue 3.0 reactivity system
// ---- reactive() ----
const data = { x: 1, y: 2 }
const proxy = reactive(data) // or readonly(data)
console.log(isProxy(proxy)) // true
console.log(data === proxy) // false
// ---- share same object with reactively ----
export default {
data() {
const foo = { x: 1, y: 2}
return { a: foo, b: foo }
},
methods: {
test() {
// will affect both this.a.x and this.b.x
this.a.x = 3
// won't share data with this.a any more after setting this
this.b = { x: 3, y: 4 }
}
}
}
// ---- readonly() ----
export default {
data() {
const foo = { x: 1, y: 2}
return { foo: readonly(foo) }
},
methods: {
test() {
// nothing happen
this.foo.x = 3
// will replace another reference so break the readonly behavior
this.foo = { x: 3, y: 4 }
}
}
}
// ---- markRaw() ----
const data = { x: 1, y: 2 }
const raw = markRaw(data)
// after marking as raw, the reactive/readonly call
// on this object won't work any more
// it's a global effect
const proxy = reactive(data)
const proxy2 = reactive(raw)
console.log(isProxy(raw)) // false
console.log(raw === data) // true
console.log(isProxy(proxy)) // false
console.log(isProxy(proxy2)) // false
export default {
data() {
const foo = { x: 1, y: 2}
return { foo: markRaw(foo) }
},
methods: {
test() {
// will change data but won't re-render
// after that any other re-render will use this changed data
this.foo.x = 3
// will replace another reference so break the markRaw behavior
this.foo = { x: 3, y: 4 }
}
}
}
// ---- shallowReactive()/shallowReadonly() ----
const data = { foo: 0, bar: { x: 1, y: 2 }}
const proxy = reactive(data) // or readonly(data)
const shallowProxy = shallowReactive(data) // or shallowReadonly(data)
console.log(isProxy(proxy)) // true
console.log(isProxy(proxy.bar)) // true
console.log(isProxy(shallowProxy)) // true
console.log(isProxy(shallowProxy.bar)) // false
console.log(shallowProxy.bar === data.bar) // true
export default {
data() {
const data = { foo: 0, bar: { x: 1, y: 2 }}
return { a: shallowReactive(data) }
},
methods: {
test() {
// will trigger re-render
this.a.foo = 10
// will trigger re-render
this.a.bar = { x: 3, y: 4 }
// will change data but won't re-render
// after that any other re-render will use this changed data
this.a.bar.x = 3
// will replace another reference so break the shallowReactive behavior
this.a = { foo: 10, bar: { x: 3, y: 4 }}
}
}
}
// ---- reactive()/readonly() to a same object ----
export default {
data() {
const data = { x: 1, y: 2 }
return { foo: reactive(data), bar: readonly(data) }
},
methods: {
test() {
// will trigger re-render both foo and bar
this.foo.x++
// won't trigger re-render
this.bar.x++
}
}
}
// ---- ref() ----
const primitiveRef = ref(0)
const objRef = ref({ x: 1, y: 2, z: { a: 3, b: 4} })
const objReadonlyRef = ref(readonly({ x: 1, y: 2, z: { a: 3, b: 4} }))
const objShallowRef = ref({ x: 1, y: 2, z: { a: 3, b: 4} })
console.log(isRef(primitiveRef)) // true
console.log(isRef(objRef)) // true
console.log(isProxy(objRef.value)) // true
console.log(isReadonly(objRef.value)) // true
console.log(isProxy(objShallowRef.value)) // false
// primitiveRef = 1 // wrong access
primitiveRef.value = 1 // will trigger re-render
// objRef = { x: 1, y: 3} // wrong access
objRef.value = { x: 3, y: 4 } // will trigger re-render
objRef.value.x = 5 // will trigger re-render
objReadonlyRef.value.x = 5 // nothing happen
objShallowRef.value = { x: 3, y: 4 } // will change data but won't re-render
// ---- ref in proxy ----
const primitiveRef = ref(0)
const objRef = ref({ x: 1, y: 2, z: { a: 3, b: 4} })
const proxy = reactive({
primitive: primitiveRef,
obj: objRef,
arr: [primitiveRef, objRef]
})
console.log(isRef(proxy.primitive)) // true
console.log(isRef(proxy.obj)) // true
console.log(isRef(proxy.arr[0])) // true
console.log(isRef(proxy.arr[1])) // true
console.log(isProxy(proxy.obj.value.z)) // true
// ---- ref in template ---
const primitiveRef = ref(0)
const objRef = ref({ x: 1, y: 2, z: { a: 3, b: 4} })
const proxy = reactive({
primitive: primitiveRef,
obj: objRef,
arr: [primitiveRef, objRef]
})
export default {
// will render primitiveRef.value
template: '<div>{{ primitive }}</div>'
}
export default {
// wrong access
template: '<div>{{ primitive.value }}</div>'
}
export default {
// will render objRef.value
template: '<div>{{ obj }}</div>'
}
export default {
// wrong access
template: '<div>{{ obj.value }}</div>'
}
export default {
// will get wrong result like: { __v_isRef: true, value: 0 }
template: '<div>{{ arr[0] }}</div>'
}
export default {
// will get wrong result
template: '<div>{{ arr[1] }}</div>'
}
export default {
// will render primitiveRef.value
template: '<div>{{ arr[0].value }}</div>'
}
export default {
// will render objRef.value
template: '<div>{{ arr[1].value }}</div>'
}
// computed <-> value
const primitiveRef = ref(0)
const objRef = ref({ x: 1, y: 2, z: { a: 3, b: 4} })
const readonlyComputed = computed(
() => primitiveRef.value + objRef.value.x
)
const reactiveComputed = computed(
get: () => primitiveRef.value + objRef.value.x,
set: v => primitiveRef.value = v
)
console.log(isRef(readonlyComputed)) // true
console.log(isRef(reactiveComputed)) // true
readonlyComputed.value = 10 // nothing happen
reactiveComputed.value = 10 // will trigger re-render
export default {
// will render readonlyComputed.value
template: '<div>{{ readonlyComputed }}</div>'
}
export default {
// will render reactiveComputed.value
template: '<div>{{ reactiveComputed }}</div>'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment