在uni-app中如何从Options API迁移到Composition API?

uni-app 从 Options API 迁移到 Composition API 的详细指南

一、迁移前的准备
  1. 升级环境

    • 确保 HBuilderX 版本 ≥ 3.2.0
    • 项目 uni-app 版本 ≥ 3.0.0
  2. 了解 Composition API 基础

    • 响应式系统:refreactive
    • 生命周期钩子:onMountedonUnload
    • 组合函数:提取可复用逻辑
  3. 备份项目

    • 迁移前务必备份代码
    • 建议使用版本控制系统(如 Git)
二、渐进式迁移策略
  1. 组件级别迁移

    • 先迁移简单、独立的组件
    • 再处理复杂、依赖多的组件
  2. 功能模块迁移

    • 先迁移数据逻辑
    • 再迁移生命周期钩子
    • 最后处理计算属性和监听器
  3. 保持两种 API 并存

    • 迁移期间允许两种 API 在项目中共存
    • 新组件使用 Composition API,旧组件逐步迁移
三、基础语法迁移
1. 数据定义
javascript 复制代码
// Options API
export default {
  data() {
    return {
      count: 0,
      user: {
        name: 'John',
        age: 30
      }
    };
  }
}

// Composition API
import { ref, reactive } from 'vue';

export default {
  setup() {
    // 基本类型用 ref
    const count = ref(0);
    
    // 对象用 reactive
    const user = reactive({
      name: 'John',
      age: 30
    });
    
    return {
      count,
      user
    };
  }
}
2. 方法定义
javascript 复制代码
// Options API
export default {
  methods: {
    increment() {
      this.count++;
    }
  }
}

// Composition API
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);
    
    const increment = () => {
      count.value++;
    };
    
    return {
      count,
      increment
    };
  }
}
3. 计算属性
javascript 复制代码
// Options API
export default {
  computed: {
    doubleCount() {
      return this.count * 2;
    }
  }
}

// Composition API
import { ref, computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    
    const doubleCount = computed(() => count.value * 2);
    
    return {
      count,
      doubleCount
    };
  }
}
4. 监听器
javascript 复制代码
// Options API
export default {
  watch: {
    count(newVal, oldVal) {
      console.log('count changed:', newVal, oldVal);
    }
  }
}

// Composition API
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);
    
    watch(count, (newVal, oldVal) => {
      console.log('count changed:', newVal, oldVal);
    });
    
    return {
      count
    };
  }
}
四、生命周期钩子迁移
javascript 复制代码
// Options API
export default {
  onLoad() {
    console.log('页面加载');
  },
  onShow() {
    console.log('页面显示');
  },
  onUnload() {
    console.log('页面卸载');
  }
}

// Composition API
import { onLoad, onShow, onUnload } from 'vue';

export default {
  setup() {
    onLoad(() => {
      console.log('页面加载');
    });
    
    onShow(() => {
      console.log('页面显示');
    });
    
    onUnload(() => {
      console.log('页面卸载');
    });
    
    return {};
  }
}
五、组合函数提取复用逻辑
javascript 复制代码
// Options API (mixins)
const counterMixin = {
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    }
  }
};

export default {
  mixins: [counterMixin]
}

// Composition API (组合函数)
// useCounter.js
import { ref } from 'vue';

export function useCounter(initialValue = 0) {
  const count = ref(initialValue);
  
  const increment = () => {
    count.value++;
  };
  
  return {
    count,
    increment
  };
}

// 组件中使用
import { useCounter } from './useCounter';

export default {
  setup() {
    const { count, increment } = useCounter(5);
    
    return {
      count,
      increment
    };
  }
}
六、使用 <script setup> 简化语法
vue 复制代码
<template>
  <view>
    <text>{{ count }}</text>
    <button @click="increment">+1</button>
  </view>
</template>

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

// 响应式数据
const count = ref(0);

// 方法
const increment = () => {
  count.value++;
};

// 生命周期钩子
onLoad(() => {
  console.log('页面加载');
});
</script>
七、处理组件通信
1. Props
javascript 复制代码
// Options API
export default {
  props: {
    message: String
  },
  methods: {
    handleClick() {
      console.log(this.message);
    }
  }
}

// Composition API
import { defineProps } from 'vue';

export default {
  props: {
    message: String
  },
  setup(props) {
    const handleClick = () => {
      console.log(props.message);
    };
    
    return {
      handleClick
    };
  }
}

// 或使用 <script setup>
<script setup>
const props = defineProps({
  message: String
});

const handleClick = () => {
  console.log(props.message);
};
</script>
2. Emits
javascript 复制代码
// Options API
export default {
  emits: ['update'],
  methods: {
    triggerUpdate() {
      this.$emit('update', 'new value');
    }
  }
}

// Composition API
import { defineEmits } from 'vue';

export default {
  emits: ['update'],
  setup(props, { emit }) {
    const triggerUpdate = () => {
      emit('update', 'new value');
    };
    
    return {
      triggerUpdate
    };
  }
}

// 或使用 <script setup>
<script setup>
const emit = defineEmits(['update']);

const triggerUpdate = () => {
  emit('update', 'new value');
};
</script>
八、处理特殊情况
1. 访问实例属性
javascript 复制代码
// Options API
export default {
  methods: {
    callMethod() {
      this.$refs.myRef.focus();
    }
  }
}

// Composition API
import { getCurrentInstance } from 'vue';

export default {
  setup() {
    const { proxy } = getCurrentInstance();
    
    const callMethod = () => {
      proxy.$refs.myRef.focus();
    };
    
    return {
      callMethod
    };
  }
}
2. 处理 ref
javascript 复制代码
// Options API
export default {
  mounted() {
    this.$refs.myRef.focus();
  }
}

// Composition API
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const myRef = ref(null);
    
    onMounted(() => {
      myRef.value.focus();
    });
    
    return {
      myRef
    };
  }
}
九、测试与验证
  1. 单元测试

    • 确保迁移后的组件行为不变
    • 使用 Vue Test Utils 3.0+ 测试 Composition API
  2. 集成测试

    • 验证组件间交互正常
    • 测试路由、状态管理等集成功能
  3. 性能测试

    • 对比迁移前后的内存使用
    • 验证响应式系统性能
十、迁移建议
  1. 从简单组件开始

    • 先迁移无依赖的基础组件
    • 再迁移复杂业务组件
  2. 利用工具辅助

    • 使用 IDE 插件(如 Vetur)提供的代码转换功能
    • 参考 Vue 官方迁移工具
  3. 团队培训

    • 组织 Composition API 培训
    • 编写内部迁移指南和最佳实践
  4. 持续重构

    • 新功能优先使用 Composition API
    • 逐步重构旧组件

总结

从 Options API 迁移到 Composition API 是一个渐进的过程,需要耐心和规划。建议采用"组件级别迁移"和"功能模块迁移"相结合的策略,先易后难,逐步推进。在迁移过程中,充分利用 Composition API 的优势,如逻辑复用、更好的 TypeScript 支持等,提高代码质量和可维护性。

相关推荐
魔力女仆3 小时前
分享一个 JS 鼠标跟随贪吃蛇背景库
开发语言·javascript·计算机外设
别惊醒渔人5 小时前
Vue3 Diff 优化:最长递增子序列 LIS
前端·javascript·vue.js
Larcher5 小时前
从“加载模型”界面到端侧推理:拆解一个 React + WebGPU 大模型 Demo
javascript·后端
Larcher6 小时前
从状态快照到惰性初始化:读懂 React useState 的三个关键场景
javascript·人工智能·后端
Hilaku7 小时前
工作 5 年后,决定你薪资上限的究竟是什么?
前端·javascript·程序员
weixin_BYSJ19877 小时前
springboot校园自习室管理小程序---附源码32142
java·javascript·spring boot·python·django·flask·php
gis开发之家8 小时前
《Vue3 从入门到大神40篇》Vue3 源码详解(十):diff 算法全解析 —— 为什么 Vue3 比 Vue2 更快?
javascript·算法·typescript·前端框架·vue3·vue3源码
用户83134859306989 小时前
Vue+Three.js实现PCB电路板3D交互:元器件点击高亮、部件显隐、模型自动旋转
vue.js·webgl·three.js
海带紫菜菠萝汤9 小时前
WebCodecs API 实战:浏览器原生视频编解码的原理与性能测试
前端·javascript·音视频·视频编解码
a11177610 小时前
Three.js 动漫3D交互小游戏 messenger-copy
开发语言·javascript·ecmascript