[toc]
# 1. 样式
# 1.1. fixed弹窗滑动时,下层页面也跟着滑动(穿透问题)
这里有篇文章 (opens new window)介绍的比较好。
对于uni-app来说,最简单的方法应该是第一种,在弹窗外层元素加上事件@touchmove.stop="preventTouchMove"
:
preventTouchMove() {
return;
},
如果弹窗内部有滚动元素,则在滚动元素外层用scroll-view
包裹。
这个 scroll-view 的子孙元素不能添加 overflow: auto,否则无法滚动。
另外,试了下在page-meta
上加上 page-style="height: 100%; overflow: 'hidden'"
是不生效的。
# 1.2. 安全区
h5的时候有下面的样式,就是处理ios的刘海屏。
body {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-left: env(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-right: env(safe-area-inset-right);
/* padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom); */
}
在小程序中,这段样式需要去掉,否则会在自定义导航栏下面出现一条白框。
在uni-app项目中,只要把上面代码移动到index.html
中就可以了,因为只有h5项目才会使用这个index.html
文件。
# 1.3. page-meta
<page-meta :root-font-size="fontsize+'px'"></page-meta>
page-meta只能是页面内的第一个节点,可以实现rem
# 1.4. slot问题
uni-app是支持具名插槽的,有一点需要注意,对于写在slot标签上的类名,h5会下发到slot内部的外层元素上,而小程序则会创建view元素,在这个元素上添加类名。
如果遇到slot的样式异常,可以先排查下这里。
举个例子:
<SomeComp class="extra">
<template #middle>
title
</template>
</SomeComp>
SomeComp组件内容如下:
<div class="inner">
<div class="middle">
<slot name="middle" />
</div>
</div>
在h5中会被渲染成:
<div class="extra inner">
<div class="middle">
title
</div>
</div>
在小程序会被渲染成:
<view class="extra">
<view class="inner">
<view class="middle">
title
</view>
</view>
</view>
子组件加上下面代码可以解决:
options: {
virtualHost: true,
},
# 1.5. 样式隔离
主要涉及 styleIsolation 属性。文档地址在这里 (opens new window)。
styleIsolation 选项支持以下取值:
- isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);
- apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
- shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用)
# 1.6. uni-app在h5端默认开启scoped
H5端为了隔离页面间的样式默认启用了 scoped,且无法取消
# 1.7. 不要在 class、style 中使用复杂对象
不能在 class、style 中直接使用 函数、data、计算属性 的对象,比如:
<div
:style="scheItemStyle[index]"
>
但是可以这样:
<div
:style="{ height: scheItemStyle[index].height }"
>
也就是使用某个具体的属性(字符串、数字等非引用类型类型),但不能是对象、数组等。
这种也不可以:
<div
:class="[
{'hidden-van-tabs': stageCfgList.length === 1},
]"
/>
这种可以:
<div
:class="[
{'hidden-van-tabs': isOnlyOneStage},
]"
/>
后面发现用字符串就可以了。
这样会报错
:style="getString(item,index)"
这样就不会
<div
:style="type === 'card'? getString(item,index): getString(item,index)"
/>
可以变通一下,这样也不会报错
<div
:style="true ? getString(item,index) : ''"
/>
# 1.8. v-if vs v-show
都知道v-show比v-if性能高,但是uni-app不支持v-show,对于dom节点特别大的页面来说,切换tab只能用v-show,v-if太卡。
这时可以用修改动态元素样式来实现,示例如下:
<div
:class="['double-fail-wrap', `double-fail-wrap-${curTab}`]"
>
<style lang="scss">
.double-fail-wrap-1 {
.loser-sche-map {
display: none;
}
}
.double-fail-wrap-2 {
.winner-sche-map {
display: none;
}
}
</style>
# 1.9. CSS变量
uni-app 中css变量可以用 page,在h5模式下会自动转成uni-page-body
,不能用:root
,小程序中不生效,如:
page {
// 修改switch的一些变量
--switch-width: 0.88rem;
--switch-height: 0.48rem;
}
# 1.10. 小程序中的:empty
问题
uni-app 小程序 :empty
,可能会存在问题,slot 即使父组件不传的情况下,还是会生成 <scoped-slots-label />
,导致永远不为空,无法命中 empty
。
# 1.11. 样式层级问题
有些组件不要加scoped,加了以后,外面的样式很难覆盖里面的。
比如组件内的这个样式
.press-popover--right.data-v-3fdac1da {}
比组件外的这个样式优先级高。
.popover-wrap .demo-nav-popover--right {}
这块总之很乱,要每个case去看。
# 1.12. rpx精度丢失
小程序 rpx 转 px 时会直接去掉小数点,导致赛程树错位,用原生 rem 解决
# 1.13. 自定义组件多节点带来的样式问题
自定义组件渲染差异
微信(可以使用virtualHost
配置)/QQ/百度/字节跳动这四家小程序,自定义组件在渲染时会比App/H5端多一级节点,在写样式时需要注意:
- 使用
flex
布局时,直接给自定义组件的父元素设置为·不能影响到自定义组件内部的根节点,需要设置当前自定义组件为display:flex
才可以。 - 在自定义组件内部设置根元素高度为
100%
,不能撑满自定义组件父元素。需要同时设置当前自定义组件高度为100%
才可以。
支付宝小程序默认启用了 virtualHost 配置不会插入节点,一般不存在如上问题。
参考:uni-app官网 (opens new window)
# 1.14. 条件编译
样式文件中的条件编译需要用/* */
包裹,不能用/** */
包裹。
下图左边不生效,右边才生效。
# 1.15. 样式转化
对page
设置的样式,在h5中会被转成uni-page-body
:
对html
和body
设置的样式,在小程序中会被转成page
:
对于这些容易造成歧义、容易产生误解,理解成本较高的转化样式,建议使用条件编译,只在本平台写本台可识别的样式,减少这种转化。
# 1.16. 多行省略号兼容性
不是uni-app
项目独有的问题,这里也记录下。
多行省略号只能支持 webkit
内核浏览器, IE系就不兼容,所以对于多行省略号是不能用stylelint
的默认规则。
- 溢出隐藏:
overflow: hidden;
- 省略号:
text-overflow: ellipsis; display: -webkit-box;
- 弹性盒模型:
设置弹性盒子的子元素的排列方式 :
-webkit-box-orient: vertical;
设置显示文本的行数:-webkit-line-clamp: 3;
(最多显示3行)
# 1.17. page大部分情况下都应该为overflow:hidden
# 1.17.1. page
移动端,不论是h5还是小程序,大部分页面应该设置为height: 100%;overflow: hidden;
,这样整个页面才不会跟着滑动,才不会漏出最底层,用户体验才好点。
如果是渐变式导航,则相反,page
需要设置为height: auto
,这样才会触发onPageScroll
事件。此外,想让page
滚动,那么page
下的第一层的高度要大于一屏才可以,也就是不能在demo-wrap
上设置height: 100%
,可以给height: auto
,或具体的高度。
除了需要onPageScroll
事件的,其他都建议page
设置为overflow: hidden
。
设置page
为overflow:hidden
还有个好处,不用再给page
设置额外的背景色了,反正看不见,只关心页面就行了,没铺满的就铺满即可。
# 1.17.2. demo-wrap
既然page
设置了overflow:hidden
,那么page
下的第一个元素如果超出了屏幕高度,则需要设置overflow: auto;height: 100%;
,否则就会显示不全。
如果不加demo-wrap
,则页面在h5下可以滚动,在小程序下不可以滚动。因为h5中uni-page-body
设置了overflow:auto
,而小程序没有这个中间层。
# 1.17.3. press-ui
对于press-ui
示例项目:
- H5中
html/body
设置了height: 100%;overflow:hidden
,uni-page-body
设置了height: 100%;overflow:auto
- 小程序中,
page
设置了height: 100%;overflow:hidden;
,页面顶层需要滚动的dom
,加上类名demo-wrap
,其样式为height: 100%;overflow: auto;
。
小程序下页面级别的vue
文件中,对page
的样式设置:
- 小程序下,不能加
scoped
,否则无效。 - H5下,加了
scoped
,page
转化的uni-page-body
样式是生效的。
# 1.18. 安全区
什么时候需要适配安全区呢,底部是tabbar
、购买按钮、输入框等不随页面滚动的元素。
# 1.19. 页面样式
归类,页面一定要有统一的包裹层class
。好处是方便维护。
# 1.20. 动态class
小程序不支持这个
:class="`tip-match-schedule-tab-item--scroll-${col - scrollTime}`"
但是支持这个
:class="[`tip-match-schedule-tab-item--scroll-${col - scrollTime}`]"
# 2. vant
# 2.1. van-tab
# 2.1.1. change事件参数
uni-app中 vant-tab 的change事件暴露参数为event,需适配
this.curTab = e.detail.name;
# 2.1.2. v-model无效
uni-app 中 van-tab 使用 v-model 无效,会被转为,所以必须要想拿到改变后的tab,要写change事件,因为 van-weapp 默认更新的是 active 属性。
<van-tabs active="{{ active }}" bind:change="onChange">
</van-tabs>
Page({
data: {
active: 1,
},
onChange(event) {
wx.showToast({
title: `切换到标签 ${event.detail.name}`,
icon: 'none',
});
},
});
# 2.1.3. 性能问题
tabMap[curTab]
不要写在 template 中,否则切换 tab 时会有延迟,也不要写在 computed 中,最好不依赖 curTab。
<!-- 存在问题 -->
<Comp
:list="tabMap[curTab]"
/>
<!-- 不推荐 -->
<Comp
:list="curList"
/>
computed: {
curList() {
const { tabMap, curTab } = this;
return tabMap[curTab]
}
}
更好的方式是不依赖curTab
:sche-list="stageScheMap[index]"