1. 为什么要写这篇文章
鄙人有幸参与迭代版本中小程序接入原生直播的业务开发工作,在项目迭代过程中,遇见过许多“百思不得其解”的问题。
由于直播需要使用live-player
,而live-player
是微信原生组件,也就是层级是最高的,所以页面中的其他组件无论设置 z-index
为多少,都无法盖在原生组件上,所以小程序专门提供了cover-view
和cover-image
组件,可以覆盖在部分原生组件上面,在适配cover-view
的时候也是遇到了很多事情(坑?)
2. 基础介绍
1. 底层默认属性
cover-view {
display: block;
line-height: 1.2;
overflow: hidden;
white-space: nowrap;
pointer-events: auto;
font-family: -apple-system;
}
复制代码
2. 介绍
覆盖在原生组件之上的文本视图。
可覆盖的原生组件包括 map、video、canvas、camera、live-player、live-pusher
只支持嵌套 cover-view、cover-image,可在 cover-view 中使用 button。
3. Bug & Tip
3. 遇到的相关问题及解决办法
1. 字体被截断、显示不全问题(仅在iOS下会出现)
原因:iOS上计算宽高的问题
<cover-view class="row">
<cover-view class="btn">打开弹窗</cover-view>
</cover-view>
复制代码
.row {
display: flex;
align-items: center;
.btn {
+ padding: 0 20rpx;
color: #fff;
background-color: red;
}
}
复制代码
显示效果如下: 加了padding以后
解决办法:
在「打开弹窗」的文字后加入固定宽度的一个cover-view即可,也就是把父节点的宽度撑开。
<cover-view class="row">
<cover-view class="btn">打开弹窗<cover-view class="space" /></cover-view>
</cover-view>
复制代码
.row {
display: flex;
align-items: center;
.btn {
padding: 0 20rpx;
color: #fff;
background-color: red;
}
}
+ .space {
+ display: inline-block;
+ width: 2rpx;
+ line-height: 1;
+ }
复制代码
最终显示效果:
2. 嵌套cover-view时,自定义组件slot及父节点不支持wx:if进行隐藏和显示,否则不显示
<!-- page -->
<page-container id="container">
<cover-view class="page">
<cover-view class="row">
<cover-view class="btn" catch:tap="openModal"
>打开弹窗<cover-view class="space"
/></cover-view>
</cover-view>
</cover-view>
<modal visible="{{ visible }}" bind:on-close="closeModal">
<cover-view>我是弹窗的</cover-view>
</modal>
</page-container>
<!-- modal -->
<cover-view class="modal" wx:if="{{ visible }}">
<cover-view class="mask" catch:tap="closeModal"></cover-view>
<cover-view class="content">
<slot></slot>
</cover-view>
</cover-view>
复制代码
// modal
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.mask {
width: 100%;
height: 100%;
background-color: rgba($color: #000, $alpha: 0.4);
}
.content {
position: absolute;
top: 50%;
left: 50%;
background-color: #fff;
transform: translate(-50%, -50%);
}
复制代码
导致如下问题:
打开弹窗时,弹窗内部显示的slot不展示,当点击遮罩进行关闭弹窗时,会出现,弹窗关闭后,slot中的文字显示,然后消失。
所以只能将 wx:if 改为用css去控制 modal 的展示和隐藏,即使用display: block 和 display: none;
<cover-view class="modal {{ visible ? 'show' : '' }}">
<cover-view class="mask" catch:tap="closeModal"></cover-view>
<cover-view class="content">
<slot></slot>
</cover-view>
</cover-view>
复制代码
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
+ display: none;
}
.mask {
width: 100%;
height: 100%;
background-color: rgba($color: #000, $alpha: 0.4);
}
.content {
position: absolute;
top: 50%;
left: 50%;
background-color: #fff;
transform: translate(-50%, -50%);
}
+ .show {
+ display: block;
+ }
复制代码
3. 在cover-view中使用button
<cover-view class="action-contain action-button-class" bindtap="handleCloseAction">
<button open-type="share" class="action-item" bindtap="handleClickShare" data-type="action">
分享给朋友
</button>
<cover-view class="action-item" bindtap="handleGenerateImage">
生成分享图
</cover-view>
</cover-view>
复制代码
button在编译的时候,会自动在button下加入两层的cover-view,并会赋予一些自己的样式。
4. cover-image使用border-radius无效
如果想对cover-image使用border-radius,需要在cover-image外包一层cover-view,对cover-view进行使用border-radius,并且将cover-view设置overflow: hidden。
举个?
<cover-view
class="external-class cover-avatar"
style="height:{{ size }}{{ unit }};width:{{ size }}{{ unit }};{{ radius !== -1 ? 'border-radius:' + radius + unit + ';' : '' }};{{ externalStyle }}"
bindtap="onClick"
>
<cover-view
class="cover-avatar-container"
style="{{ radius !== -1 ? 'border-radius:' + radius + unit + ';' : '' }}"
>
<cover-image class="cover-avatar-image" src="{{ src }}" />
</cover-view>
</cover-view>
复制代码
.cover-avatar {
box-sizing: border-box;
border: 1rpx solid rgba(0, 0, 0, 0.05);
&-container {
width: 100%;
height: 100%;
overflow: hidden;
}
}
复制代码
5. cover-view设置overflow: scroll后,touchend事件不触发
<cover-view class="list" catchtouchend="handleTouchEnd">
<cover-view>
<cover-view style="display: flex">
<cover-view style="display: inline-block">
<cover-view class="item">代码片段是一种可分享的小项目,可用于分享小程序和小游戏的开发经验、展示组件和 API 的使用、复现开发问题等等。分享代码片段会得到一个链接,所有拥有此分享链接的人可以在工具中导入此代码片段。如果网页可点击的链接指向的是分享链接,那么点击链接也会自动打开工具进入代码片段导入页。使用最新版的开发者工具可以</cover-view>
</cover-view>
</cover-view>
</cover-view>
<cover-view>
<cover-view style="display: flex">
<cover-view style="display: inline-block">
<cover-view class="item">代码片段是一种可分享的小项目,可用于分享小程序和小游戏的开发经验、展示组件和 API 的使用、复现开发问题等等。分享代码片段会得到一个链接,所有拥有此分享链接的人可以在工具中导入此代码片段。如果网页可点击的链接指向的是分享链接,那么点击链接也会自动打开工具进入代码片段导入页。使用最新版的开发者工具可以</cover-view>
</cover-view>
</cover-view>
</cover-view>
</cover-view>
复制代码
.list {
width: 100%;
height: 300rpx;
display: inline-block;
overflow-y: scroll;
}
.item {
width: 100%;
white-space: normal;
}
cover-view {
line-height: normal;
overflow: visible;
}
复制代码
const app = getApp()
Page({
data: {
},
handleTouchEnd() {
console.log('end...')
}
})
复制代码
当cover-view设置滚动后,touch的相关事件触发会有问题,当未达到scroll的效果时,touch事件生效,当cover-view能进行scroll时,touch不生效,目前还未有解决办法。。。
7. 对cover-view进行wx:if判断
问题:隐藏时,cover-view只是做销毁处理,对性能并无太大影响,而对于显示Dom的时候,需要重新渲染整块的cover-view,对部分旧的手机有很大的性能消耗,会导致显示卡顿,显示类似于未做懒加载的图片一样,四面八方逐个开始渲染,display: block | none 与wx: if大同小异。
解决办法:不做wx:if的判断,对需要隐藏的cover-view不做销毁的处理,可使用css的属性去对dom节点的位置、属性做处理,如:left、opacity,如果在隐藏的dom节点中,有可点击的dom,则不可使用opacity。
4. 总结
涉及到原生组件相关的都需要使用cover-view和cover-image,当然这俩的问题也是比较多的,在进行使用的时候,要去阅读微信开放文档,测试时需用真机去进行测试,用开发者工具去进行开发的话,看上去一切都是没问题的,如果你换到手机上,那可能就会有很多问题了,开发完一个基础模块后,最好用真机去测试一下当前模块的功能是否符合逻辑。