1. 定于数据角度对比:
ref 用来定义:基本类型数据
reactive 用来定义:引用类型,例如对象、或数组类型的数据
备注:ref也可以用来定义对象或数组类型数据,它内部会自动通过 reactive 转为代理对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="../../dist/vue.global.js"></script>
<body>
<div id="app"></div>
</body>
<script>
const { ref, reactive } = Vue
const App = {
setup () {
const data = ref({
name: 'lokka'
})
console.log(data)
return {
data
}
}
}
const app = Vue.createApp(App)
app.mount('#app')
</script>
</html>
可以看到 ref.value 返回的是一个 proxy 对象,他是通过代理 reactive 实现的,下面让我们看看源码
export function ref(value?: unknown) {
return createRef(value, false)
}
function createRef(rawValue: unknown, shallow: boolean) {
if (isRef(rawValue)) {
return rawValue
}
return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
private _value: T
private _rawValue: T
public dep?: Dep = undefined
public readonly __v_isRef = true
constructor(value: T, public readonly __v_isShallow: boolean) {
this._rawValue = __v_isShallow ? value : toRaw(value)
this._value = __v_isShallow ? value : toReactive(value)
}
get value() {
trackRefValue(this)
return this._value
}
set value(newVal) {
newVal = this.__v_isShallow ? newVal : toRaw(newVal)
if (hasChanged(newVal, this._rawValue)) {
this._rawValue = newVal
this._value = this.__v_isShallow ? newVal : toReactive(newVal)
triggerRefValue(this, newVal)
}
}
}
export const toReactive = <T extends unknown>(value: T): T =>
isObject(value) ? reactive(value) : value
2. 原理角度对比:
ref 通过 Class 的 get 与 set 来实现响应式的(数据劫持)
reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过Reflect 操作源对象内部的数据。
3. 使用角度对比:
ref 定义的数据:操作数据需要 .value,读取数据时模版中直接读取不需要 .value
reactive 定义的数据:操作数据与读取数据,均不需要 .value
可以得出 data.value.name === obj.name,但是对象更推荐用 reactive 定义,语义化更强
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="../../dist/vue.global.js"></script>
<body>
<div id="app"></div>
</body>
<script>
const { ref, reactive } = Vue
const App = {
setup () {
const data = ref({
name: 'lokka'
})
const obj = reactive({
name: 'lokka'
})
console.log(data.value.name === obj.name)
return {
data,
obj
}
}
}
const app = Vue.createApp(App)
app.mount('#app')
</script>
</html>
|