Which is better: ref vs reactive?
In the vue3 version, reactive data is implemented based on proxy. Proxy to create a Proxy object for other objects. A proxy is a proxy for the basic semantics of an object. It allows us to intercept and redefine basic operations on an object.
However, proxies cannot provide proxies for primitive data types (Boolean, Number, BigInt, String, Symbol, undefined, null). In JavaScript, primitive data are passed by value, not by reference, which means that if a function accepts primitive as arguments, then there is no reference relationship between parameter and argument, they are two completely independent values, and modifications to the parameter cannot affect the arguments.
Therefore, in order to deal with primitive and non-primitive data type, vue provides reactive
and ref
methods for creating reactive objects.
Reactive
The purpose of this article is to explore the difference between reactive and ref function, so it will not delve into the source code implementation of reactive.
<script setup>
import { reactive, ref } from 'vue'
const count = ref(0)
const obj = reactive({
list: [1, 2, 3]
name: 'reactive',
count
})
console.log(obj.name) // reactive
console.log(obj.list) // [1, 2, 3]
console.log(obj.count) // good 0
console.log(obj.value.count) // bad
</script>
reactive
function receive parameter is a value of a non-primitive type- Return a proxy instance object
- Reactive objects created with reacitve are accessed in script without the use of ‘.value ‘. This is because reactive has the ability of automatic derefs, which reduces the mental burden of users.
- 1. ‘reactive’ The received parameter is a value of a non-primitive type
2. Return a proxy instance object
3. Reactive objects created with reacitve are accessed in script without the use of ‘.value ‘. This is because reactive has the ability of automatic derefs, which reduces the mental burden of users. - When using
watch
to listen toobj
, deep listening will be automatically performed without setting{deep: true}
ref
To solve the problem that non-primitive values cannot be proxying using proxy
, vue’s solution is to wrap the non-primitive values in an object and then use the reactive
function to create a reactive object.
function ref(val) {
const wrapper = {
value: val
}
/*
* oBject.definePropertydefines the non-enumerable attribute __v_isRef. This attribute is used when implementing the automatic unwrap ref capability.
* If ref, return the value attribute, otherwise return itself.
*/
Object.defineProperty(wrapper, '__v_isRef', {
value: true
})
return reactive(wrapper)
}
<script setup>
import { reactive, ref } from 'vue'
const count = ref(0)
console.log(count.value)
</script>
In this way, the created data can be accessed using count.value
in script
.
In the template
, you can access data without using the form .value
, because vue implements the ability to automatically unwrap ref. Data returned by the ‘setup’ function in the Vue component is passed to the ‘proxyRefs’ function for processing.
function proxyRefs(target) {
return new Proxy(target, {
get(target, key, receiver) {
const value = Reflect.get(target, key, receiver)
return value.__v_isRef ? value.value : value
}
})
}
In general, the characteristics of ref are as follows:
1. ref can accept both primitive and non-primitive values
2. ref
returns a RefImpl object
3. In script
, you need to use .value
to access data
4. watch
does not deeply listen to ref
by default
In Plain English 🚀
Thank you for being a part of the In Plain English community! Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | LinkedIn | YouTube | Discord | Newsletter
- Visit our other platforms: Stackademic | CoFeed | Venture | Cubed
- More content at PlainEnglish.io