记一次使用 uniapp 开发微信小程序遇到的疑难杂症
前言
记一次使用 uniapp 开发微信小程序遇到的疑难杂症
正文
swiper 滚动异常
在做列表的时候,很多情况下都是把类型放在顶部成为一个 tab ,然后左右滑动来切换列表。
在 uniapp 中,提供了一个 swiper 组件,它其实就是微信小程序中的 swiper 。
在使用 swiper 的时候,如果需要记录当前的 tab 值,则需要绑定 current
属性和 change
事件。
这里如果使用 change
事件,在开启 autoplay
或者连续快速滑动的情况下有很大概率在滑动的时候会出现 UI 错误。具体表现为晃动闪烁,相关的问题有
原因在微信小程序的文档里有说明:
解决方法是不要使用 change
事件,而是 animationfinish
事件来更新 current
的值
1 | <script setup> |
或者用第三个帖子中有个老哥回复的方法:
1 | <script setup> |
目前用的第一个解决方法,看起来似乎没有出现闪烁的情况了。
操蛋的开发者工具不会出现这个 bug ,只有真机的情况下有概率出现,麻了。
scroll-view 内 fixed 布局的内容在 IOS 下出现遮挡异常
如果要实现一个滚动列表,那么 uniapp 有一个 scroll-view 的组件可以作为滚动的容器,它在微信小程序中就是 scroll-view 。
在 IOS 中,如果在 scroll-view 中出现 position: fixed
布局( 一般为弹出层 )的元素的话,那么可能会出现遮挡异常的问题。
相关的问题有:
原因是 IOS 对添加了 -webkit-overflow-scrolling: touch
(滚动惯性)样式,他会和 position: fixed
发生冲突。
解决方法是将 -webkit-overflow-scrolling: touch
改为 -webkit-overflow-scrolling: auto !important
,如下:
1 | /* App.vue 内添加 */ |
这个用了之后确实有效果,弹出层不会被遮挡了。至于什么滚动惯性,体验更好,去他妈的,等客户提出来再说。
除了这个方法,也可以使用微信小程序的 root-portal 来模拟 position: fixed
。这样的话就不会被影响。
不过我用的组件库 sard-uniapp 似乎用的是 css fixed 的方案,并且我想还是尽量不使用一些特定平台的特性,所以我就直接用第一种方式了。
获取头像和昵称
当前的微信小程序已经不支持通过 wx.getUserInfo
来获取用户的头像和昵称了,调用 wx.getUserInfo
会返回统一的灰色头像和统一的昵称(微信用户),相关的链接为:小程序登录、用户信息相关接口调整说明 。
如果需要使用微信头像和昵称的话,需要通过 button 指定的 open-type
和事件来触发:
1 | <script> |
1 | <template> |
效果图可以在微信的文档中看到:开放能力/用户信息/获取头像昵称 。
获取手机号码
一般小程序会通过用户 unionID 或者手机号来区分唯一用户,在我这次做的小程序中,我们使用的是手机号。
在微信小程序中,需要通过 button 指定的 open-type
和事件来触发:
1 | <script> |
这里需要注意的是,可能组件库并没有将 open-type
作为 prop 传入,这时候要么自己用原生的 button 来写,要么就要把 button 当作 view 来使用。
这里我使用的是后面的方法,写成代码看起来如下(这里以登录为例子):
1 | <script setup lang="ts"> |
这里要注意的是 button 在微信小程序里面的默认样式的边框是通过伪类 ::after
来设置的,这里覆盖要从 ::after
覆盖:
1 | <style lang="scss" scoped> |
看起来不是很 nice ,但确实解决了所需的功能,如果你有其他的写法,欢迎评论!
识别 html 代码
在 H5 中,如果要识别一段 html 代码,一般我们使用 v-html
,或者直接通过 dom 操作( innerHTML
)
在 uniapp 中,我们依然可以用 v-html
,它在微信小程序中会被编译为 rich-text
,如下:
在什么情况下我们会要使用到这个特性呢,最常见的应该就是编写用户协议的页面。
1 | <script setup lang="ts"> |
上面的 v-html
在微信小程序中会被编译为一个 rich-text 子元素:
注意,如果需要识别 \n
之类的,需要使用 text 标签而不是 view 标签,在 view 标签中, \n
只会被识别为空格,而 text 才会识别为换行,例子如下:
1 | <script setup lang="ts"></script> |
效果如下:
rich-text
无法识别 \n
,会报错,如果 html 代码中混入了 \n
,则需要 replace
转化一下:
1 | <script setup lang="ts"></script> |
报错如下:
vue3 中通过 import 导入组件报错
在 uniapp 中,项目的目录几乎固定,在 components
中编写公共组件,在 pages
编写页面组件,这样子写不需要写 import 语句。
但某些时候我们需要对一个很长的页面需要拆开为一些局部的组件,这些局部的组件只会被一个页面使用,这时候如果我们使用 import 导入,则会报错:
1 | <!-- pages/test/index.vue --> |
这时执行 npm run dev:mp-weixin
之后,控制台就会显示一个报错:
这个问题目前看起来是 uniapp 的问题,相关 issue 为 #4952 。
解决方法有两个:
- 降低 uniapp 版本。
- 添加一个临时的 vite 插件。
依赖的版本这种基本不会乱改,所以这里我们用第二种方法,代码如下:
1 | import uni from "@dcloudio/vite-plugin-uni"; |
重新执行 npm run dev:mp-weixin
之后代码就不报错了。
键盘高度
当需要使用 input 弹出键盘的时候,我们需要注意键盘高度。
关于键盘高度有两个相关的属性:
- adjust-position
- cursor-spacing
一般而言只需要设置一下 cursor-spacing
即可,在我的项目中这个值为 40rpx
。
安全高度
在安卓和 iPhone 中,全面屏会有一个底部的线,这部分在正常情况下我们应该通过 css 来抬高相关的内容,避免和遮挡到内容
通过 css 的 env
来获取安全高度
1 | .safeHeight { |
这里的 safe-area-inset-bottom
就是底部的应该排除的高度
在模拟器中,可以切换机型来查看,比如切换成 iPhone X
当然,这个样式只在需要自定义底部样式的时候才有用,如果使用配置文件来生成 tabBar ,那么会自动抬高,就跟如上截图一样,
自定义底部的情况下,没有设置安全高度,则会出现下面的情况:
当你设置安全高度后:
在安卓手机中,似乎安全高度是系统层面会直接抬高,所以设不设置都没关系。
input 弹出键盘页面上移问题
在前面键盘高度一节,提及了两个属性 adjust-position
和 cursor-spacing
。
想象一下此时你正在编写一个聊天的界面,此时一般的布局是,使用纵向 flex ,顶部和底部固定,中间 flex-grow
设为 1 ,底部放置一个 input ,中间能够滚动查看消息。这时代码一般长下面这样子:
1 | <template> |
如果此时点击这个底部的 input 弹出键盘的时候,此时页面可能会造成整体上移,顶部会被上移到屏幕之外。
这时的解决办法是,将 adjust-position
设置为 false ,然后通过 input 的 keyboardheightchange
事件来获取键盘的高度,
1 | <script setup> |
这里需要注意要在 blur
事件里面重置 height ,不然某些情况下键盘收起后 keyboardheightchange
不触发导致 UI 异常。
后记
不得不说,uniapp 和微信开发者工具的配合真的很差,很多时候都是 uniapp 项目更改了某些文件,但是没有识别出来,导致微信开发者工具没法更新,有时又是 uniapp 改了某些文件,而微信开发者工具卡住,这时候就只能重启微信开发者工具。
只能说开发的感受真的让他发狂…