news 2026/6/9 7:42:57

《uni-app开发Harmony Next平台的App》第八篇:vue2项目迁移到vue3——为鸿蒙化做准备

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《uni-app开发Harmony Next平台的App》第八篇:vue2项目迁移到vue3——为鸿蒙化做准备

《uni-app开发Harmony Next平台的App》第八篇:vue2项目迁移到vue3——为鸿蒙化做准备

为什么要迁移到Vue3

uni-app官方在HBuilderX 4.27版本之后,对Harmony Next平台的App编译只支持Vue3。如果现有项目是Vue2构建的,直接编译到鸿蒙会报错,必须先将项目升级到Vue3。

Vue3本身在性能、TypeScript支持、组合式API等方面都有明显提升。迁移后不仅能编译到鸿蒙,还能获得更好的开发体验。但要注意,迁移不只是改版本号那么简单,Vue2和Vue3在语法、生命周期、响应式系统上都有重大变化。下面这篇文章会梳理出迁移过程中最核心的改动和踩坑点。

环境说明

项目版本
HBuilderX4.27 及以上
uni-app建议升级到最新正式版
目标平台Harmony Next(仅支持Vue3编译)

一、迁移前的准备

在动手修改代码之前,先做好这几件事:

  1. 备份项目:复制一份旧项目,避免操作失误。
  2. 升级HBuilderX:确保使用能编译鸿蒙的版本(4.27+)。
  3. 检查依赖:项目用到的第三方插件(如uView、colorUI等)是否支持Vue3。不支持的需要找替代品或升级版本。
  4. 清理无用代码:删除已经废弃的写法,比如Vue.prototype挂载全局方法。

官方提供了一个迁移指南页面(https://uniapp.dcloud.net.cn/tutorial/migration-to-vue3.html),可以对照参考。

二、核心差异与代码迁移

2.1 响应式系统的变化

Vue2使用data函数返回对象,通过Object.defineProperty实现响应式。Vue3使用refreactive,基于Proxy实现。

迁移时最直观的改动:

<!-- Vue2 Example.vue --> <template> <view> <text>{{ count }}</text> <button @click="increment">+1</button> </view> </template> <script> export default { data() { return { count: 0 } }, methods: { increment() { this.count++ } } } </script>

改为Vue3的组合式API写法(推荐):

<!-- Vue3 Example.vue --> <template> <view> <text>{{ count }}</text> <button @click="increment">+1</button> </view> </template> <script setup> import { ref } from 'vue' const count = ref(0) function increment() { count.value++ } </script>

如果不想用setup语法糖,也可以保留选项式API保持兼容:

<script> import { ref } from 'vue' export default { setup() { const count = ref(0) const increment = () => { count.value++ } return { count, increment } } } </script>

注意:在Vue3中,data中的属性不能直接使用ref包裹,必须通过setup()返回。而使用<script setup>后,顶层的响应式变量会自动暴露给模板,更简洁。

2.2 生命周期的变化

Vue2的生命周期函数在Vue3中大部分重命名,并且需要在组合式API中使用对应的钩子。

Vue2Vue3 (选项式)Vue3 (组合式)
beforeCreatebeforeCreate不再需要(由setup替代)
createdcreatedsetup()执行时机等同于created
beforeMountbeforeMountonBeforeMount
mountedmountedonMounted
beforeUpdatebeforeUpdateonBeforeUpdate
updatedupdatedonUpdated
beforeDestroybeforeUnmountonBeforeUnmount
destroyedunmountedonUnmounted
errorCapturederrorCapturedonErrorCaptured

注意beforeDestroydestroyed已被beforeUnmountunmounted替代。

迁移示例

// Vue2exportdefault{mounted(){console.log('mounted')},beforeDestroy(){console.log('before destroy')}}
// Vue3 选项式exportdefault{mounted(){console.log('mounted')},beforeUnmount(){console.log('before unmount')}}
// Vue3 组合式<script setup>import{onMounted,onBeforeUnmount}from'vue'onMounted(()=>console.log('mounted'))onBeforeUnmount(()=>console.log('before unmount'))</script>

2.3 模板指令的细微变化

v-model:Vue3中v-model的默认修饰符和属性名有所调整。对于自定义组件,v-model默认传递给modelValueprop,input事件改为update:modelValue。如果组件中使用了model选项改造v-model,在Vue3中需要改为modelValue+emit('update:modelValue')

v-if与v-show:行为没有变化,但需要注意在Vue3中v-if的优先级略高于v-for,不会出现Vue2中的作用域冲突(但也不建议同时使用)。

keykey的使用方式不变,但Vue3对同级的动态节点优化更好。

自定义指令:Vue3的自定义指令生命周期钩子名称发生了变化(例如bindbeforeMountinsertedmounted等)。uni-app中很少自定义指令,如果使用了需要查阅文档修改。

2.4 全局API的变化

  • Vue.prototypeapp.config.globalProperties
  • Vue.nextTick→ 从vue单独导入
  • Vue.set/Vue.delete→ 不再需要,因为响应式系统自动支持添加/删除属性
  • Vue.extend→ 被移除,组件定义改用函数式组件或defineComponent

在uni-app中,如果使用了Vue.prototype挂载全局方法(比如this.$api),需要在main.js中修改:

// Vue2Vue.prototype.$api={...}
// Vue3import{createSSRApp}from'vue'constapp=createSSRApp(App)app.config.globalProperties.$api={...}

注意:uni-app实际上使用createApp而不是createSSRApp,在HBuilderX自动生成的模板中已经是Vue3版本。

2.5 过滤器的移除

Vue3移除了过滤器(filter)。如果项目中使用了过滤器,需要替换为methods或computed。

迁移示例

<!-- Vue2 --><text>{{ price | currency }}</text>

改为:

<!-- Vue3,使用computed --><text>{{ currencyPrice }}</text>
<script setup>import{computed}from'vue'constprops=defineProps({price:Number})constcurrencyPrice=computed(()=>`${props.price.toFixed(2)}`)</script>

三、使用迁移构建工具

uni-app官方提供了一键迁移的功能?实际上在HBuilderX中,当打开一个Vue2项目时,编辑器会提示“此项目为Vue2,建议升级到Vue3”。但并没有全自动转换工具,需要手动修改。

建议操作流程

  1. 在HBuilderX中新建一个Vue3项目模板。
  2. 将旧项目的pagescomponents等文件夹复制过来。
  3. 逐个修改.vue文件,将script改写为组合式API。
  4. 修改main.jsApp.vuemanifest.json等根文件。
  5. 升级依赖:将manifest.json中的"vueVersion"改为"3"(如果有),并且在package.json(如果存在)中安装Vue3相关包。

实际上uni-app的Vue3项目不需要显式安装vue包,HBuilderX内置了。但某些第三方插件可能需要手动更换版本。

四、踩坑记录:迁移过程中常见问题

问题1:uni-app内置组件在Vue3中不显示

现象:把Vue2项目代码复制到Vue3模板后,页面空白,控制台报错说<scroll-view>等组件未注册。

原因:Vue3要求组件必须先注册才能使用。而旧版uni-app的Vue2项目会把内置组件自动注册,但Vue3项目中需要显式引入(或者检查manifest.json中是否包含"easycom"配置)。如果使用了easycom模式,需要确保组件名称匹配。

解决方案:在pages.json中添加easycom配置,或者确保组件在components目录下且命名符合规范。最简单的方法是检查HBuilderX生成的新项目模板中的pages.json,复制其easycom配置。

// pages.json"easycom":{"autoscan":true,"custom":{"^uni-(.*)":"@/components/uni-$1/uni-$1.vue"}}

问题2:this.$mp等内部属性无法使用

现象:Vue2项目中使用了this.$mp获取小程序平台信息,迁移后该属性为undefined

原因:Vue3中uni-app的内部属性有所调整。$mp在Vue3中可能改为其他方式获取,或者需要使用getEnv()函数。

解决方案:使用uni-app提供的uni.getSystemInfouni.getLaunchOptionsSync等标准API,避免直接访问$mp。如果非用不可,可以改为从Vue.prototype挂载对象中读取。

问题3:reqires在Vue3中不能使用(模块加载)

现象require('@/utils/xxx.js')在Vue3中报错,提示require未定义。

原因:Vue3全面拥抱ES Module,不支持CommonJS的require。HBuilderX在Vue3项目中默认使用ES Module,需要改用import

解决方案:将所有require改为import。注意动态导入也要使用await import()

// Vue2constutil=require('@/utils/util.js')
// Vue3importutilfrom'@/utils/util.js'

问题4:slot-scope指令无效

现象:旧项目中使用了<template slot-scope="scope">,迁移后作用域插槽不渲染。

原因:Vue3已废弃slot-scope,改用v-slot指令。

解决方案:将slot-scope替换为v-slot

<!-- Vue2 --><templateslot-scope="{item}">...</template>
<!-- Vue3 --><templatev-slot="{item}">...</template><!-- 简写 --><template#default="{item}">...</template>

问题5:uni-组件库需要升级

很多第三方组件库(如uView、colorUI)的Vue2版本不能在Vue3项目中使用,需要升级到对应的Vue3版本或改用uni-app官方插件。如果在HBuilderX插件市场搜索不到Vue3版本,建议更换为uni-ui(官方组件库,支持Vue3)。

五、最佳实践

  1. 先在Vue3环境下编译小程序端验证:鸿蒙模拟器启动较慢,可以先编译到微信小程序工具或H5端,确认基础功能正常后再编译鸿蒙。这样能更快定位问题。
  2. 逐步迁移,不要一次改完:建议按页面顺序逐个修改,每次只改几个文件,编译测试,确保不引入新错误。
  3. 保留选项式API作为过渡:如果团队不熟悉组合式API,可以继续使用选项式API(export default { data(), methods... }),Vue3完全兼容。但注意生命周期的名称变化和Vue.prototype的替换。
  4. 使用TypeScript:Vue3对TS支持更友好,迁移时可以顺便引入TypeScript,提高代码质量。只需将<script>改为<script lang="ts">,安装@types/uni-app等类型包。
  5. 检查异步组件引用:Vue3对异步组件的定义方式变了(使用defineAsyncComponent),如果项目中有动态组件加载,需要按新写法调整。

六、完整项目结构示例

下面是一个迁移后的H5页面示例,包含组合式API、生命周期和状态管理。

pages/index/index.vue:

<template> <view class="index"> <text class="title">{{ msg }}</text> <button @click="update">更新</button> <person-detail ref="childRef" /> </view> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' import PersonDetail from './personDetail.vue' const msg = ref('Hello Harmony Next') const childRef = ref(null) function update() { msg.value = `更新于 ${new Date().toLocaleTimeString()}` // 调用子组件方法 childRef.value?.doSomething() } onMounted(() => { uni.showToast({ title: '页面加载完成' }) }) onUnmounted(() => { console.log('页面销毁') }) </script>

pages/index/personDetail.vue:

<template> <view> <text>姓名:{{ name }}</text> <text>年龄:{{ age }}</text> </view> </template> <script setup> import { ref } from 'vue' const name = ref('张三') const age = ref(25) function doSomething() { age.value++ } // 暴露方法给父组件 defineExpose({ doSomething }) </script>

FAQ

Q:迁移后编译到H5没问题,但鸿蒙模拟器报错“ReferenceError: require is not defined”?
A:项目中还有文件使用了require(比如在static下的某些库),需要全局搜索替换为import

Q:原来用uni.$emit全局通信,迁移后怎么用?
A:Vue3中uni.$emit一样可以用,它是uni-app的API,不受Vue版本影响。但最佳实践推荐使用vue的provide/inject或状态管理库(pinia)。

Q:有些第三方uni-app插件在Vue3下无法安装?
A:检查插件市场是否有Vue3版本(标签为vue3),如果没有,可能需要手动fork后适配。建议先替换为官方uni-ui组件。

Q:迁移后部分页面可能访问未定义变量,如何快速定位?
A:启用Vue3的模板编译警告,在main.js中加入app.config.warnHandler = (msg) => console.warn(msg),能打印出更详细的错误信息。

如果你在迁移过程中遇到其他问题,欢迎留言讨论。最后一步:编译到鸿蒙,验证所有功能正常。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 7:42:05

面向对象的三大特性(封装、继承、多态)

面向对象的三大特性&#xff08;封装、继承、多态&#xff09; 一、封装1. 修饰符&#xff1a;◦ private&#xff0c;代表私有的&#xff0c;被private修饰的内容只能在本类中使用。◦ public&#xff0c;代表公开的&#xff0c;公共的2. 封装的要求&#xff1a; (1) 属性私有…

作者头像 李华
网站建设 2026/6/9 7:40:35

告别调参玄学:Halcon图像分割从binary_threshold到dyn_threshold的实战选择

工业视觉实战&#xff1a;Halcon阈值分割算子的科学选择与性能优化在工业视觉检测领域&#xff0c;图像分割的质量直接决定了后续特征提取和缺陷识别的准确性。面对复杂多变的工业场景&#xff0c;如何选择合适的阈值分割方法成为工程师们必须掌握的核心技能。本文将深入剖析Ha…

作者头像 李华
网站建设 2026/6/9 7:40:31

Ubuntu Wayland 环境下 CopyQ 剪贴板失效及改用 GPaste 的解决方案

摘要 在 Ubuntu 24.04&#xff08;GNOME 46&#xff09;从 Xorg 会话切换到 Wayland 会话后&#xff0c;CopyQ 剪贴板管理器无法再记录复制内容。本文分析其根本原因&#xff0c;并给出两种解决方案&#xff0c;重点说明在保留 Wayland 会话的前提下改用 GNOME 原生剪贴板工具 …

作者头像 李华
网站建设 2026/6/9 7:39:57

企业AI编排实战:MuleSoft+LangChain混合架构设计

1. 项目概述&#xff1a;当企业数据孤岛撞上大模型洪流我在做企业级AI落地咨询的第七年&#xff0c;几乎每周都会被客户问同一个问题&#xff1a;“我们买了最好的LLM API&#xff0c;也上了最贵的CRM和ERP&#xff0c;为什么销售团队还在用Excel手工拼客户画像&#xff1f;为什…

作者头像 李华