昨天在写一个小程序时,做了一个带吸顶的效果,亲测有效。看到网上很多都不能兼容安卓机,这个可以,随便滑,无论快慢。github地址:https://github.com/yangdongMC/caas.git(如果有用,欢迎给个star)
所有尝试方法:
需求是一个导航栏,页面滚动后吸附到顶部,兼容安卓。 尝试的方法有:
1.css position: sticky ( 安卓机内小程序内核有时支持,有时不支持)
2.onPageScroll 方法中根据scrollTop切换 fixed or relative,勉强可以实现,安卓机卡得飞起
3.结合scroll-view 标签,安卓机也是卡的飞起,在原生小程序中这个写很流畅。
4.wx.createIntersectionObserver 用这个方法,固定结构,么有请求,很流畅,效果很好,页面onLoad里面如果加个请求,渲染列表,安卓机也是卡的飞起。请问一下有做类似的功能吗?
5.以上实现都是使用wepy框架,最后尝试小程序原生实现
2018年9月18日重新修改:
- 能兼容安卓机的请按参照下面的,最后面的是css写法,在安卓机中不能实现。
2018年9月21日再次修改:
原因是createIntersectionObserver与请求一起初始化执行,不论先后,js线程队列中存在多个计算,此时安卓机小程序中也很卡,当然是基于了wepy框架的开发(不确定,考虑方向)
2.但是看那些大厂实现了小程序吸顶,很想一窥究竟,于是我就扒起了某小程序的源码,就是用原生写的,也就是我所有尝试方法中的第三条。思考一番:框架很好,但是现在的小程序原生生态更好。
2018年9月24日最终版修改:
1.起初,我怀疑是wepy框架的赋值造成的计算比原生的慢(猜测),于是我看了考拉严选砍价助手的源码(中秋假前2天,一直在看,代码被转译了,有点难看懂),我有猜测是这些大厂引用了自己的js来实现安卓机的兼容,第一天还是这么认为的 ,但是第三天早上证实了不是这样的,安卓机就是实现不了快速的计算、响应
2.实现方案是:请参考小程序优化关于setData,要想实现吸顶并兼容安卓;一是:要么需求是固定的数据(不是动图加载的大量数据,比如说一个带跳转链接的提示,);二是:跟考拉严选砍价一样,接口数据量小,14条,字段少,这样不会造成大量的计算,(合理的安排产品,意思就是你在小程序中,比如一个页面想做吸顶+动态请求数据,那么建议你就去加载小批量的数据,如果还有其他的请求,你这个吸顶效果在安卓中绝对卡的飞起。);三是:使用web-view来引用你的这个页面,当然就不存在固定、限制数据这么一说,(京东优惠小程序的吸顶就是这么干的)
总结:
1.现在有这个需求的小程序不多,我所看过的有考拉严选砍价、京东优惠、美团外卖、优衣库,其他的(扫了大概70多个小程序)都没有这么个吸顶的功效。
2.吸顶效果不区分框架还是原生,如果有这个需求,请参考上面的3次修改,会让你节约很多时间,还可以跟产品切磋一下。
3.如果大佬有解决方案,欢迎留言。
- 目前小程序中webview绝大多数是基于chrome 53版本的内核,是不支持sticky的
- 安卓原生的scroll会触发大量的计算,BFC不会触发(没搞明白),
下面是兼容安卓新一版的实现方式:
<style>
.noneClass {
height: 45px;
line-height: 45px;
color: #999;
width: 100%;
position:fixed;
top:0;
background-color:#fff;
display:none;
}
.nav-list{
height:45px;
line-height:45px;
background-color:#fff;
}
.show{
display:block;
}
.chosed{
display:inline-block;
width:25%;
}
#back{
height:250px;
background:#ddd;
}
.scrollClass{
position:fixed;
top:0;
background:#fff;
}
</style>
<template>
<view class="container">
<view id="back" class="banner">
<image src="https://upload-images.jianshu.io/upload_images/985352-9d89c4178ac72ab3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700/format/webp" style="height:250px"></image>
</view>
<view class="nav-list">
<view class="chosed">洗剪吹</view>
<view class="chosed">美甲</view>
<view class="chosed">烫染护</view>
<view class="chosed">美容</view>
</view>
<view class="noneClass {{scrollClass?'show':''}}">
<view class="chosed">洗剪吹</view>
<view class="chosed">美甲</view>
<view class="chosed">烫染护</view>
<view class="chosed">美容</view>
</view>
<view style="height:100vh;background-color:#eee">热议度</view>
<view style="height:50vh;background-color:#efefef">二楼</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class Index extends wepy.page {
config = {
navigationBarTitleText: '丽人'
}
data={
scrollClass: false
}
onLoad() {
let me = this
let observer = wx.createIntersectionObserver()
observer.relativeToViewport({top: -50}).observe('.nav-list', (res) => {
// res.intersectionRect.top 相交区域
if (res.intersectionRect.top === 0) {
me.scrollClass = true
me.$apply()
} else {
me.scrollClass = false
me.$apply()
}
})
}
onPageScroll = (e) => {
}
}
</script>
下面是css实现方式,安卓机:微信中可以,小程序中不行
.
概览:
介绍一下我的机型:
名称:华为荣耀8
内核:4.1.18-ga5ff2c9 android@localhost #1
Android版本:7.0
用它测试很多问题都出现了,用起来卡的半死,简直就是弱鸡?..
下面是实现方法:
.
//home
<template>
<view id="home">
<table></table>
</view>
</template>
<script>
import Table from '../components/home/table'
export default class Home extends wepy.page {
config ={
navigationBarTitleText: '榜单'
}
data={
android: false, // 获取设备是ios还是android
ios: false
}
components={
table: Table
}
onLoad =() => {
this.$invoke('table', 'fetchList', this.platform)
// 判断当前设备
let u = wx.getSystemInfoSync()
let isAndroid = u['system'].indexOf('Android') > -1 || u['system'].indexOf('Adr') > -1
let isiOS = u['system'].indexOf('iOS') > -1
this.android = isAndroid
this.ios = isiOS
this.$broadcast('fixSuctionTop', this.suctionTop, this.android, this.ios)
}
onPageScroll = (e) => {
if (e.scrollTop > 170) {
this.suctionTop = true
this.$broadcast('fixSuctionTop', this.suctionTop, this.android, this.ios)
} else {
this.suctionTop = false
this.$broadcast('fixSuctionTop', this.suctionTop, this.android, this.ios)
}
}
}
</script>
//table
<style>
.tab_header{
display:flex;
background-color: #00a2ff;
font-size: 0.8rem;
color: #fff;
height:2.3rem;
line-height:2.3rem;
}
.sticky{
position:-webkit-sticky;
position:sticky;
top:0;
left:0;
z-index:9999
}
.fixed_top{
position:fixed;
width:100%;
left:0;
top:0;
}
</style>
<template>
<view wx:if="{{ios}}" class="tab_header {{scutionTop?'fixed_top':''}}">
<view wx:for="{{header}}" wx:for-item="item" wx:key="item.value" wx:for-index="idx" style="width:{{item.width}};text-align:{{item.textAlign}}">
<view class="header_title">{{item.name}}
<image src="./img/class_square.png"></image>
</view>
</view>
</view>
<view wx:if="{{android}}" class="tab_header sticky">
<view wx:for="{{header}}" wx:for-item="item" wx:key="item.value" wx:for-index="idx" style="width:{{item.width}};text-align:{{item.textAlign}}">
<view class="header_title">{{item.name}}
<image src="./img/class_square.png"></image>
</view>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class Table extends wepy.component {
/**
*table组件内进行渲染list列表,从父组件获取不同的参数
*/
data={
scutionTop: false,
android: false,
ios: false
}
events={
fixSuctionTop: (scutionTop, android, ios) => {
this.scutionTop = scutionTop
this.android = android
this.ios = ios
}
}
}
</script>
总结:
1.判断到一定的点替换class
2.替换的时候会因为机型对css兼容不同,需要区分开来使用不同的css class
3.初始化加载判断机型