HBuilder X打包运行鸿蒙应用(vue2 -> vue3)

打印 上一主题 下一主题

主题 861|帖子 861|积分 2583

1. manifest.json配置为vueVersion: 3

2. main.js调解(下方已增补)

3. store调解

  1. import { createStore } from 'vuex'
  2. const state = {}
  3. const getters = {}
  4. const mutations = {}
  5. const actions = {}
  6. // 创建 Vuex Store
  7. const store = createStore({
  8.   state,
  9.   getters,
  10.   mutations,
  11.   actions,
  12. });
  13. export default store
复制代码
4. 增加入口文件index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.   <head>
  4.     <meta charset="UTF-8" />
  5.     <script>
  6.       var coverSupport = "CSS" in window && typeof CSS.supports === "function" && (CSS.supports("top: env(a)") || CSS.supports("top: constant(a)"));
  7.       document.write(
  8.         '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
  9.           (coverSupport ? ", viewport-fit=cover" : "") +
  10.           '" />'
  11.       );
  12.     </script>
  13.     <title></title>
  14.     <!--preload-links-->
  15.     <!--app-context-->
  16.   </head>
  17.   <body>
  18.     <div id="app"><!--app-html--></div>
  19.     <script type="module" src="/main.js"></script>
  20.   </body>
  21. </html>
复制代码
5. require方式调解为import导入方式

6. main导入uni.promisify.adaptor3-2.js uniapp Vue 3转Vue 2 API Promise 化调用效果的方式

API Promise 化 调用效果的方式
  1. // uni.promisify.adaptor3-2.js
  2. uni.addInterceptor({
  3.     returnValue(res) {
  4.         if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
  5.             return res;
  6.         }
  7.         const returnValue = [undefined, undefined];
  8.         return res
  9.             .then((res) => {
  10.                 returnValue[1] = res;
  11.             })
  12.             .catch((err) => {
  13.                 returnValue[0] = err;
  14.             })
  15.             .then(() => returnValue);
  16.     },
  17. });
复制代码
7. 项目运行,组件调解,样式调解,vue2组件升级为vue3组件;vue3不建议利用标签样式,比如p, img

8. jweixin-module等部分利用动态导入方式

  1. // loadJweixin.js
  2. xport async function loadJweixin() {
  3.     try {
  4.         // 动态导入 jweixin-module
  5.         return await import('jweixin-module');
  6.     } catch (error) {
  7.         console.error('Failed to load jweixin-module:', error);
  8.         throw error;
  9.     }
  10. }
  11. // main.js
  12. import App from "./App";
  13. // 全局状态管理
  14. import store from "./store";
  15. // #ifdef VUE3
  16. import { createSSRApp } from "vue";
  17. import "./uni.promisify.adaptor3-2";
  18. import uViewPlus from "@/uni_modules/uview-plus";
  19. // #ifdef H5
  20. import { loadJweixin } from "./utils/loadJweixin.js";
  21. // #endif
  22. // 不能修改导出的 createApp 方法名,不能修改从 Vue 中导入的 createSSRApp。
  23. export function createApp() {
  24.     // 创建应用实例
  25.     const app = createSSRApp(App);
  26.     // 使用 uViewPlus
  27.     app.use(uViewPlus);
  28.     // 设置全局配置
  29.     app.config.globalProperties.$store = store;
  30.     // #ifdef H5
  31.     loadJweixin().then((res) => {
  32.         app.config.globalProperties.$jweixin = res;
  33.     });
  34.     // #endif
  35.     // 忽略某些元素
  36.     // app.config.ignoredElements.push('wx-open-launch-weapp');
  37.     return {
  38.         app,
  39.     };
  40. }
  41. // #endif
复制代码
9. H5各个界面运行,出现异常进行代码调解

10. 适配小程序

11. 适配APP

12. 适配鸿蒙模仿器,以及处置惩罚tabbar界面不显示问题



  • a). 白屏不展示问题按照官网方式,注释pages.json,二分法测试各个界面
  • b). tabbar界面第一次不显示数据:第一次打开onShow不会实行,实行函数需要在onLoad内里
  • c). axios拦截器不支持,接口会没有相应
13. 华为安卓权限监听显示顶部蒙层,导入permissionListener.js文件,利用的uni.createRequestPermissionListener



  • a). 华为权限索取行为
  1. /**
  2. * @Author:liyuqi
  3. * @Date:2024-09-06 10:38:45
  4. * @LastEditors:liyuqi
  5. * @Description:uni.createRequestPermissionListener()
  6. * @Description:安卓权限说明顶部蒙层
  7. * @Description:文档地址:https://uniapp.dcloud.net.cn/api/system/create-request-permission-listener.html
  8. * @Description:注意:HBuilderX (4.0+) android 平台支持;HBuilderX 4.01 Vue2项目需要使用自定义基座测试监听权限申请的功能,标准基座暂不支持测试。
  9. */
  10. // #ifndef APP
  11. export default null;
  12. // #endif
  13. // #ifdef APP
  14. let permissionListener = null;
  15. // 是安卓平台,同时有uni.createRequestPermissionListener这个api
  16. if (getApp().globalData.isAndroid && uni.createRequestPermissionListener) {
  17.     permissionListener = uni.createRequestPermissionListener();
  18. }
  19. let canRunListener = true;  // 是否可以执行所有监听方法
  20. let canStopListener = true; // 是否可以执行取消所有监听方法,避免唤起权限会触发App.vue的onHide生命周期
  21. const permissionEnums = {
  22.     "ACCESS_COARSE_LOCATION": {
  23.         name: "定位",
  24.         explain: "展示附近店铺、填写收货地址等相关功能"
  25.     },
  26.     "ACCESS_FINE_LOCATION": {
  27.         name: "定位",
  28.         explain: "展示附近店铺、填写收货地址等相关功能"
  29.     },
  30.     "READ_EXTERNAL_STORAGE": {
  31.         name: "存储",
  32.         explain: "上传图片、上传视频等相关功能"
  33.     },
  34.     "CAMERA": {
  35.         name: "相机",
  36.         explain: "扫二维码、拍摄图片等相关功能"
  37.     },
  38.     "WRITE_EXTERNAL_STORAGE": {
  39.         name: "存储",
  40.         explain: "把图片保存到相册等相关功能"
  41.     }
  42. }
  43. /**
  44. * 权限说明文字
  45. * @param {String} permissionName  例如:ACCESS_COARSE_LOCATION
  46. */
  47. const texts = (permissionName) => {
  48.     let title = "";
  49.     let content = "";
  50.     let permissionInfo = permissionEnums[permissionName] || null;
  51.     if (permissionInfo) {
  52.         const { name, explain } = permissionInfo;
  53.         title = `${name}权限使用说明`;
  54.         content = `将获取${name}权限,用于${explain}`;
  55.     } else {
  56.         title = "";
  57.         content = "";
  58.     }
  59.     return {
  60.         title,
  61.         content
  62.     }
  63. };
  64. /**
  65. * 绘画顶部权限说明
  66. * 文档地址:https://www.html5plus.org/doc/zh_cn/nativeobj.html
  67. * @function drawView title标题,content描述使用说明
  68. * @function hideView 隐藏顶部权限说明
  69. */
  70. let view = null;
  71. const drawView = ({ title, content }) => {
  72.     console.log("drawView方法的参数值:", title, content);
  73.     if (view || !title || !content) return;     // 没有标题和内容则return出去
  74.     const { windowTop, windowWidth, statusBarHeight } = uni.getSystemInfoSync();
  75.     const topHeight = windowTop + statusBarHeight;
  76.     const distance = {
  77.         box: 10,    // 盒子距离视图两边的距离
  78.         text: 20    // 文字距离视图两边的距离
  79.     }
  80.     // 标题的相关样式
  81.     const titleStyle = {
  82.         size: 16,
  83.         height: 16,
  84.         top: `${topHeight + 22}`,
  85.         color: "#000",
  86.     }
  87.     // 内容的相关样式
  88.     const contentStyle = {
  89.         size: 14,
  90.         height: 0,
  91.         top: `${parseInt(titleStyle.top) + titleStyle.height + 6}`,
  92.         color: "#656563",
  93.     }
  94.     const contentLength = content.length;   // 权限说明内容文字长度
  95.     const contentWidth = windowWidth - distance.text * 2;   // 内容的宽度
  96.     const contentRowCount = Math.floor(contentWidth / contentStyle.size);   // 一行占几个文字
  97.     const contentRows = Math.ceil(contentLength / contentRowCount);     // 当前内容占几行
  98.     contentStyle.height = contentRows * (contentStyle.size + 4);    // 内容的高度
  99.     /**
  100.      * @description 计算盒子的高度
  101.      * 获取content到盒子顶部距离:parseInt(contentStyle.top) - topHeight - distance.box
  102.      * content的高度:contentStyle.height
  103.      * 获取content到盒子底部的距离:(distance.text - distance.box)
  104.      */
  105.     const boxHeight = (parseInt(contentStyle.top) - topHeight - distance.box) + contentStyle.height + (distance.text - distance.box);
  106.     view = new plus.nativeObj.View('per-modal', {
  107.         top: '0',
  108.         left: '0',
  109.         width: '100%',
  110.         backgroundColor: 'rgba(0,0,0,0.2)'
  111.     })
  112.     view.drawRect({
  113.         color: '#fff',
  114.         radius: '5px',
  115.     }, {
  116.         top: `${topHeight + distance.box}px`,
  117.         left: `${distance.box}px`,
  118.         right: `${distance.box}px`,
  119.         height: `${boxHeight}px`
  120.     })
  121.     view.drawText(title, {
  122.         top: `${titleStyle.top}px`,
  123.         left: `${distance.text}px`,
  124.         height: `${titleStyle.height}px`
  125.     }, {
  126.         size: `${titleStyle.size}px`,
  127.         align: "left",
  128.         color: titleStyle.color,
  129.         weight: "bold"
  130.     })
  131.     view.drawText(content, {
  132.         top: `${contentStyle.top}px`,
  133.         left: `${distance.text}px`,
  134.         right: `${distance.text}px`,
  135.         height: `${contentStyle.height}px`,
  136.     }, {
  137.         size: `${contentStyle.size}px`,
  138.         lineSpacing: "2px",
  139.         align: "left",
  140.         color: contentStyle.color,
  141.         verticalAlign: "top",
  142.         whiteSpace: "normal"
  143.     })
  144.     let timer = setTimeout(() => {
  145.         view && view.show();
  146.         clearTimeout(timer);
  147.         timer = null;
  148.     }, 200)
  149. }
  150. // 关闭顶部权限说明
  151. const hideView = () => {
  152.     if (view) {
  153.         view.hide();
  154.         view = null;
  155.     }
  156. }
  157. // 监听权限方法
  158. const listenerFunc = () => {
  159.     stopFunc();     // 取消所有监听方法
  160.     if (canRunListener && permissionListener) {
  161.         let permissionName = "";    // 权限名称
  162.         let hasConfirm = false;     // 是否有权限弹窗(触发permissionListener.onConfirm这个回调)
  163.         canRunListener = false;
  164.         canStopListener = false;
  165.         // 监听申请系统权限
  166.         permissionListener.onRequest((e) => {
  167.             console.log("permissionListener.onRequest回调:", e);
  168.             if (Array.isArray(e) && e.length > 0) {
  169.                 const stringToArray = e[0].split(".");
  170.                 permissionName = stringToArray[stringToArray.length - 1];
  171.                 console.log("权限名称:", permissionName);
  172.             }
  173.         });
  174.         // 监听弹出系统权限授权框
  175.         permissionListener.onConfirm((e) => {
  176.             console.log("permissionListener.onConfirm回调:", e);
  177.             hasConfirm = true;
  178.             if (permissionName) {
  179.                 drawView(texts(permissionName));
  180.             }
  181.         });
  182.         // 监听权限申请完成
  183.         permissionListener.onComplete((e) => {
  184.             console.log("permissionListener.onComplete回调:", e);
  185.             // e.length === 0:权限列表无值,则不继续做相对逻辑
  186.             if (e.length === 0) return;
  187.             let name = "";      // 权限名称
  188.             let explain = "";   // 权限说明
  189.             if (permissionName && permissionEnums[permissionName]) {
  190.                 name = permissionEnums[permissionName].name;
  191.                 explain = permissionEnums[permissionName].explain;
  192.             }
  193.             const Manifest = plus.android.importClass("android.Manifest");
  194.             const MainActivity = plus.android.runtimeMainActivity();
  195.             const permissionStatus = MainActivity.checkSelfPermission(Manifest.permission[permissionName]);
  196.             console.log("当前权限状态:", permissionStatus);
  197.             /**
  198.              * @description 永久拒绝该权限,则引导用户前往设置页
  199.              * permissionStatus != 0:权限状态是拒绝
  200.              * !hasConfirm:没有permissionListener.onConfirm这个回调
  201.              */
  202.             if (permissionStatus != 0 && !hasConfirm && name && explain) {
  203.                 uni.showModal({
  204.                     title: "温馨提示",
  205.                     content: `开启${name}权限后,才能${explain}`,
  206.                     showCancel: true,
  207.                     confirmText: "去设置",
  208.                     success: (res) => {
  209.                         if (res.confirm) {
  210.                             uni.openAppAuthorizeSetting();
  211.                         }
  212.                     }
  213.                 })
  214.                 return;
  215.             }
  216.             canStopListener = true;
  217.             hideView();
  218.         });
  219.     }
  220. }
  221. // 取消所有监听方法
  222. const stopFunc = () => {
  223.     if (canStopListener && permissionListener) {
  224.         console.log("执行permissionListener.stop()方法");
  225.         canRunListener = true;
  226.         hideView();
  227.         permissionListener.stop();
  228.     }
  229. }
  230. let exportObj = null;
  231. if (permissionListener) {
  232.     exportObj = {
  233.         listenerFunc,
  234.         stopFunc
  235.     };
  236. } else {
  237.     exportObj = null;
  238. }
  239. export default exportObj;
  240. // #endif
复制代码
导入方式
  1. // App.vue
  2. // #ifdef APP
  3. import permissionListener from  "./utils/permissionListener.js";
  4. // #endif
  5. export default {
  6.         onLaunch: function(options) {
  7.         },
  8.         onShow() {
  9.       // #ifdef APP
  10.       permissionListener && permissionListener.listenerFunc();
  11.       // #endif
  12.         },
  13.         onHide() {
  14.       // #ifdef APP
  15.       permissionListener && permissionListener.stopFunc();
  16.       // #endif
  17.     },
  18. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

郭卫东

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表