博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Intersection Observer API创建无限加载组件
阅读量:6200 次
发布时间:2019-06-21

本文共 4169 字,大约阅读时间需要 13 分钟。

本文章翻译自:https://vueschool.io/articles/vuejs-tutorials/build-an-infinite-scroll-component-using-intersection-observer-api/

开发过程中,经常会遇到需要处理大量数据的情况,比如列表、历史记录等,通常选择无限加载和分页导航。

传统后端渲染,一般会选择分页导航,它可以轻松跳转,甚至一次跳转几个页面,现在SPA盛行,无限滚动加载是更好的方案,可以给用户更好的体验,尤其是在移动端。

在Awesome Vue中,有如下无限滚动组件

  • - An infinite scroll plugin for Vue.js 1.0 & Vue.js 2.0.
  • - Infinite scroll component for Vue.js 2.
  • - An infinite scroll directive for vue.js.
  • - An infinite content loop component for Vue.js 2.
  • - An infinite content loop component for Vue.js 2, including functionalities such as 'pull-to-refresh', 'infinite-loading', 'snaping-scroll'.
  • - An infinite list mixin can recycle dom for Vue.js 2
  • - ∞ Infinite slide bar component.
  • - A vue2 component based on Iscroll, supports big data list with high performance scroll, infinite load and pull refresh.

Intersection Observer API的出现,让开发无限滚动组件变得更加简单方便。

Intersection Observer API

Intersection Observer API提供了一个可订阅的模型,可以观察该模型,以便在元素进入视口时得到通知。

创建一个观察者实例很简单,我们只需要创建一个IntersectionObserver的新实例并调用observe方法,传递一个DOM元素:

const observer = new IntersectionObserver();const coolElement = document.querySelector("#coolElement");observer.observe(coolElement);复制代码

接下来可以使用回调方式将参数传给InersectionObserver:

const observer = new IntersectionObserver(entries => {  const firstEntry = entries[0];  if (firstEntry.isIntersecting) {    // Handle intersection here...  }});const coolDiv = document.querySelector("#coolDiv");observer.observe(coolDiv);复制代码

回调接收entries作为其参数。 这是一个数组,因为当你使用阈值时你可以有几个条目,但事实并非如此,所以只得到第一个元素。 然后可以使用firstEntry.isIntersection属性检查它是否相交。 这是进行异步请求并检索下一个页面的数据。

IntersectionObserver构造函数使用以下表示法接收选项组件作为其第二个参数:

const options = {  root: document.querySelector("#scrollArea"),  rootMargin: "0px",  threshold: 1.0};const observer = new IntersectionObserver(callback, options);复制代码

关于options里的参数解释,截自

==root==:性指定目标元素所在的容器节点(即根元素)。注意,容器元素必须是目标元素的祖先节点

==rootMargin==: 定义根元素的margin,用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小。它使用CSS的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值。

这样设置以后,不管是窗口滚动或者容器内滚动,只要目标元素可见性变化,都会触发观察器

==threshold==:决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。 比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素0%、25%、50%、75%、100%可见时,会触发回调函数。

由于需要使用dom元素作为观察者,在Vue中,使用mounted,React中使用componentDidMount

// Observer.vueexport default {  data: () => ({    observer: null  }),  mounted() {    this.observer = new IntersectionObserver(([entry]) => {      if (entry && entry.isIntersecting) {        // ...      }    });    this.observer.observe(this.$el);  }};复制代码

注意:我们在* [entry] *参数上使用数组解构,使用this.$el作为root以便观察

为了使其可重用,我们需要让父组件(使用Observer组件的组件)处理相交的事件。 为此,可以在它相交时发出一个自定义事件:

export default {  mounted() {    this.observer = new IntersectionObserver(([entry]) => {      if (entry && entry.isIntersecting) {        this.$emit("intersect");      }    });    this.observer.observe(this.$el);  }  // ...};
复制代码

组件销毁的时候,记得关闭observer

export default {  destroyed() {    this.observer.disconnect();  }  // ...};复制代码

与==unobserve==不同的是,unobserve关闭当前被观察的元素,而disconnect关闭所有被观察的元素。

复制代码

创建无限滚动组件Vue

假如有如下类似需求

复制代码

引入Observer组件

复制代码

将==mounted==钩子里的异步请求移到==methods==里,并加上自增page以及合并items数据

export default {  data: () => ({ page: 1, items: [] }),  methods: {    async intersected() {      const res = await fetch(        `https://jsonplaceholder.typicode.com/comments?_page=${          this.page        }&_limit=50`      );      this.page++;      const items = await res.json();      this.items = [...this.items, ...items];    }  }};复制代码

this.items = [...this.items, ...items] 等价于 this.items.concat(items)

到此InfiniteScroll.vue已经完成

复制代码

值得注意的是,intersection Observer api兼容性并不是太好,经本人测试,chrome上无压力,其余全不兼容,不过可以使用[W3C’s Intersection Observer(https://github.com/w3c/IntersectionObserver/tree/master/polyfill),npm install intersection-observer,然后在Observer.vue中加入require('intersection-observer');即可。

Demo在此:https://codesandbox.io/s/kxm8wlnn85

转载地址:http://artca.baihongyu.com/

你可能感兴趣的文章
I00015 打印等腰三角形字符图案(底边在上)
查看>>
HDU2502 月之数
查看>>
从浏览器渲染的角度谈谈html标签的语义化
查看>>
JS移动客户端--触屏滑动事件
查看>>
对于PHP大型开发框架的看法[转]
查看>>
11-03笔记图
查看>>
python基础练习
查看>>
Python编码与解码
查看>>
持续集成~Jenkins构建GitHub项目的实现
查看>>
遍历页面上的CheckBox,CheckBoxList
查看>>
返回引用
查看>>
如何将python3.6软件的py文件打包成exe程序
查看>>
开发的套路
查看>>
【02】Kubernets:使用 kubeadm 部署 K8S 集群
查看>>
stat
查看>>
python14期2017.7.13
查看>>
Oracle 与 MySql 区别
查看>>
jsp,el表达式
查看>>
HDOJ1005
查看>>
mySQL建表允许最多多少字段?
查看>>