[Vue] 都是支持响应式, defineModel 和 reactive 有何不同【热度: 344】

关键词:defineModel 和 reactive 异同

在 Vue 3 中,defineModelreactive虽然都与响应式相关,但它们有以下不同之处:

一、功能目的

  1. reactive
    • 主要用于创建响应式对象。它接收一个普通的 JavaScript 对象,并将其转换为响应式对象,使得对这个对象的属性进行修改时,可以触发依赖这个对象的组件重新渲染。
    • 例如:
    import { reactive } from "vue";
    const state = reactive({
      count: 0,
    });
    state.count++; // 修改响应式对象的属性,会触发相关组件重新渲染
  2. defineModel
    • 主要用于在组合式函数中简化双向绑定的实现。它通常与reactive等响应式函数一起使用,自动解包响应式对象的属性,使得这些属性可以在模板中直接使用,无需通过.value来访问,并且方便与v-model指令配合实现双向绑定。
    • 例如:
    import { reactive, defineModel } from "vue";
    export default function useCounter() {
      const state = reactive({
        count: 0,
      });
      return defineModel(() => ({
        count: state.count,
      }));
    }

二、使用方式

  1. reactive
    • 直接接收一个普通对象作为参数,返回一个响应式对象。这个响应式对象的属性可以在组件的逻辑部分(如setup函数、方法等)中被修改,从而触发视图更新。
    • 例如在组件中使用:
    <template>
      <div>{{ state.count }}</div>
    </template>
    <script setup>
      import { reactive } from "vue";
      const state = reactive({
        count: 0,
      });
      setTimeout(() => {
        state.count++;
      }, 1000);
    </script>
  2. defineModel
    • 在组合式函数中使用,通常返回一个对象,其中包含需要进行双向绑定的属性。这个对象中的属性可以在模板中直接使用v-model指令进行双向绑定。
    • 例如:
    <template>
      <div>
        <input v-model="count" />
      </div>
    </template>
    <script setup>
      import useCounter from "./useCounter";
      const { count } = useCounter();
    </script>

三、作用范围

  1. reactive
    • 创建的响应式对象可以在整个组件中使用,包括模板、setup函数、方法等。它主要用于管理组件的状态数据,使得这些数据的变化能够反映到视图中。
  2. defineModel
    • 主要作用于组合式函数中,用于处理特定的逻辑并返回可以在模板中进行双向绑定的属性。它的作用范围相对较窄,主要是为了方便实现双向绑定的场景。

四、与v-model的配合

  1. reactive
    • 如果要在自定义组件中使用reactive创建的响应式对象与父组件进行双向绑定,需要手动处理v-model绑定的值的传递和更新。通常需要在组件的props中接收一个值,并在组件内部通过事件触发将更新后的值传递回父组件。
    • 例如:
    <template>
      <div>
        <input :value="inputValue" @input="$emit('update:inputValue', $event.target.value)" />
      </div>
    </template>
    <script setup>
      defineProps(["inputValue"]);
    </script>
  2. defineModel
    • v-model配合更加方便,使用defineModel返回的属性可以直接在模板中使用v-model进行双向绑定,无需手动处理事件的触发和值的传递。它自动处理了输入事件,并将新的值更新到响应式对象中。