背景
之前在公司做了一个 uniapp vue2 项目的一个升级的工作,在此记录一下。vue 2 升级 vue3 的好处显而易见,在此不多赘述,直接开启升级之旅。
框架搭建
HBuilder 不好用,所以使用的是 cli 的方式开搭建项目
vue create -p dcloudio/uni-preset-vue my-project
统一请求
原来请求有两种方式 uni.request 直接请求,以及基于 uni.request 请求的封装,目前统一成基于 uni.request 请求的封装,代码路径从 service/http.js 改成 utils/http.js
import { getCurrentPage, merger, generateId } from '@/utils/common.js';
const baseUrl = import.meta.env.VITE_APP_BASE_URL;
const DEFAULT_CONFIG = {
baseUrl: baseUrl,
data: {},
header: {},
method: 'post',
timeout: 150000,
dataType: 'json',
responseType: 'text',
...
};
// 屏蔽的页面
const blockLoginPopList = [...];
let loading = true;
const requestInterceptor = (opt) => {
const { url, isLoading } = opt;
const u = DEFAULT_CONFIG.baseUrl + url;
const m = merger(DEFAULT_CONFIG, opt);
const token = uni.getStorageSync('token') || '';
if (token) {
m.header.token = token;
}
const configs = {
...m,
url: u,
};
if (loading && isLoading) {
loadingMask();
}
return configs;
};
const responseInterceptor = (res) => {
const { code } = res.data;
const pages = getCurrentPage();
if (pages && pages.route) {
const r = !blockLoginPopList.includes(pages.route);
if (['200000', '200006'].includes(code)) {
uni.removeStorageSync('token');
}
}
return res.data;
};
const loadingMask = (opt = {}) => {
const o = {
...opt,
mask: true,
};
loading = false;
uni.showLoading(o);
};
const request = (options) => {
const { method, url } = options;
const requestConfig = requestInterceptor(options);
let requestId = generateId(method, url);
if (!requestId) {
return false;
}
return new Promise((resolve, reject) => {
uni.request({
...requestConfig,
header: {
token: uni.getStorageSync('token') || '',
},
success: (res) => {
const inter_res = responseInterceptor(res);
if (inter_res.code == '000000') {
resolve(inter_res);
} else {
console.log('request fail ', request, inter_res);
reject(inter_res);
}
},
fail: (err) => {
console.log('request fail ', request);
reject(err);
},
complete: () => {
setTimeout(() => {
loading = true;
}, 1000);
},
});
});
};
export { request };
请求方式
import { request } from '@/utils/http.js';
export const getData = (id) => {
return request({
url: `/xxxxxx/url`,
method: 'GET',
});
};
全局状态
vuex -> pinia (vue 官方推荐的状态管理库,更好的兼容性、更轻量化,打包完只有 1kb ) Pinia 语法有两种方式,一种是组合式,一种是选项式的;选项式的更好理解,所以这里使用的是选项式的。
import { createPinia } from 'pinia';
import { defineStore } from 'pinia';
export const useExpressStore = defineStore('myData', {
state: () => ({
data: {},
}),
getters: () => {},
actions: {
setData(data) {
this.data = data;
},
},
});
Mixins -> hooks
Mixins 存在很多缺点,比如说命名冲突,相互之间有依赖维护很麻烦等;所以摈弃 mixins,改成官方更推荐的 hooks
// 使用方式
import { useUserStore } from '@/store/index';
const userStore = useUserStore();
全局样式
全局样式统一放 style 里面
环境变量
环境变量使用 env 文件来控制,不同的 env 文件对应不同的环境变量
.env.development -> 开发环境
.env.test -> 测试环境
.env.custom -> 自定义环境
.env.production -> 生产环境
// 本地开发,mode 后加不同的环境,可以拿到不同的环境变量: development、test、prod
"dev": "uni -p mp-weixin --mode development",
获取环境变量
vite 不支持 process 环境变量获取方式如下:
const baseUrl = import.meta.env.VITE_APP_BASE_URL
相关的环境变量统一 VITE_ 开头
// 相关变量统一 VITE 开头
VITE_APP_BASE_URL=https://xxx.com
VITE_APP_ENV=dev
...
升级过程遇到的问题
- uni wx 等 not find
-
eslint.config.mjs文件配置{ globals: uni: true, wx: true }
- vue3 使用的是 vite ,不支持 commonJS, 所有的 require/module.export 方式都需要改成 import/export 的形式
- 下图原因一般是组件未注册造成的
- 在uniapp中vue3报错Cannot read property ‘route‘ of undefined
-
- 因为vue3没有this上下文,所以使用
uni.createSelectorQuery().in(this)时会出这个错误
- 因为vue3没有this上下文,所以使用
import {getCurrentInstance} from 'vue'
const instance = getCurrentInstance(); // 获取组件实例
const query = uni.createSelectorQuery().in(instance);
- uniapp小程序的全局弹窗解决方法 (基于 vite)
// vite.config.js
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni';
export default defineConfig({
plugins: [uni(), {
name: 'any name', // 插件名称
enforce: 'pre', // 插件的执行顺序, 我们需要再vite的核心插件前执行
// vite提供的钩子, 处理每个文件的时候都会触发一次改钩子
// code: string 为文件数据
// id: string 为文件路径
transform(code, id) {
// 过滤出page文件
if (/\.vue$/.test(id) && /\/pages\//.test(id)) {
/**
* 匹配开头的第一个标签 例:
* <template>
* <view>
*
* 然后在下面添加需要的全局组件
*/
code = code.replace(/[\s\S]+?<[\d\D]+?>/, _ => `
${_}
<YourComponent />
`)
return code
}
},
}],
})
- eslint 配置不生效
-
- 执行
npx eslint --debug .命令,查看当前配置是否正确 - 查看
eslint版本,我执行了npm init @eslint/config@latest自动升级了相关版本,然后配置eslint.config.mjs文件(vite 所以用的 mjs 文件),配置完之后重启就生效了 - 建议看官网文档
- 执行
import globals from 'globals';
import pluginJs from '@eslint/js';
import vueParser from 'vue-eslint-parser';
import pluginVue from 'eslint-plugin-vue';
export default [
{
files: ['**/*.{js,mjs,cjs,vue}'],
languageOptions: {
sourceType: 'module',
globals: { ...globals.browser, ...globals.node, uni: true, wx: true },
parser: vueParser,
},
},
pluginJs.configs.recommended,
...pluginVue.configs['flat/essential'],
{
rules: {
'vue/multi-word-component-names': 'off',
'vue/no-unused-vars': [
'error',
{
ignorePattern: '^_',
},
],
},
},
];
升级完前后对比:
vue3 包体积:
- dev: 3.37MB 主包: 2.54MB
- build:2.01MB 主包 1.52MB
vue2 包体积:
- dev: 11.50MB 主包: 5.52MB
- build:3.52MB 主包 1.99MB
参考:
如何使用ARMS前端监控开始监控微信小程序_应用实时监控服务(ARMS)-阿里云帮助中心
Uni App + Vue3 引入高德小程序插件Js文件失败_plugins: [″],引入高德失败-CSDN博客
vue3引入wxcomponents中有带import字样会报错 - DCloud问答