要拿捏局部优化和系统优化
文章简单记录下,小程序自定义tabbar结构设计优化,导致的多页面代码变更的问题,和解决思维的变化
背景
全局layout组件有个error-page样式会覆盖住自定义tabbar,需要解决
自定义tabbar组件目前是在各个页面引用的,而不是统一在公共的layout组件使用,这个属于历史原因了,所以就有这个问题了
这里有个小点:微信小程序的app.json的tabbar可支持放入5个以上的页面,这些页面将会拥有switchTab的切换效果,但底部tabbar只能展示5个
原先代码case
<!-- index页面 --!>
<layout>
<view>
<!-- content --!>
</view>
<tabbar />
<view style="height:50px"></view>
</layout>
<!-- layout组件代码 --!>
<view>
<view class="content-page">
<slot />
</view>
<view class="error-page" wx:if="{{ showErrorPage }}">
接口报错啦
</view>
</view>
<style>
.content-page {
z-index: 1;
position:relative;
}
.error-page {
z-index: 2;
position: fixed;
height: 100vh;
background-color: #fff;
}
</style>
其实主要本质上是因为tabbar位置放错了,应该得把tabbar组件放到layout组件,而不是放到页面里,这样就能和error-page保持同级,从而不会被盖住,如下:
<!-- layout组件代码 --!>
<view>
<view class="content-page">
<slot />
</view>
<view class="error-page" wx:if="{{ showErrorPage }}">
接口报错啦
</view>
<tabbar />
<view style="height:50px"></view>
</view>
为什么要说他呢,因为一开始我其实不敢把这个自定义tabbar放在layout里,我的想法是能简单就简单,能少改动就少改动,能不影响之前的就不影响之前的。
也就是一开始想“局部修补”,但发现在复杂结构中,局部修补只会带来更多局部修补。
所以一开始我的解决的切入点就是error-page和content-page这俩部分,比方说
-
error-page判断有没有自定义tabbar,动态变更高度:calc(100vh - 50px),50px是自定义tabbar高度,因为error-page是fixed+100vh,所以他就盖住了自定义tabbar- 这里有个点,虽然
自定义tabbar层级可能很高,但error-page最终的层级比较还是content-page
- 这里有个点,虽然
-
考虑到
content-page设置了z-index,所以可以把content-page的z-index``设置为unset,这样error-page就能和自定义tabbar进行比较了,从而自定义tabbar不会被盖住
以上2点,就是我一开始解决时想到的点
这里说明下三个方案的优缺点,加上抽取自定义tabbar放到layout的方案
| 方案 | 改动成本 | 可维护性 | 健壮性 | 长期收益 |
|---|---|---|---|---|
❌ 高度调整 error-page | ✅ 低 | ❌ 差 | ❌ 差 | ❌ 差 |
| ❌ unset z-index content-page | ✅ 低 | ⚠️ 一般 | ⚠️ 一般 | ❌ 差 |
| ✅ 移动 tabbar 到 layout | ❌ 高 | ✅ 好 | ✅ 好 | ✅ 高 |
这里的主要问题就是:对原结构进行妥协,没有要做到系统性优化
只是把当前问题解决了,他带来的隐藏问题还需要一个一个页面进行查看,那这就和重新优化tabbar引入位置带来的问题一样,也需要一个个页面查看,既然投入的成本类似,那为什么不尝试用更好的办法呢,优化系统结构
不过呢,局部优化和整体优化有时候是有一定的取舍的,也就是不是完全反对局部优化,需要看情况,总结就是
- 结构有误、问题普遍、未来可期 ⇒ 优化结构
- 影响到了全部页面,每个页面都可能有类似问题等,后期也有类似问题等
- 局部异常、代价可控、生命周期短 ⇒ 优化局部
- 比方说,只有一个页面有问题,或者需要紧急上线
问题&设计
以上是背景,接下来就是一些问题&设计
iphone安全距离
| 项目 | constant() | env() |
|---|---|---|
| 状态 | 已废弃 | ✅ 推荐 |
| 兼容性 | 老版 iOS Safari(12 及以前) | iOS 11.2+,现代浏览器支持 |
| 用法 | constant(safe-area-inset-bottom) | env(safe-area-inset-bottom) |
其他可用安全距离
| 变量名 | 含义 |
|---|---|
safe-area-inset-top | 顶部安全距离(刘海/状态栏) |
safe-area-inset-bottom | 底部安全距离(Home Indicator) |
safe-area-inset-left | 左边安全距离(圆角屏) |
safe-area-inset-right | 右边安全距离(圆角屏) |
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
自定义tabbar引发的一系列高度问题
原先页面中都有一段这样的代码,height: 50px起一个占位作用,因为tabbar是fixed布局
<tabbar />
<view style="height:50px"></view>
现在放到了layout组件里
<!-- layout组件代码 --!>
<view>
<view class="content-page">
<slot />
</view>
<view class="error-page" wx:if="{{ showErrorPage }}">
接口报错啦
</view>
<tabbar />
<view style="height:50px"></view>
</view>
为什么要说这个呢,因为页面里有些样式会这么写
.my-content-page {
height: 100vh
}
此时把自定义tabbar组件移到layout组件里,和content-page保持同级,就会导致height: 100vh多了50px,会影响滚动或者其他的样式,所以原来的页面需要减掉50px
layout怎么判断是否展示自定义tabbar
这里推荐使用每个页面传递参数的方法进行标识
<layout is-tab-bar-page="{{ true }}"></layout>
这样layout可以更快的判别是否渲染自定义tabbar,核心原因是微信小程序的组件的生命周期原因
微信小程序的组件的生命周期:created -> attached -> ready
简单理解可以看成vue的生命周期,比如
beforeCreate -> created -> mounted
我在created环节就能拿到props数据了,从而更快的判别是否渲染自定义tabbar
还有个方法可以判别:
可以在mounted(ready)环节,获取页面实例,获取页面名、页面路径,判断是否在tabbar,从而判别是否渲染自定义tabbar
但他是在mounted环节判断的,速度要比beforeCreate(created)慢,所以推荐向子组件传参
我这里的欠缺点,没有考虑到生命周期的影响,我一开始采用的是后者,进行代码review后使用了前者,所以记录下
按钮点击没有反应
这算是个历史bug,刚好讲讲,个人的解决思路,顺便记录下,代码case
api.submit().then(res => { wx.navigate({ url: 'pages/index/index' }) })
手机上看到时,发现点击没反应,没有报错提示,也没有跳转,那么至少可以简单的分析出来,接口可能发生了点问题,从而没有走进跳转逻辑
至于报错提示没有,需要了解处理请求返回结果的逻辑怎么做报错提示的
我这里的代码是只对个别错误码进行了toast提示,个别没有,那接下来该怎么办,复现又不好复现
此时需要让后端人员,查一下接口日志,看看有没有发起请求、请求报错等
我这里得到的结果就是————没有登录。
考虑到,我页面初始化就会判断是否登录,没有登录就会发起登录,所以这里需要分析下,为什么会没有登录,token问题还是什么问题,这就需要让后端人员看了
我这里的欠缺点:KiBanba不熟悉、对没有登录不敏感(因为页面初始化就会发起登录,所以就得确认,是不是token过期了,或者后端逻辑问题等)
面对问题的解决思路
刚好在整理一下问题的解决思路
广泛来说:个人解决 -> AI解决 -> google、社区、issue解决
问题现象有很多:接口报错、没反应、页面加载速度慢、控制台报错、页面异常等
这里主要说明个人解决思路,以我的error-page覆盖问题来说明
- 问题是什么,描述问题现象
- 寻找触发问题的代码,可以通过接口、控制台、现象展示分析
- 判断这是前端问题还是后端问题
- 分析造成问题的核心原因,局部方面,系统方面,要带着全局观来看,可以查日志,复现问题环节,调试等等
- 提出、评估解决问题的手段,有时候还需要大胆猜测,小心求证
- 实践
如果是诡异的问题,可以多多比较,二分法等,比较可以比机型、环境、参数、版本等
如果有解决不了的问题,需要带着代码执行流程的进行模拟一遍,然后分析
考虑到代码中会有一些常用的封装逻辑,比如公共layout、公共请求、main.js等,这些也是需要注意的,总之而言,带着代码执行流程去分析,比方说一个接口发起的代码执行流程:按钮触发事件 -> 公共请求 -> 回调
总结
多多复盘,查漏补缺,沉着冷静,带着代码流程去分析,保持怀疑