在Vue3中对Object等复杂数据类型变为响应式数据使用 reactive()
,对于Number、String、Boolean、undefined、null等基本数据类型使用 ref()
变为响应式数据。
ref( )
接受一个内部值,返回一个ref 对象,这个对象是响应式的、可更改的,且只有一个指向其内部值的属性 .value。ref()
将传入参数的值包装为一个带 .value 属性的 ref 对象。ref 对象是可更改的,即可以为 .value 赋予新的值.
const num = ref(1);
// 为 num.value 赋予新的值
num.value = 2;
console.log("num.value--->", num.value);
ref 对象是响应式的,即所有对 .value 的操作都将被追踪,并且写操作会触发与之相关的副作用。ref()
方法允许创建可以使用任何值类型的响应式 ref。ref 的 .value 属性也是响应式的。当ref的值为对象类型时,会用 reactive()
自动转换它的 .value。
举例:一个包含对象类型值的 ref 可以响应式地替换整个对象
const obj = ref({ name: 'vue3' });
// 响应式替换
obj.value = { name: 'vite' };
console.log("obj--->", obj);
console.log("obj.value--->", obj.value);
ref 被传递给函数或是从一般对象上被解构时,不会丢失响应性:
const obj = {
foo: ref(0),
bar: ref(1)
}
// 仍然是响应式的
const { foo, bar } = obj;
当 ref 在模板中作为顶层属性被访问时,它们会被自动“解包”,所以不需要使用 .value。
<script setup>
import { ref } from 'vue';
const num= ref(1);
</script>
<template>
<!-- 无需 .value -->
<div>num:{{ num }}</div>
</template>
通过 ref 可以访问到在组件中定义的 DOM 元素,例如:input、div、img 等。可以使用 $refs 属性访问到这些元素。
<template>
<div>
<input ref="myInput" type="text">
<button @click="focusInput">Focus Input</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const myInput = ref(null)
function focusInput() {
myInput.value.focus()
}
return {
myInput,
focusInput
}
}
}
</script>
reative()
底层使用的是Proxy代理的方式。那 ref()
呢?
我们都知道Proxy的代理目标必须是非原始值(Object),所以我们没有任何手段拦截对原始值的操作.vue3 中对Ref
的实现基本没有太大改变,也是利用setter
和getter
对数据实现数据劫持,
源码ref:
源码路径:packages/reactivity/src/ref.ts
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)
}
}
}
ref 作用及用法
- 参数可以为任意类型,推荐使用基本类型
- 使用时 需要通过
xxx.value
的形式获取 - 本质是
拷贝粘贴
一份数据,脱离了与源数据的交互 - 将对象中属性变成响应式数据,修改该数据是不会影响到源数据,但是会更新视图