uni-app导航栏+swiper,及处理滑动冲突

第一部分:swiper + 顶部/底部导航栏实现

这里的思想与安卓的fragment+viewpager是很类似的,用swiper作为左右滚动区间,联动tab导航栏,中间展示内容组件化

整体布局

导航栏部分大家可以自定义,我整个界面采用的是底部导航栏用position:fixed浮动,swiper部分的current注意是与tab的下标一致,并且注意swiper的高度一定要动态自适应,这个等下滑动冲突会讲到。swiper-item内部内容是抽成组件化了,这样代码看着更整洁规范,注意内部class一定要写。

组件化,刚开始swiperHeight你们可以用500之类的
方法

一个简单的swiper联动导航栏例子就好了,当然只是简单的,因为实际上还有不少问题。

第二部分:滑动冲突处理

如果你按照上面自己敲出来一个demo 你就会发现,如果你的页面内容过长涉及滚动,你的组件内就根本就不能滚动,原理是这些组件的父组件是swiper这货,而swiper样式中本身是不支持上下滑动滴,当然这个也好处理,我们在样式中加入:

/deep/ uni-swiper .uni-swiper-wrapper {

overflow-y: auto !important;

}

/deep/ uni-swiper-item {

overflow-y: auto !important;

}

加完了滚动以后你就会惊喜的发现页面滚动上去以后再也下不来了!因为下拉事件被原生的下拉刷新占用咯~   你想着这还不简单,我加个scrollview还不行么,那你试试吧真不行嘿嘿!

首先让我告诉你原理:我们的swiper这货是必须有高度的, 而由于swiper高度是固定的,导致就算组件内部内容已经过长了,但下拉的时候body其实并没有过长,因此,无论你是什么scrollview或者overflow:auto,都会优先触发body滚动,也就是下拉刷新,这就是造成冲突的主要原因,我可以用一张图更清晰的解释:

针对这点,网上一种解决办法@touch.stop和@touchmove.stop你们可以试一下,反正H5可以,真机上不行,就算真机上可以,但这种方法只会在swiper区域拦截,造成下拉刷新区域很小,用户体验也是很差的。所以被我淘汰了。

根据上面的原理图,我们可以想到,既然swiper内部不能滚动,那就让swiper自身高度自适应撑起来,这样就会完美解决问题

所以首先我们需要解决swiper高度自适应问题

获取dom元素高度
这就是刚才组件上类名的用处

这里给了高度,的确已经解决了初步的问题,但是实际运用中,不可能所有的内容都是一上来就确定的,肯定要有网络请求在随时更新内容和高度的,比如有一个列表,那么上面的代码就失效了,因为高度在onReady周期已经定死了。

所以 我们的最后一步 需要随时更新高度,那么想到的思路就是子组件中emit通知父组件的swiper更新高度咯,尝试一下:(我这里用了个测试box来实验)

子组件中

uni.$on('updateSwiperHeight', () => {

console.log('收到通知');

this.getCurrentSwiperHeight('.fragment');

}); //父组件中注册监听

父组件在收到通知后会重新获取子组件高度并更新界面,这是美好的逻辑设想,但实际上获取dom高度的方法中,此时高度还没有及时更新,所以我们首先会想到将getCurrentSwiperHeight方法放在this.$nextTick方法中,但是在我的尝试下 就算包裹在nexttick中,高度也是没有及时更新,所以我只能使用了最终解决办法:

最终方案

使用setTimeout,延迟一段时间再获取高度,事实证明暂时只有这种方法能获取到高度。如果大家有什么更好的办法,可以留言告诉我谢谢!

你可能感兴趣的:(uni-app导航栏+swiper,及处理滑动冲突)