Vue3的选项式API组合式API对比

Vue3的选项式API和组合式API对比

Vue 3 中的选项式 API(Options API)和组合式 API(Composition API)是两种构建组件的方式。它们本质上是两种不同的组织逻辑和编写代码的风格,都可以实现相同的功能,但各有优缺点和适用场景。

一、选项式 API(Options API)

核心思想:
选项对象来组织组件的代码,比如 datamethodscomputedwatch 等。每个功能点都有自己的专属配置项。
写法示例:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Add</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
}
</script>

二、组合式API(Composition API)

核心思想:
通过引入 Vue 3 的 setup() 函数,在其中使用 refreactivecomputedwatchonMounted 等函数组合逻辑,更加灵活。

setup() 是 Vue 组件在创建时最先执行的函数,所有组合式逻辑(如 ref、reactive、computed、watch、onMounted 等)都在里面使用,并最终将它们“暴露”给模板*

写法示例

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Add</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);
const increment = () => {
  count.value++;
}
</script>

三、两种API的细致对比

下面展示一个 用户信息表单组件,可以:

  • 输入用户姓名和年龄

  • 实时显示用户是否成年(18岁以上)

  • 在用户信息变化时写入 localStorage

  • 页面加载时从 localStorage 读取用户信息

  • 有表单验证(如年龄必须为数字,且 ≥ 0

选项式 API 实现

<!-- UserFormOptions.vue -->
<template>
  <div>
    <h2>选项式 API 表单</h2>
    <input v-model="user.name" placeholder="姓名" />
    <input v-model.number="user.age" type="number" placeholder="年龄" />
    <p>是否成年:{{ isAdult ? '是' : '否' }}</p>
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: '',
        age: 0
      },
      error: ''
    };
  },
  computed: {
    isAdult() {
      return this.user.age >= 18;
    }
  },
  watch: {
    user: {
      handler(newVal) {
        localStorage.setItem('user', JSON.stringify(newVal));
      },
      deep: true
    }
  },
  mounted() {
    const saved = localStorage.getItem('user');
    if (saved) {
      this.user = JSON.parse(saved);
    }
  },
  methods: {
    validate() {
      if (typeof this.user.age !== 'number' || this.user.age < 0) {
        this.error = '年龄必须是非负数字';
      } else {
        this.error = '';
      }
    }
  },
  updated() {
    this.validate();
  }
};
</script>

组合式 API 实现

<!-- UserFormComposition.vue -->
<template>
  <div>
    <h2>组合式 API 表单</h2>
    <input v-model="user.name" placeholder="姓名" />
    <input v-model.number="user.age" type="number" placeholder="年龄" />
    <p>是否成年:{{ isAdult ? '是' : '否' }}</p>
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script setup>
import { reactive, computed, watch, onMounted, ref } from 'vue';

const user = reactive({
  name: '',
  age: 0
});

const error = ref('');

const isAdult = computed(() => user.age >= 18);

const validate = () => {
  if (typeof user.age !== 'number' || user.age < 0) {
    error.value = '年龄必须是非负数字';
  } else {
    error.value = '';
  }
};

watch(user, (newVal) => {
  localStorage.setItem('user', JSON.stringify(newVal));
  validate();
}, { deep: true });

onMounted(() => {
  const saved = localStorage.getItem('user');
  if (saved) {
    const parsed = JSON.parse(saved);
    user.name = parsed.name;
    user.age = parsed.age;
  }
});
</script>

对比总结

选项式 API组合式 API
响应式状态定义data() 返回对象ref() / reactive() 明确声明
生命周期钩子mounted()onMounted()
计算属性computed: { isAdult() {} }const isAdult = computed(...)
监听器watch: { user: { handler, deep } }watch(user, callback, { deep: true })
表单验证逻辑位置分布在 methodsupdated集中在 watch 内部或 validate() 函数
代码结构分块清晰,逻辑分散结构集中,逻辑归一
可复用性较差,逻辑难抽离好,可提取为 composable

四、可复用的组合式函数

现在我将把上面的用户信息表单逻辑提取为一个 组合式函数(composable),这样多个组件都可以轻松复用它,而不用重复写逻辑。

自定义组合函数(useUserForm.js)

// composables/useUserForm.js
import { reactive, computed, watch, onMounted, ref } from 'vue';

export function useUserForm(storageKey = 'user') {
  const user = reactive({
    name: '',
    age: 0
  });

  const error = ref('');

  const isAdult = computed(() => user.age >= 18);

  const validate = () => {
    if (typeof user.age !== 'number' || user.age < 0) {
      error.value = '年龄必须是非负数字';
    } else {
      error.value = '';
    }
  };

  watch(user, (newVal) => {
    localStorage.setItem(storageKey, JSON.stringify(newVal));
    validate();
  }, { deep: true });

  onMounted(() => {
    const saved = localStorage.getItem(storageKey);
    if (saved) {
      const parsed = JSON.parse(saved);
      user.name = parsed.name;
      user.age = parsed.age;
    }
  });

  return {
    user,
    error,
    isAdult,
    validate
  };
}

在组件中使用(UserForm.vue)

<template>
  <div>
    <h2>用户表单</h2>
    <input v-model="user.name" placeholder="姓名" />
    <input v-model.number="user.age" type="number" placeholder="年龄" />
    <p>是否成年:{{ isAdult ? '是' : '否' }}</p>
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script setup>
import { useUserForm } from '@/composables/useUserForm';

const { user, isAdult, error } = useUserForm();
</script>

注意:选项式 API 设计上不支持直接通过函数进行逻辑复用;组合式 API 是为此场景而生的。

五、总结建议

项目阶段/特点推荐使用
学习入门Options API
小型项目Options API
中大型项目Composition API
追求逻辑复用/TS 类型Composition API
要做 Vue3 最佳实践项目Composition API
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值