IntersectionObserver的实践

在小程序里面提供了createIntersectionObserver来实现监听目标元素与视窗的位置变化

wx.createIntersectionObserver(Object component, Object options)

利用这个API,可以轻松实现滚动定位功能:
在这里插入图片描述
实现的整体思路:

  1. 先实现根据页面的滚动,导航条高亮到具体的内容模块
  2. 再实现点击对应的导航,页面再滚动到具体的内容区域

1.1 实现页面的滚动,高亮具体的导航条

利用IntersectionObserver的方式实现:监听每个模块与viewport之间的距离变化

<template>
	<view class="nav-position-box">
		<text id="1' @tap="toViewClick(1)" :class="actionViewName == 1 ? 'isActive': ''">内容1</text>
		<text id="2' @tap="toViewClick(2)" :class="actionViewName == 2 ? 'isActive': ''">内容2</text>
		<text id="3' @tap="toViewClick(3)" :class="actionViewName == 3 ? 'isActive': ''">内容3</text>
	</view>
	<!-- 具体内容区 -->
	<view id="content-1" class="observe-scroll-node">
		..................
	</view>
	<view id="content-2" class="observe-scroll-node">
		..................
	</view>
	<view id="content-3" class="observe-scroll-node">
		..................
	</view>
</template>

<script>
	let node = [
		{id: 'content-1', show: false},
		{id: 'content-2', show: false},
		{id: 'content-3', show: false},
	];
	export default class backTop extends wepy.component {
		data = {
			actionViewName: ''
		}
		// 页面滚动改变对应的导航信息
	    changeTypeByScroll() {
	        if (observerScrollNodeObj) {
	            observerScrollNodeObj.disconnect();
	            observerScrollNodeObj = null;
	        }
	        observerScrollNodeObj = wx.createIntersectionObserver(this.$wxpage, { observeAll: true });
	        observerScrollNodeObj
	        	// 相对于页面可视区
	            .relativeToViewport({ top: -70 })
	            // 相对于某一个元素
	            .observe('.observe-scroll-node', res => {
	                this.observeNode(res);
	                this.$apply();
	            });
	    }
	
	    // 观察节点
	    observeNode({ intersectionRatio, id }) {
	    	// 找到滚动到对应id下面的序号
	        const nodeIndex = node.findIndex(ele => ele.id === id);
	        // 将滚动到的版块的show属性设置为true
	        node[nodeIndex] && (node[nodeIndex].show = intersectionRatio > 0);
	        // 找到nav应该显示哪一个内容
	        this.actionViewName = node.findIndex(ele => ele.show);
	        this.$apply();
	    }

		onLoad() {
			this.changeTypeByScroll();
		}
	}
</script>

1.2 点击对应的导航,页面滚动到对应位置

<script>
	// 锚点定位(点击topNav页面滑动到具体位置)
    toViewClick(actionView) {
        const query = wx.createSelectorQuery();
        query.select(`#${actionView}`).boundingClientRect(); // 选择对应Id的节点,获取节点位置信息的查询请求
        query.selectViewport().scrollOffset(); // 获取页面滑动位置的查询请求
        query.exec((res) => {
            if (res[0] && res[0].top) {
                (actionView === 'swiper-list') && (this.backTopShow = false);
                this.scrollPageHash(res[0].top, res[1].scrollTop, actionView);
                this.$apply();
            }
        });
    }// 页面滚动函数
    scrollPageHash(distance, scrollTop, actionView) {
        const _ = this;
        // 滚动的时候,断开连接
        if (observerScrollNodeObj) {
            observerScrollNodeObj.disconnect();
            observerScrollNodeObj = null;
        }
        wx.pageScrollTo({
            scrollTop: distance + scrollTop - 50,
            duration: 200,
            complete() {
                // 改变节点的状态
                const currentIndex = node.findIndex(ele => ele.id === 'content-'+actionView);
                node.forEach((_, index) => {
                    if (index < currentIndex) {
                        _.show = false;
                    }
                });
                // 再链接监听
                _.changeTypeByScroll();
            }
        });
    }
</script>

这样就实现了页面的固定定位。

二. 实现图片懒加载

当图片没有出现在视窗里时,此时去加载图片资源比较消耗性能,那么如果在进入视窗才加载,可以很好的优化性能.

<view class="observe-image">
	<block v-if=" item.show ">
	   <image class="gray-bg lottery-img" mode="aspectFill" :src="cover" ></image>
	</block>
	<block v-else>
	   <view class="gray-bg lottery-img"></view>
	</block> 
</view>

<script>
data() {
	return {
		cover: false
	}	
},
mounted() {
   // 开启监听
   this.createObserveInstance();
},
methods: {
	async observerNode() {
	  // 先断开
	  this.disconnectObserve();
	  // 再链接
	  this.createObserveInstance();
	  observerInstance.relativeToViewport().observe('.observe-image', res => {
	    if (res.intersectionRatio > 0) {
	      // 开启image标签发送请求,没开启之前用view空白盒子占位
	      this.cover = true;
	    }
	  });
	},
	// 断开链接
	disconnectObserve() {
	  if (observerInstance) {
	    observerInstance.disconnect();
	    observerInstance = null;
	  }
	},
	// 创建一个监听的IntersectionObserver实例
	createObserveInstance() {
	  observerInstance = uni.createIntersectionObserver(this, {
	    observeAll: true
	  });
	},
}
</scirpt>

上面使用uni的版本实现的.当滚动页面的时候就可以发现只有当内容出现时才会去发送下载图片的请求.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值