关键词:defineModel 和 reactive 异同
在 Vue 3 中,defineModel
和reactive
虽然都与响应式相关,但它们有以下不同之处:
一、功能目的
- reactive:
- 主要用于创建响应式对象。它接收一个普通的 JavaScript 对象,并将其转换为响应式对象,使得对这个对象的属性进行修改时,可以触发依赖这个对象的组件重新渲染。
- 例如:
import { reactive } from "vue"; const state = reactive({ count: 0, }); state.count++; // 修改响应式对象的属性,会触发相关组件重新渲染
- defineModel:
- 主要用于在组合式函数中简化双向绑定的实现。它通常与
reactive
等响应式函数一起使用,自动解包响应式对象的属性,使得这些属性可以在模板中直接使用,无需通过.value
来访问,并且方便与v-model
指令配合实现双向绑定。 - 例如:
import { reactive, defineModel } from "vue"; export default function useCounter() { const state = reactive({ count: 0, }); return defineModel(() => ({ count: state.count, })); }
- 主要用于在组合式函数中简化双向绑定的实现。它通常与
二、使用方式
- reactive:
- 直接接收一个普通对象作为参数,返回一个响应式对象。这个响应式对象的属性可以在组件的逻辑部分(如
setup
函数、方法等)中被修改,从而触发视图更新。 - 例如在组件中使用:
<template> <div>{{ state.count }}</div> </template> <script setup> import { reactive } from "vue"; const state = reactive({ count: 0, }); setTimeout(() => { state.count++; }, 1000); </script>
- 直接接收一个普通对象作为参数,返回一个响应式对象。这个响应式对象的属性可以在组件的逻辑部分(如
- defineModel:
- 在组合式函数中使用,通常返回一个对象,其中包含需要进行双向绑定的属性。这个对象中的属性可以在模板中直接使用
v-model
指令进行双向绑定。 - 例如:
<template> <div> <input v-model="count" /> </div> </template> <script setup> import useCounter from "./useCounter"; const { count } = useCounter(); </script>
- 在组合式函数中使用,通常返回一个对象,其中包含需要进行双向绑定的属性。这个对象中的属性可以在模板中直接使用
三、作用范围
- reactive:
- 创建的响应式对象可以在整个组件中使用,包括模板、
setup
函数、方法等。它主要用于管理组件的状态数据,使得这些数据的变化能够反映到视图中。
- 创建的响应式对象可以在整个组件中使用,包括模板、
- defineModel:
- 主要作用于组合式函数中,用于处理特定的逻辑并返回可以在模板中进行双向绑定的属性。它的作用范围相对较窄,主要是为了方便实现双向绑定的场景。
四、与v-model
的配合
- reactive:
- 如果要在自定义组件中使用
reactive
创建的响应式对象与父组件进行双向绑定,需要手动处理v-model
绑定的值的传递和更新。通常需要在组件的props
中接收一个值,并在组件内部通过事件触发将更新后的值传递回父组件。 - 例如:
<template> <div> <input :value="inputValue" @input="$emit('update:inputValue', $event.target.value)" /> </div> </template> <script setup> defineProps(["inputValue"]); </script>
- 如果要在自定义组件中使用
- defineModel:
- 与
v-model
配合更加方便,使用defineModel
返回的属性可以直接在模板中使用v-model
进行双向绑定,无需手动处理事件的触发和值的传递。它自动处理了输入事件,并将新的值更新到响应式对象中。
- 与