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. 更小的打包体积 - 按需导入

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

相关推荐
kcuwu.3 小时前
CNN与RNN入门技术博客
人工智能·rnn·cnn
fly_over3 小时前
AI Agent 开发实战教程(三):记忆与数据库集成
数据库·人工智能·python·ai agent
2601_956414143 小时前
科捷智能仓储解决方案 ,助力两轮车行业高效运转
大数据·人工智能
hans汉斯3 小时前
【人工智能与机器人研究】基于改进YOLOv11的野外中草药目标检测
人工智能·yolo·目标检测·目标跟踪·机器人
mask哥3 小时前
codex安装并配置第三方大模型api方法详解
人工智能·ai编程·codex·vibecoding
Black蜡笔小新3 小时前
企业AI算力工作站DLTM深度学习推理工作站AI智检重构制造业质量管控新模式
人工智能·深度学习·重构
中国胖子风清扬3 小时前
PageIndex:用推理替代向量的下一代 RAG 架构
java·spring boot·python·spring·ai·embedding·rag
optimistic_chen3 小时前
【AI Agent 全栈开发】RAG(检索增强生成)
java·linux·运维·人工智能·ai编程·rag
zhangxingchao3 小时前
AI应用开发四:RAG多模态数据处理
人工智能