uni-app nvue页面position:sticky 与 bindingX相关冲突问题
uni-app nvue页面position:sticky 与 bindingX相关冲突问题
开发环境 | 版本号 | 项目创建方式 |
---|---|---|
Mac | 12.2.1 | HBuilderX |
产品分类:uniapp/App
PC开发环境操作系统:Mac
HBuilderX类型:Alpha
HBuilderX版本号:3.4.6
手机系统:Android
手机系统版本号:Android 11
手机厂商:小米
手机机型:Redmi K40
页面类型:nvue
vue版本:vue2
打包方式:离线
示例代码:
<template>
<scroller ref="page">
<refresh class="refresh" @refresh="onrefresh" @pullingdown="onpullingdown"
:display="page_refreshing?'show':'hide'">
<loading-indicator color="#999"></loading-indicator>
</refresh>
<view>
<view class="container">
<view class="navbar-box" ref="navbar" style="position:sticky;height:88px;width:750rpx"></view>
</view>
</view>
</scroller>
</template>
```javascript
onReady() {
this.navbarHeight = plus.navigator.getStatusbarHeight() + (this.systemInfo.platform == "ios" ? 44 :
48)
let that = this
setTimeout(() => {
let navbar = that.getEl(this.$refs.navbar)
let page = that.getEl(this.$refs.page)
var gesTokenObj = BindingX.bind({
anchor: page,
eventType: 'scroll',
props: [{
element: navbar,
property: 'opacity',
expression: `1-(abs(y)/${that.navbarHeight})`
}]
}, function(e) {
console.log(e)
console.log("1",navbar)
console.log(that.$refs.container)
});
this.navbar_active = gesTokenObj.token;
}, 300)
},
```
操作步骤:
```
看看下拉和上拉效果
```
预期结果:
```
理论上不应该有两个能显示到视图层的navbar 但是更不应该ref选择不上后浮上来的navbar
```
实际结果:
```
不管用户如何滑动都可以根据该表达式改变navbar的透明度
```

bug描述:
```
1.对于nvue 的position:sticky 的元素 会形成上下两层
在页面初始化时会显示其中一层,在页面下滑后会显示另外一层(这个很容易测试,我就不贴代码了,不加背景不加background,把opacity设置上就能看到有重叠的两个了,现在是Android发现了ios还没进行测试)
2.如第一条所说,这个情况会产生两个节点,而且当给节点赋予ref属性时在onReady事件选择bindingX的token后绑定相关视觉表达式仅会在页面第一次进入后在未执行上滑操作前执行的下拉刷新操作会对该节点生效。(个人感觉其实是生效了,但是生效的是已经被压在后面的那个节点)
确实是Android平台实现sticky的机制存在的问题,目前暂时只能设置停靠区域不使用透明背景色避免。
后续我们会改进优化,但还没有具体的时间点。
谢谢回复。这个问题通过用bindingX的transform变着法的实现sticky逻辑的给强行解决了一下,现在看起来没什么大问题就是没具体测试性能。
在 uni-app
中使用 nvue
页面时,position: sticky
和 bindingX
可能会产生冲突,导致布局行为不符合预期。以下是一些可能的原因和解决方案:
1. position: sticky
的工作原理
position: sticky
是一种混合定位方式,元素在滚动到某个阈值之前表现为相对定位(relative
),之后表现为固定定位(fixed
)。它依赖于父容器的滚动行为。
2. bindingX
的作用
bindingX
是 nvue
中用于实现复杂动画和交互的机制,它允许你通过表达式绑定元素的样式属性,从而实现更灵活的动画效果。
3. 冲突原因
position: sticky
依赖于浏览器或原生容器的滚动事件来计算元素的位置,而 bindingX
则通过直接操作元素的样式属性来实现动画效果。当两者同时作用于同一个元素时,可能会导致样式计算的冲突,使得 position: sticky
无法正常工作。
4. 解决方案
方案一:避免同时使用 position: sticky
和 bindingX
如果可能,尽量避免在同一个元素上同时使用 position: sticky
和 bindingX
。你可以考虑通过其他方式实现类似的效果,例如:
- 使用
scroll
事件手动控制元素的定位。 - 使用
transform
或translate
来实现动画效果,而不依赖bindingX
。
方案二:手动实现 sticky
效果
你可以通过监听滚动事件,手动计算元素的位置,并根据滚动距离动态调整元素的 top
或 transform
属性,从而实现类似 sticky
的效果。
// 示例代码
onPageScroll(e) {
const scrollTop = e.scrollTop;
const stickyElement = this.$refs.stickyElement;
const stickyThreshold = 100; // 阈值
if (scrollTop > stickyThreshold) {
stickyElement.style.transform = `translateY(${scrollTop - stickyThreshold}px)`;
} else {
stickyElement.style.transform = 'translateY(0)';
}
}
方案三:使用 weex
原生的 sticky
组件
如果你的 nvue
页面是基于 weex
的,你可以尝试使用 weex
原生的 sticky
组件来实现 sticky
效果,而不是依赖于 position: sticky
。
<template>
<sticky>
<view class="sticky-content">Sticky Content</view>
</sticky>
</template>