去除 image
标签自带的 margin-bottom 值
小程序 image
标签,html img
自带 margin-bottom 值,会导致和下边元素产生距离
- 方案一: 设置包裹
image
标签的容器cssfont-size: 0
- 方案二: 设置
image
标签的display:block
1rpx border ios真机显示不全问题
满足以下一种条件就出现bug
- 当标签的父容器宽度(单位rpx)÷2的值为 偶数或偶数.5 的时候会出现该bug,那么我们可以推到出用200.52=401,3022=604等等都会重现这个bug 导致左右边框可能显示不全 上下边框同理由于高度
- 当标签自身宽度(单位rpx)÷2的值为 偶数或偶数.5 的时候会出现该bug,那么我们可以推到出用200.52=401,3022=604等等都会重现这个bug 导致左右边框可能显示不全 上下边框同理由于高度
解决方案
- 改变宽高同时避免这两种情况出现,并且开发时 设置标签的宽高尽量 为 偶数
- 建议采用 transform: scale 实现 1px 边框
.border-1px {
width: 200px;
height: 50px;
position: relative;
}
.border-1px::after {
position: absolute;
content: '';
width: 200%;
height: 200%;
left: 0;
top: 0;
border-radius: 100px;
border: 1px solid red;
transform: scale(0.5);
transform-origin: left top;
}
iphone 上某些情况文字不能垂直居中
例如 设置 height
为 28rpx
,font-size
为18rpx
时文字始终无法在 border
内垂直居中对齐
解决方案:
将字体大小改为16rpx
或者以下。
暂时还没找到具体的规律,设计不同意将字体改下,最后解决是分andirod和ios分别设置不同的样式
iphone 上 textarea
设置padding
值无效导致文字间距无法和andirod展示一致
解决方案:区分 andirod 和 ios 系统设置不同的样式使得展示一致,例: andirod 的情况下可设置 pading
值,ios 下设置 positon:raletive
位移
动画设置技巧
当动画需要在动画完成前或者后不出现在页面内,可将动画初始位置置于视野外
强制开启同层渲染
使原生组件也可同层渲染,通过z-index控制层级
"window": {
"renderingMode": "mixed"
},
性能篇
- 简化需要展示的dom结构,例如长列表隐藏不在视窗内的元素
- 简化数据setData操作
- 拆分组件复用,图片资源压缩上cdn,小程序分包预加载
性能体验
-
不使用:active伪类,并使用hover-class替换:active
-
iPhone X 兼容
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
惰性函数的使用
获取某些耗时且不会更改的信息的时候可考虑使用惰性函数进行封装避免多次耗时操作
例:获取系统信息等
简易版
let systemInfo = null
function getInfo() {
if (!systemInfo) {
systemInfo = wx.getSystemInfoSync()
}
return systemInfo
}
惰性函数版:推荐
export let systemInfo = function() {
const res = wx.getSystemInfoSync()
systemInfo = function() {
return res
}
return systemInfo()
}
setData 数据量过大
当 setData 过大时会提示错误
vdSyncBatch 数据传输长度为 2260792 已经超过最大长度 1048576
因为setData设置的数据量是有限制的,单次设置的数据大小不得超过1024kb,否则就会出现如上错误
解决方案:将数组转成二维数组后进行setData,并且需要修改wxml的循环结构,多套一层循环。
伪代码
data:{
// 当前页数
pageNo:0,
// 数据源
list:[]
},
getListData:function(){
// 本次加载的数据
let _list = [];
...
setData({
['list[' + pageNo + ']']: _list,
});
}
超长滚动列表,上拉加载过多后内存溢出性能优化
当列表页面上拉加载数据到一定量时,占内存过高,导致小程序卡顿甚至黑屏关闭。
解决思路:让不在当前窗口区域内的内容wxml结构移除。
操作思路:封装一个列表item的容器组件,利用 createIntersectionObserver
的 relativeToViewport
的 observe
方法监听当前 item 所在位置,进行移除或者插入
核心代码
组件skeleton.wxml
<view class="list-item" id="list-item-{{uniqueId}}" style="min-height: {{height}}px;">
<block wx:if="{{showSlot}}">
<slot></slot>
</block>
</view>
组件skeleton.js
...
ready() {
// 修改了监听是否显示内容的方法,改为前后showNum屏高度渲染
// 监听进入屏幕的范围relativeToViewport({top: xxx, bottom: xxx})
const { windowHeight = 667 } = systemInfo()
const showNum = this.data.showNum //超过屏幕的数量,目前这个设置是上下2屏
try {
this.IntersectionObserver = this.createIntersectionObserver()
this.IntersectionObserver.relativeToViewport({
top: showNum * windowHeight,
bottom: showNum * windowHeight
}).observe(`#list-item-${this.data.uniqueId}`, res => {
let { intersectionRatio } = res
if (intersectionRatio === 0) {
console.log('【卸载】#', this.data.uniqueId, '超过预定范围,从页面卸载')
this.setData({ showSlot: false })
} else {
console.log('【进入】#', this.data.uniqueId, '达到预定范围,渲染进页面')
this.setData({
showSlot: true,
height: res.boundingClientRect.height
})
}
})
} catch (error) {
console.log(error)
}
...
获取自定组件节点实例
注意使用.in(this)
Component({
queryMultipleNodes (){
const query = wx.createSelectorQuery().in(this)
query.select('#the-id').boundingClientRect(function(res){
res.top // 这个组件内 #the-id 节点的上边界坐标
}).exec()
}
})
不常用参数
- EventChannel 页面间事件通信通道
只有 wx.navigateTo() 中可使用
示例代码
wx.navigateTo({
url: 'test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
//test.js
Page({
onLoad: function(option){
console.log(option.query)
const eventChannel = this.getOpenerEventChannel()
eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'});
eventChannel.emit('someEvent', {data: 'test'});
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
}
})