vue3的ref和reactive的使用

1,276 阅读1分钟
<tempalte>
    <div>{{person1}}--{{person2}}</div>
    <!-- { name: 'Amy' }和{ name: 'Tom' },三秒后person1变成了{name: 'Tony'} -->
</template>
<script>
import { ref, reactive } from 'vue';
export default {
    setup () {
        const person1 = ref({ name: 'Amy' });
        const person2 = reactive({ name: 'Tom' });
        setTimeout(() => {
            person1.value = {name: 'Tony'};
            person2 = {name: 'Tony'};
        }, 3000);
        return { person1, person2 };
    }
};
</script>

这样的运行结果颠覆了我对ref和reactive的理解,两者不是通过数据是基础类型或引用类型区分的。

ref

接受一个any类型的参数,返回{value: }包裹的Proxy,可以通过改变value属性实现响应式的赋值操作,但是在setup作用域中访问内部结构也需要带上value属性,在模板中自动拆解value的包裹。

使用场景: 适用于需要赋值操作的数据,基本类型(必须)、结构较浅的引用类型(建议)。

reactive

接受引用类型的参数,返回其Proxy,无法响应对整个Proxy的赋值。ref对引用类型的处理在包裹value后就由reactive负责。因此,reactive在官网列入响应式基础API。

使用场景: 不需要赋值操作的数据,结构较深的引用类型(建议)。

<tempalte>
   <div>{{person1 === person2}}</div>
   <!-- true -->
</template>
<script>
import { ref, reactive } from 'vue';
export default {
   setup () {
   	let obj = { name: 'Amy' };
       const person1 = ref(obj);
       const person2 = reactive(obj);
       console.log(person1.value === person2); // true
       return { person1, person2 };
   }
};
</script>

两者在引用类型的处理上,区别在ref拥有value的包裹,内部则一致。

相关应用

v-model

<tempalte>
   <my-component v-model="data"></my-component>
   <!-- 等同于 -->
   <my-component
   	modelValue="data"
       @update:modelValue="e => data.value=e"></my-component>
</template>

v-model含有隐式的赋值操作,因此v-model的props也需要传入ref处理的数据,而不是reactive。

ref Element

setup在mount之前执行,那么我们如何在其中获取ref绑定的dom?

 <tempalte>
   <div ref="div"></div>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
   setup () {
   	const div = ref(null);
       onMounted(() => {
       	console.log(div.value); // <div></div>
       });
       return { div };
   }
};
</script>

ref生成一个包裹null的Proxy,以暴露的属性名作为向dom绑定ref的name,便可获取dom。