Which is better: ref vs reactive?

Lyle
JavaScript in Plain English
3 min readMay 6, 2024

--

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 refmethods 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>
  1. reactive function receive 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.
  4. 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.
  5. When using watch to listen to obj, 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 reactivefunction 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 .valueto 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:

--

--