uniapp vue2 转 vue3

将 uniapp 项目从 Vue2 迁移到 Vue3 需要进行一些必要的调整,以确保项目能够正常运行。以下是一些关键步骤和注意事项:

创建应用实例

在 Vue2 中,应用实例的创建方式如下:

复制代码
// Vue 2
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
 ...App
})
app.$mount()

在 Vue3 中,应用实例的创建方式有所不同:

复制代码
// Vue 3
import { createSSRApp } from 'vue'
import App from './App'
export function createApp() {
 const app = createSSRApp(App)
 return {
   app
 }
}

全局属性

在 Vue2 中,可以通过 Vue.prototype 来定义全局属性:

复制代码
// Vue 2
Vue.prototype.$http = () => {};

在 Vue3 中,需要使用 app.config.globalProperties:

复制代码
// Vue 3
const app = createApp({});
app.config.globalProperties.$http = () => {};

插件使用

在 Vue2 中,插件的使用方式如下:

复制代码
// Vue 2
import store from "./store";
Vue.prototype.$store = store;

在 Vue3 中,插件的使用方式有所变化:

复制代码
// Vue 3
import store from "./store";
const app = createApp(App);
app.use(store);

vuex 用法

复制代码
//  Vue 2 中使用
  import Vue from 'vue'
  import Vuex from 'vuex'
  Vue.use(Vuex)
  const store = new Vuex.Store({
      state: {}
  })
  export default store
 
// Vue 3 中使用 (建议使用pinia)
  import { createStore } from 'vuex'
  const store = createStore({
      state: {}
  })
  export default store

模块导入和导出

Vue3 只支持 ES6 模块规范,因此需要将 CommonJS 模块改为 ES6 模块:

复制代码
// Vue 2
var utils = require("../../../common/util.js");
module.exports.X = X;
// Vue 3
import utils from "../../../common/util.js";
export default { X };

生命周期的适配

在 Vue3 中,组件卸载的生命周期被重新命名:

  • destroyed 修改为 unmounted

  • beforeDestroy 修改为 beforeUnmount

生命周期变更对照表:
vue2 (Options API) Vue3 (Composition API / setup) 说明
beforeCreate / created setup() 本身 直接在 setup 顶层编写
beforeDestroy onBeforeUnmount 需从 vue 引入
destroyed onUnmounted 需从 vue 引入
activated / deactivated onActivated / onDeactivated 保持缓存逻辑

事件的适配

Vue3 提供了一个 emits 选项,用于定义组件可以向其父对象发出的事件:

这里解决截图 上面的警告

复制代码
// Vue 3
export default {
 emits: ["click"],
 inheritAttrs:false,
 methods: {
   onClick() {
     this.$emit("click", "OK");
   },
 },
};

v-model 的适配

Vue3 的 v-model 语法有所变化,支持多 model:

复制代码
// Vue 3
export default {
 props: {
   modelValue: String,
 },
 methods: {
   updateValue(value) {
//将之前的 this.$emit('input') 修改为 this.$emit('update:modelValue') 
     this.$emit('update:modelValue', value);
   }
 }
};

在模板中使用:

复制代码
<ChildComponent v-model="pageTitle" />
<!-- 等同于 -->
<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />

插槽的适配

Vue3 不再支持 slot="xxx" 的用法,需要使用 v-slot:xxx:

复制代码
<!-- Vue 2 -->
<uni-nav-bar>
 <view slot="left" class="city"></view>
</uni-nav-bar>
<!-- Vue 3 -->
<uni-nav-bar>
 <template v-slot:left>
   <view class="city"></view>
 </template>
</uni-nav-bar>

在 Vue3 中,处理 API Promise 化 调用结果的方式不同于 Vue2 。更多

  • Vue3 中,调用成功会进入 then 方法,调用失败会进入 catch 方法

  • Vue2 中,调用无论成功还是失败,都会进入 then 方法,返回数据的第一个参数是错误对象,第二个参数是返回数据

  • Vue 2 写法转 Vue 3 写法

复制代码
  // 在 main.js 中写入以下代码即可
  function isPromise(obj) {
    return (
      !!obj &&
      (typeof obj === "object" || typeof obj === "function") &&
      typeof obj.then === "function"
    );
  }
   
  uni.addInterceptor({
    returnValue(res) {
      if (!isPromise(res)) {
        return res;
      }
      return new Promise((resolve, reject) => {
        res.then((res) => {
          if (res[0]) {
            reject(res[0]);
          } else {
            resolve(res[1]);
          }
        });
      });
    },
  });

Vue 3 写法转 Vue 2 写法

复制代码
// 在 main.js 中写入以下代码即可
function isPromise(obj) {
  return (
    !!obj &&
    (typeof obj === "object" || typeof obj === "function") &&
    typeof obj.then === "function"
  );
}
 
uni.addInterceptor({
  returnValue(res) {
    if (!isPromise(res)) {
      return res;
    }
    const returnValue = [undefined, undefined];
    return res
      .then((res) => {
        returnValue[1] = res;
      })
      .catch((err) => {
        returnValue[0] = err;
      })
      .then(() => returnValue);
  },
});
相关推荐
Amos_Web2 小时前
Markdonw语法
开发语言·前端·javascript
小万7422 小时前
刚发布就冲上GitHub热榜!Filee支持244种格式转换,完全免费还全本机运行
前端
星光不问赶路人2 小时前
Vue 3 对象监听与快照:ref 和 reactive 的关键差异
前端·vue.js
世界一刘先生2 小时前
不引入 JSZip,自己写一个 ZIP 打包器:CRC32、中央目录与 UTF-8 文件名
前端
全栈项目管理程序猿2 小时前
ArcGIS JS 基础教程(34):体元系列 - 等值面 VoxelIsosurface
前端·javascript
代码搬运媛2 小时前
如何使用 @codemirror/view 库创建一个简单的代码编辑器
前端
SensorFlow2 小时前
离页埋点:sendBeacon 返回 true,为什么还不能算接收成功
javascript
huali2 小时前
草稿该存在哪:per-session 是怎么成为共识的
前端·产品经理·产品
IPIPD2 小时前
Proxifier规则为什么没有生效?从连接日志定位规则命中与DNS路径
前端