美文网首页
uni-app 填坑之旅

uni-app 填坑之旅

作者: 渚清与沙白 | 来源:发表于2023-10-11 09:45 被阅读0次

H5

  • 下载文件
    h5下载文件使用uni.downloadFile()有跨域问题,导致无法下载文件
    可以使用window.location.href=url方式解决
  • token失效拦截并登录
    根据token是否存在进行判断,是否跳转登录页面。
       uni.request({
            ...defaultOpts,
            success(response) {
                if (response.data.code === -1) { // token失效  跳转登录
                    // 避免一次请求多个接口,多次跳转登录页面
                    if (uni.getStorageSync('token')) {
                        uni.removeStorageSync('token');
                        uni.$emit('logout');
                        uni.navigateTo({
                            url: '../login/index',
                        });
                    }
                    reject(response.data);
                } else if (response.data.code === 1) {
                    resolve(response.data);
                } else {
                    if (!options.hasErrorTip) {
                        uni.showToast({
                            icon: 'none',
                            title: response.data.msg,
                        });
                    }
                    reject(response.data);
                }
            },
            fail(err) {
                console.log(err);
                uni.showToast({
                    icon: 'none',
                    title: '服务响应失败',
                });
                reject(err);
            },
            complete() {
                uni.hideLoading();
            },
        });
注意:
  1. 谨慎使用uni.redirectTo(OBJECT),首页请求接口时,登录页会将首页替换掉,无法进入游客模式,因为返回按钮不会显示。
  2. 使用uni.navigateTo(OBJECT),要注意重复跳转登录页的问题,可以通过uni.getStorageSync('token')是否存在来判断,不存在就不需要再跳转登录。
  3. 在H5上,浏览器可以刷新页面;刷新后,路由中只存在当前页面一个路由。首页或者其他页面均不存在,这种情况要考虑登陆成功回到首页的使用uni.navigateBack(),还是使用uni.switchTab(OBJECT)
 // #ifndef APP-PLUS
 // 非APP平台
 const pages = getCurrentPages();
   if (pages.length === 1) {
      uni.switchTab({
         url: '../home/index',
      });
    return;
  }
// #endif
uni.navigateBack();
  • loading加载框表现丑陋
    uni.showLoading(OBJECT)显示加载弹窗,在App上样式表现正常,在h5上很丑陋,无法满足需求。
    需要使用自定义弹窗。
  • 事件监听注册问题
    在首页,特别是有TabBar的首页,每个tab页面都需要注册和取消注册事件,否则其他tab页无法收到消息。
    例如:更新用户信息
    1. 在App上只需要在一个tab页注册监听,获取用户信息即可更新UI。
    2. 在h5上,A、B、C三个都是tab页,只在A页面注册了user监听。当用户在B或者C页面时,同时刷新了页面,导致当前路由中没有A,在登录成功后,发送user消息获取用户信息,A无法收到消息,B、C都未注册user消息,也就无法获取用户信息。所以,需要每个tab页都需要注册监听才能正常收到消息。
    onLoad() {
        uni.$on('logout', this.loginEvent);

        // #ifndef APP-PLUS
        uni.$on('user', this.getUserInfo);
        // #endif
    },
    onUnload() {
        uni.off('logout', this.loginEvent);

        // #ifndef APP-PLUS
        uni.$off('user', this.getUserInfo);
        // #endif
    },
  • 检测手机端、PC端
    使用ismobilejs库,根据navigator.userAgent来检测当前是否是手机端。如果不是手机端,在PC端访问h5 ,直接跳转到PC端的站点。
    检测位置在App.vue中的onShow函数
// 导入插件
  import isMobile from 'ismobilejs';
   onShow: function () {
        // #ifdef H5
        if (!isMobile(navigator.userAgent).phone) {
            // 重定向到另一个站点
            window.location.replace('https://www.xxx.com');
        }
        // #endif
        console.log('App Show');
    },
  • h5上,API uni.navigateBack() 的问题
    刷新一个二级页面,使用uniapp默认导航栏,右上角的按钮可以关闭页面同时回到首页。使用API uni.navigateBack();来关闭页面,无法回到首页,始终会跳转到当前页面。
    可以使用switchTab来回到首页,App也支持该API。
  • 浏览器自动填充账号和密码问题
    在页面中第一个密码框前面增加两个input组件,用于欺骗浏览器。这两个组件宽高设置为0,设置对应的type。
    第一个input组件用于填充账号,第二个组件用于填充密码。
            <!-- H5浏览器记住密码自动填充密码 -->
            <!-- #ifdef H5 -->
            <input class="w-0 h-0" type="text" />
            <input class="w-0 h-0" type="password" />
            <!-- #endif -->

scroll-view滑动问题

在带有TabBar的页面中使用scroll-view组件下拉刷新,出现上下滑动异常

  1. 在page.json文件中将该页面设置为禁止滑动disableScroll: true
  2. 指定scroll-view的高度

scroll-view高度计算

  1. 页面template的根view设定高度100%
  2. 计算高度。记住:使用100%去计算
// 第一步
.container {
    height: 100%;
}
// 第二步
.scroll-box {
   height: calc(100% - 258rpx);
}

uni-app中vh的理解

  • APP 和小程序的导航栏和 tabbar 均是原生控件,元素区域坐标是不包含原生导航栏和 tabbar的;而 H5 里导航栏和 tabbar 是 div 模拟实现的,所以元素坐标会包含导航栏和tabbar的高度
  • 为了优雅的解决多端高度定位问题,uni-app 新增了2个css变量:--window-top--window-bottom,这代表了页面的内容区域距离顶部和底部的距离
  • 举个实例,如果你想在原生tabbar 上方悬浮一个菜单,之前写 bottom:0。这样的写法编译到 h5 后,这个菜单会和 tabbar 重叠,位于屏幕底部。而改为使用 bottom:var(--window-bottom),则不管在 app 下还是在h5下,这个菜单都是悬浮在 tabbar 上浮的。这就避免了写条件编译代码。当然仍然也可以使用 H5 的条件编译处理界面的不同。
  • CSS 內使用 vh 单位的时候注意 100vh 包含导航栏,使用时需要减去导航栏和 tabBar 高度部分浏览器还包含浏览器操作栏高度,使用时请注意。

CSS 变量

--status-bar-height:系统状态栏高度
--window-top:内容区域距离顶部的距离,NavigationBar 的高度
--window-bottom:内容区域距离底部的距离,TabBar 的高度

image.png

App的包名

mainifest文件中配置AppId是__UNI__9204D49,App的实际包名则是uni.UNI920D49

页面滚动到目标view位置

  1. 给目标view设置id
    <view id="test" class="bg-bgColor">
  2. 给按钮添加事件
    @click="elementScroll('#test')"
  3. 根据id找到组件设置滚动距离
       elementScroll(selector) {
            const query = uni.createSelectorQuery();
            query
                .select(selector)
                .boundingClientRect((data) => {
                    let pageScrollTop = Math.round(data.top) + uni.upx2px(50);
                    uni.pageScrollTo({
                        scrollTop: pageScrollTop, //滚动的距离
                        duration: 100, //过渡时间
                    });
                })
                .exec();
        },
  1. 回到顶部
          uni.pageScrollTo({
                scrollTop: 0,
                duration: 100,
            });

process.env对象

uni-app中的process.env对象属性如下

{
    "NODE_ENV": "development",
    "VUE_APP_DARK_MODE": "false",
    "VUE_APP_NAME": "测试",
    "VUE_APP_PLATFORM": "h5",
    "VUE_APP_INDEX_CSS_HASH": "97465e7b",
    "VUE_APP_INDEX_DARK_CSS_HASH": "e6047db7",
    "VUE_APP_BASE_URL": "http://api.test.com",
    "BASE_URL": "/"
}

时间排序iOS兼容性问题

this.aar.sort((a, b) => {
  return new Date(b.createTime.replace(/-/g, '/')) - new Date(a.createTime.replace(/-/g, '/'));
});

媒体适配

template中使用了class样式img-boximg-topcode-view

<view class="flex justify-center img-box">
    <image class="img-top" src="@/static/imgs/img_ggyzm_ybd.png"></image>
</view>
 <view class="text-44 text-white flex justify-center code-view">确定</view>
<view class="text-32 text-898FA8 text-center mt-40 mx-40 pb-50">
      温馨提示: {{tips}}
</view>

使用media声明,注意screen是媒体的特性

@media screen and (max-width: 375px) {
    .img-box {
        padding-top: 60rpx;
    }
    .img-top {
        height: 330rpx;
        width: 300rpx;
    }
    .code-view {
        margin-top: 50rpx;
    }
}
@media screen and (min-width: 375px) {
    .img-box {
        padding-top: 180rpx;
    }
    .img-top {
        height: 420rpx;
        width: 380rpx;
    }
    .code-view {
        margin-top: 100rpx;
    }
}

自定义弹窗组件无法遮挡Tabbar的事件

方案:在Tabbar上层添加一层遮罩,禁止点击Tabbar。

let maskView = null;
export default {
  showMask() {
    if (!maskView) {
      maskView = new plus.nativeObj.View('maskTabarCar', {
        bottom: '0px',
        left: '0',  // 控制遮罩层起点
        height: '50px',
        width: '100%' // 设置遮罩层宽度
      })
      maskView.drawRect({
        color: 'rgba(255, 255, 255, 0)'
      })
      maskView.addEventListener('click', () => {
       // 遮罩层出发click事件
      }, false);
      //遮罩层显示
      maskView.show()
    } else {
      maskView.show()
    }
  },
  hideMask() {
    if (maskView) {
      //遮罩层关闭
      maskView.hide()
    }
  },
}

App多环境多域名打包

方案:采用离线打包来实现。

  1. 使用脚本生成本地App打包资源,脚本配置多个环境的打包命令
 "scripts": {
        "dev:h5": "cross-env NODE_ENV=development TAILWIND_MODE=watch UNI_PLATFORM=h5 vue-cli-service uni-serve --mode dev",
        "build:dev:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode dev",
        "build:test:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode test",
        "build:pre:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode pre",
        "build:release:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode release",
        "build:dev:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode dev",
        "build:test:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode test",
        "build:pre:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode pre",
        "build:release:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build --mode release"
    },
  1. 将打包出来的本地包资源拷贝到Android项目中,使用Android studio来打包。


    image.png

启动页取消转圈

     "app-plus" : {
        "usingComponents" : true,
        //设置 启动界面
        "splashscreen" : {
            "alwaysShowBeforeRender" : true,
            "waiting" : false,
            "autoclose" : true, //自动关闭启动页
            "delay" : 0
     },

alwaysShowBeforeRender:是否等待首页渲染完毕后再关闭启动界面
autoclose:是否自动关闭启动界面,仅当alwaysShowBeforeRender设置为false时生效,如果需要手动关闭启动界面,需将 alwaysShowBeforeRender 及 autoclose 均设置为 false。
waiting:是否在启动界面显示等待雪花

底部安全距离

在适配手机兼容问题上,有时需要处理底部安全距离。
当使用scroll-view时,往往需要设置高度。此时,需要考虑安全距离问题。

  1. 模板view:在scroll-view后面,增加<u-safe-bottom></u-safe-bottom>
  2. css:指定scroll-view高度,height: calc(100vh - 120rpx - env(safe-area-inset-bottom));

rich-text解析特殊符号‘<’出错

在使用<rich-text>组件展示HTML文本内容时,遇到内容中有小于等于(<=)的具有特殊含义的符号时,解析会出错,导致无法显示内容。

image.png
解决方案:查找全局的小于等于符号,进行替换。
err.msg.replace(/<=/g, '&lt;=')

当内容中有小于符号时,则无法进行替换,否则会将破坏其他HTML标签结构。

uQrcode 添加Logo

              <uqrcode
                    ref="uqrcode"
                    canvas-id="uqrcode"
                    :value="qrCode"
                    @complete="qrcodeGenerFinished"
                    :options="{
                        foregroundImageSrc: '/static/imgs/tab_order_sel.png', //logo
                        foregroundImageWidth: size / 3, //logo宽
                        foregroundImageHeight: size / 3, //logo高
                        foregroundImageBorderRadius: 35, //logo圆角
                        margin: 15, //二维码外边距
                        backgroundPadding: 10, //二维码内边距
                        areaColor: 'rgba(100, 100, 100, 0.5)', //二维码绘制区域颜色、底部背景色
                        foregroundColor: 'rgba(25, 147, 227, 0.5)',//二维码前景色  
                        backgroundImageSrc :'/static/mycenter/tab_order_sel.png',//背景图片
                    }"
                    :size="size">
                </uqrcode>

scroll-view滑动报错

image.png

解决方案:在<scroll-view @touchmove.stop>标签上添加@touchmove.stop可避免。

scroll-view水平滚动,子元素不能水平排列

1 查看文档:

  • 使用竖向滚动时,需要给 <scroll-view> 一个固定高度,通过 css 设置 height
  • 使用横向滚动时,需要给<scroll-view>添加white-space: nowrap;样式。
    2 子元素样式添加属性:display: inline-block;;或者使用<block></block>包裹子元素

相关文章

  • React Native填坑之旅--Button篇

    React Native填坑之旅--Button篇React Native填坑之旅--动画React Native...

  • React Native填坑之旅--动画

    React Native填坑之旅--Button篇React Native填坑之旅--动画React Native...

  • React Native填坑之旅--HTTP请求篇

    React Native填坑之旅--Button篇React Native填坑之旅--动画React Native...

  • 填坑之旅

    这篇文章主要是解决上一篇文章中存在Bug 上一篇文章中直接粘贴application.yml文件将会出现如下异常:...

  • 填坑之旅

    不知不觉,也填满了第二排小金币 代表3w(每周签三单)已经连续走了70周 曾经所有想象中的困难与艰辛 都如升级打怪...

  • Numpy小技巧学习历险记~~持续更新中....

    Numpy学习之旅,填坑之旅。欢迎留言补充*_<>_*。 1、numpy.random.shuffle()与num...

  • Spark填坑之旅

    0 背景 公司最近迁移 Hadoop 集群到堡垒机内部,我顺手把这些机器统一重命名了一下,折腾了几个小时,集群终于...

  • JNI 填坑之旅

    JNI 打包各种平台so文件配置在build.gradle中: 如上,在abiFilters中指定要打包输出的so...

  • uni-app开发,填坑记

    做webapp换了好多个框架,从MUI,到reactNative然后换到了uni-app 今天说下uni-app踩...

  • 填坑高手

    我的填坑之旅 2014马胜金融入坑 2015赚钱 2016掉坑 2017入坑3m 2017月入15万 2017年底...

网友评论

      本文标题:uni-app 填坑之旅

      本文链接:https://www.haomeiwen.com/subject/qapdddtx.html