Vue3组合式API实战:构建更可维护的组件

Vue3组合式API实战:构建更可维护的组件

大家好,我是蔓蔓。Vue3的组合式API是一个非常强大的特性,它让我们能够更好地组织和复用代码。今天我来和大家分享Vue3组合式API的实战技巧。

什么是组合式API

Options API vs Composition API

javascript 复制代码
// Options API - 按选项组织代码
export default {
  data() {
    return {
      count: 0,
      name: '蔓蔓'
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2;
    }
  }
};

// Composition API - 按功能组织代码
import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const name = ref('蔓蔓');
    
    const increment = () => {
      count.value++;
    };
    
    const doubleCount = computed(() => count.value * 2);
    
    return { count, name, increment, doubleCount };
  }
};

响应式基础

javascript 复制代码
import { ref, reactive, computed, watch, watchEffect } from 'vue';

// ref - 用于基本类型
const count = ref(0);
count.value++; // 需要.value访问

// reactive - 用于对象
const state = reactive({
  name: '蔓蔓',
  age: 25
});
state.name = '新名字'; // 直接访问

// computed - 计算属性
const doubleCount = computed(() => count.value * 2);

// watch - 监听变化
watch(count, (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`);
});

// watchEffect - 自动追踪依赖
watchEffect(() => {
  console.log(`count is: ${count.value}`);
});

实战案例

组合式函数

javascript 复制代码
// useCounter.js - 可复用的组合式函数
import { ref, computed } from 'vue';

export function useCounter(initialValue = 0) {
  const count = ref(initialValue);
  
  const increment = () => {
    count.value++;
  };
  
  const decrement = () => {
    count.value--;
  };
  
  const reset = () => {
    count.value = initialValue;
  };
  
  const doubleCount = computed(() => count.value * 2);
  
  return {
    count,
    increment,
    decrement,
    reset,
    doubleCount
  };
}

// 使用
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, increment, doubleCount } = useCounter(10);
    return { count, increment, doubleCount };
  }
};

异步数据获取

javascript 复制代码
// useFetch.js - 数据获取组合式函数
import { ref, onMounted, onUnmounted } from 'vue';

export function useFetch(url, options = {}) {
  const data = ref(null);
  const error = ref(null);
  const loading = ref(true);
  let controller = null;
  
  const fetchData = async () => {
    loading.value = true;
    error.value = null;
    controller = new AbortController();
    
    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal
      });
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      
      data.value = await response.json();
    } catch (err) {
      if (err.name !== 'AbortError') {
        error.value = err.message;
      }
    } finally {
      loading.value = false;
    }
  };
  
  onMounted(fetchData);
  
  onUnmounted(() => {
    if (controller) {
      controller.abort();
    }
  });
  
  return {
    data,
    error,
    loading,
    refetch: fetchData
  };
}

// 使用
import { useFetch } from './useFetch';

export default {
  setup() {
    const { data: user, loading, error } = useFetch('/api/user');
    return { user, loading, error };
  }
};

表单处理

javascript 复制代码
// useForm.js - 表单处理组合式函数
import { reactive, computed } from 'vue';

export function useForm(initialValues) {
  const form = reactive({ ...initialValues });
  const errors = reactive({});
  
  const validateField = (fieldName, rules) => {
    errors[fieldName] = null;
    
    for (const rule of rules) {
      if (rule.required && !form[fieldName]) {
        errors[fieldName] = rule.message || '此字段必填';
        return false;
      }
      if (rule.pattern && !rule.pattern.test(form[fieldName])) {
        errors[fieldName] = rule.message || '格式不正确';
        return false;
      }
    }
    return true;
  };
  
  const validate = (fieldRules) => {
    let isValid = true;
    for (const [fieldName, rules] of Object.entries(fieldRules)) {
      if (!validateField(fieldName, rules)) {
        isValid = false;
      }
    }
    return isValid;
  };
  
  const reset = () => {
    Object.assign(form, initialValues);
    Object.keys(errors).forEach(key => delete errors[key]);
  };
  
  const isValid = computed(() => {
    return Object.keys(errors).length === 0;
  });
  
  return {
    form,
    errors,
    validateField,
    validate,
    reset,
    isValid
  };
}

// 使用
import { useForm } from './useForm';

export default {
  setup() {
    const { form, errors, validate } = useForm({
      email: '',
      password: ''
    });
    
    const rules = {
      email: [
        { required: true, message: '邮箱必填' },
        { pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '请输入有效邮箱' }
      ],
      password: [
        { required: true, message: '密码必填' },
        { pattern: /.{6,}/, message: '密码至少6位' }
      ]
    };
    
    const handleSubmit = () => {
      if (validate(rules)) {
        console.log('Form submitted:', form);
      }
    };
    
    return { form, errors, handleSubmit };
  }
};

高级技巧

依赖注入

javascript 复制代码
// 父组件提供数据
import { provide } from 'vue';

export default {
  setup() {
    const theme = ref('dark');
    
    provide('theme', theme);
    provide('toggleTheme', () => {
      theme.value = theme.value === 'dark' ? 'light' : 'dark';
    });
  }
};

// 子组件注入数据
import { inject } from 'vue';

export default {
  setup() {
    const theme = inject('theme');
    const toggleTheme = inject('toggleTheme');
    
    return { theme, toggleTheme };
  }
};

生命周期钩子

javascript 复制代码
import { onMounted, onUnmounted, onUpdated, onBeforeMount, onBeforeUpdate, onBeforeUnmount } from 'vue';

export default {
  setup() {
    onBeforeMount(() => {
      console.log('组件挂载前');
    });
    
    onMounted(() => {
      console.log('组件挂载完成');
    });
    
    onBeforeUpdate(() => {
      console.log('组件更新前');
    });
    
    onUpdated(() => {
      console.log('组件更新完成');
    });
    
    onBeforeUnmount(() => {
      console.log('组件卸载前');
    });
    
    onUnmounted(() => {
      console.log('组件卸载完成');
    });
  }
};

总结

Vue3的组合式API带来了很多好处:

  1. 更好的代码组织 - 按功能组织代码
  2. 更好的代码复用 - 通过组合式函数复用逻辑
  3. 更好的类型推断 - 更好的TypeScript支持
  4. 更小的打包体积 - 按需导入

技术应当有温度,好的代码结构能提升开发体验。

相关推荐
“AI国潮设计-小江”16 分钟前
《Python实战 | SDXL大模型批量生成“英歌舞海浪”蛋糕IP,附核心Prompt控制代码与IP授权变现思路》
人工智能·python·prompt·aigc
虹科网络安全25 分钟前
使用艾体宝 IOTA 10 CORE+ 监控企业网络中的 AI 流量
网络·人工智能
朝阳资本论28 分钟前
群核科技:从空间设计龙头到物理AI“卖水人”的升维之战
人工智能
七夜zippoe35 分钟前
为什么 2026 年每个 Java 团队都该懂 AI Agent
java·开发语言·人工智能
举个栗子。37 分钟前
SwarmForge:AI 智能体协同编程框架,让多个 Agent 在隔离工作区并行协作
人工智能·开源·ai编程
AIGC小尼1 小时前
Windows 本地 AI 漫剧全自动生产线部署完整教程(零基础、全指令、带源码、模型配置、排错方案)
人工智能·windows·ai漫剧
合米AI SOP系统1 小时前
传统产线如何快速上马落地 AI 防错?合米科技 AI SOP 7天即可上线。
大数据·人工智能·科技
思录Echo1 小时前
什么决定具身智能的最终走向?多技术路线与落地现实辨析
大数据·人工智能
ShallWeL1 小时前
Orin 上多模型常驻与显存预算
人工智能·嵌入式硬件·nvidia·orin
xiaohaiAIgeo1 小时前
【2026年】AI监控加行为分析守护实验室安全
大数据·人工智能·科普知识