近一个月在做的小程序终于一期、二期都上线了,这算是我第一次使用uniapp来做微信小程序,中间踩的坑还是得记录总结一下。。。。
小程序开发之前的设计问题
交互体验
- 页面的跳转交互确认清楚
- 跳转之后返回数据是否更新
- 跳转之后返回滚动条是否需要停留在跳转之前的位置
- 跳转之后返回更新和保留数据的冲突是否考虑到
微信基础库版本
- 是否需要设置最低基础库版本
- 当基础库版本不满足的时候是否需要进行提示升级,限制使用,或者做一些兼容处理或者兜底处理
- 是否兼容电脑微信端
性能考虑
- 分包设计和配置 - 在uniapp中,属于tabbar对应的的页面不能放在分包中。
- 组件按需加载
- 图片压缩或者CDN
uniapp的使用问题
自定义导航栏
总结
- 在设计自定义导航栏的时候,需要考虑到页面滚动加载的时候导航栏是否需要滚动(和产品经理和设计师进行确认),以免不同的页面多人实现的布局差异比较大导致后期固定头部的实现代码繁琐冗余
- uni.getSystemInfoSync().statusBarHeight和uni.getWindowInfo()都可以可以获取不同机型的实际高度,在实现自定义导航栏的时候动态设置导航栏的安全高度。
- uniapp中的css变量--status-bar-height在微信小程序中是固定高度25px,在app中为手机实际状态栏高度 参考代码(简陋版)如下:
<template>
<view ref="custom-navigation">
<view class="custom-navigation">
<view class="status-bar-holder" :style="{ height: statusBarHeight }"></view>
<view class="status-bar-wrapper">
<image
src="/static/icon-back.png"
class="back-icon"
@click="pageBack()"
></image>
<text class="page-title-content">{{ props?.title??"页面标题" }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted} from "vue";
const props = defineProps(["title"]);
const statusBarHeight=ref('25px'); //因为微信小程序中的status-bar高度默认就是25
onMounted(()=>{
statusBarHeight.value=uni.getSystemInfoSync().statusBarHeight + 'px';
})
const pageBack = () => {
uni.navigateBack({
delta: 1,
})
}
</script>
<style scoped lang='scss'>
.custom-navigation {
position: relative;
padding: 0 30rpx;
box-sizing: border-box;
color: #0a1824;
.status-bar-holder{
height: var(--status-bar-height);
width: 100%;
}
.status-bar-wrapper{
width:100%;
display: flex;
flex-flow:row nowrap;
align-items: center;
justify-content: center;
height:88rpx;
font-weight: 600;
.page-title-content {
flex: 1;
text-align: center;
font-size: 32rpx;
}
}
}
.back-icon {
width: 40rpx;
height: 40rpx;
padding: 20rpx 30rpx 20rpx 0;
z-index: 99;
}
</style>
延伸:关于uniapp中的css变量和一些固定高度
uniapp中提供的内置的css变量除了--status-bar-height之外,还有--window-top和--window-bottom。--window-top表示内容区域距离顶部的距离,--window-bottom表示内容区域距离底部的距离。
CSS 变量 | App | 小程序 | H5 |
---|---|---|---|
--status-bar-height | - | 25px | 0 |
--window-top | 0 | 0 | NavigationBar 的高度 |
--window-bottom | 0 | 0 | TabBar 的高度 |
uniapp中某些组件的高度是固定的,不可修改,各小程序平台,包括同小程序平台的 iOS 和 Android 的高度也不一样。
组件 | 描述 | App | H5 |
---|---|---|---|
NavigationBar | 导航栏 | 44px | 44px |
TabBar | 底部选项卡 | 50px(但可以自主更改高度) | 50px |
关于tabBar
- 小程序和app在pages.json中配置tabBar,原生渲染提升性能,非必要不要使用自定义
- tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序
- tabbar 切换第一次加载时可能渲染不及时,可以在每个tabbar页面的onLoad生命周期里先弹出一个等待雪花
- tabbar 的页面展现过一次后就保留在内存中,再次切换 tabbar 页面,只会触发每个页面的onShow,不会再触发onLoad
- uni-app文档中提供的属性fontSize,iconWidth,spacing,height设置无效,uni-app编译至小程序app.json文件中没有对应属性
- 微信文档内tabBar的iconPath配置说明:icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片
- tabBar的图标设计时,建议四周适当留白,以免图片与文字挨的太近
- 跳转tabBar页面,使用API:switchTab();不能使用navigateTo(),会报错
关于滚动条
- 在onShow获取数据,页面会重新渲染且滚动到顶部,监听页面滚动事件onPageScroll获取保留滚动位置,但跳转其他页面返回后,触发页面onShow仍会滚动回顶部
关于小程序中获取组件宽度和高度
- vue语法ref无法在小程序中获取到DOM元素 - 这个原因其实我也不知道是为什么,尝试了各种ref绑定都不行
- 小程序中获取节点信息方法,主要用于操作DOM,设置滚动条的位置 主要使用uni.createSelectorQuery,vue2和vue3的使用是有差异的
<template>
<view class="wrapper"></view>
</template>
// vue2
<script>
const query = uni.createSelectorQuery().in(this);
</script>
// vue3
<script setup>
import { ref, getCurrentInstance,onMounted } from "vue";
const instance = ref();
onMounted(()=>{
const currentInstance=getCurrentInstance();
instance.value=currentInstance;
})
</script>
关于小程序转发
- 转发出来的卡片窗口的图片比例为5:4
- 非首页,非tabBar页面转发,点击进入后原生导航栏会自带返回首页的home Icon,自定义导航栏需自行处理,判断从转发进入,且添加返回首页功能
关于用户头像昵称
- 昵称填写能力,在开发者工具拿到input的值为空,要在真机才能拿到值
- 用户头像上传的域名要在小程序开发后台配置uploadFile合法域名
- 在PC端小程序头像昵称填写能力不起作用,原因PC端小程序基础库版本较低
- 昵称多次加载取消,会清空内容。是因为昵称填写 微信将异步对用户输入的内容进行安全检测,若未通过安全检测,微信将清空用户输入的内容。可用bindnicknamereview方法验证
- 小程序获取微信昵称后,用户再更改自己的微信昵称,小程序无法实时获取更改后的昵称。经实验延迟大概一天,小程序能获取到更改后的昵称。
小程序中的flex布局
- row-gap,column-gap小程序不生效,还未支持该属性(developers.weixin.qq.com/community/d…)
关于uniapp中的
组件的使用
- 如果模式设置为‘widthFix‘,有明确宽度的情况下,高度需要设置为height:auto,因为组件有默认的高度240px;
- 如果image样式生效慢,有时候会出现一闪而过或者出现压缩闪现的话,可以设置image{will-change:transform}来优化。 延伸阅读:CSS属性will-change
真机实践
长列表滚动加载,滚动条无法滑动
- 在滚动加载的页面,尤其是使用uniapp提供的页面触底加载(onReachBottom)的时候,一定要考虑到第一次请求的数据个数的展示需要超过一屏的高度(兼容各个机型),否则会出现刚好或者不够一屏导致无法滚动加载的场景。
小程序授权登录报错
- invalid code,需要从appid不一致和code重复消费两方面去确认
真机报错"errno": 600001
- 真机报错 "errno": 600001,"errMsg": "request:fail errcode:-105 cronet_error_code:-105 error_msg:net::ERR_NAME_NOT_RESOLVED" 是因为网络不通,如果是公司内网需要找运维人员开通内网权限
小程序轮播组件swiper的圆角失效
- 已设置圆角属性,在IOS上切换banner还是直角,除了设置border-radius和overflow属性外,还需添加transform: translateY(0);
关于详情图切割后的图片拼接成一张大图在某些机型上(如华为P40、P50)出现白线
第一种思路:
- image组件设置display:block;
- image拼接大图外层包裹容器设置font-size:0;
- iamge组件设置margin-top:-1px; 以上方法可以都设置一下。
第二种思路:
每个被切割的image组件外层包裹一个view容器,image组件上使用load事件,在图片加载完成的时候获取图片的高度,将小数向下取整之后将高度设置在image组件外层的容器上,外层的容器设置overflow:hidden。 参考代码如下:
<template>
<view class="detail-wrapper" v-if="imageData.length > 0">
<view class="img-wrapper"
v-for="(item, index) in imageData"
:key="index"
:style="{height:heightArr[index],width:`${screenWidth}px`}"
>
<!-- image默认的模式是不保持图片宽高比,完全填充至容器大小 -->
<image
class="sub-img"
:src="item.url"
:style="{height:heightArr[index],width:`${screenWidth}px`}"
@load="e=>handleLoad(e,index)"
></image>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
const props = defineProps({
imageData: Array
});
const systemInfo=uni.getSystemInfoSync();
const heightArr=ref([]);
const handleLoad=(e,index)=>{
const {width,height}=e.detail;
const {screenWidth}=systemInfo;
// 如果image组件的mode设置为widthFix,建议向下取整,因为在图片上设置style就不生效了
const realHeight=Math.ceil(screenWidth*height/width);
heightArr.value[index]=`${realHeight}px`
}
</script>
<style>
.detail-wrapper {
position: relative;
font-size:0;
}
.img-wrapper{
font-size:0;
overflow:hidden;
}
.sub-img {
width: 750rpx;
display: block;
border: 0;
}
</style>
鸿蒙系统下透明度的展示问题
- 不要用rgba方式,用opacity;
1rpx会在一些手机失效的问题
- 设计稿1rpx、2rpx建议直接用px