搜索
首页web前端js教程Vue的HOC技术如何开发一个无限加载列表(代码示例)

本篇文章给大家带来的内容是关于Vue的HOC技术如何开发一个无限加载列表(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

在web开发上,我们都对数据采用分页加载的机制,一种变形就是在页面采用循环加载的机制,拉到页面最下方有个加载更多的按钮。问题在于,当不同的数据要展示时,就要写很多这种列表,但是其中的逻辑都是相似的。

  1. 维护一组数据

  2. 加载更多数据

  3. 将数据用对应的组件显示出来

  4. 处理加载状态等

那有没有这么一个组件,来完成这一切相同的逻辑呢?

需求

需要有这么一个InfiniteList组件,它负责管理相关数据的加载和维护,然后以列表的形式显示出来,而列表项必须是由调用方决定的组件

HOC

高阶组件的概念,是React里面经常提到的,类似于高阶函数。
高阶函数:(fn) => otherFn
高阶组件:component => otherComponent
高阶组件用是代码复用的优秀工具,主要在处理逻辑方面和普适性上,有着奇效。

所以我决定用HOC来实现这个需求

参考文章:http://hcysun.me/2018/01/05/%...
良心博客

本文涉及的知识

  • vue

  • vue的render函数

实现

0

我使用的是vue和iview UI库

1

先弄出UI框架先,我用一个vue文件来构建整个组件的基本框架。源代码地址

  • html部分

<template>
  <div class="wrapper">
    <div class="content-wrapper">
      <slot></slot>
    </div>
    <div class="load-wrapper">
      <Button
        :icon="tipIcon"
        type="text"
        v-bind:disabled="!hasMore"
        v-bind:style="{color: tipColor}"
        v-bind:loading="loading"
        v-on:click="handleClickLoad">
        {{loadButtonText}}
      </Button>
    </div>
  </div>
</template>

用一个slot来分发要循环渲染的项目

  • js部分

一些UI有关的数据(不是很重要)

 props: {
      loadTip: {
        type: String,
        default: "加载更多"
      }
      ...
    },
    computed: {
      loadButtonText() {},
      tipIcon() {}
    }

这部分比较重要的只有一个事件发射,将点按钮的行为转换为 请求加载数据

handleClickLoad() {
        // 发射 请求加载数据的 事件
        this.$emit("on-load");
      }
  • css部分略

2

接下来就是最重要的部分,编写HOC
首先要明白,Vue中的组件,到底是什么。像我们写一个Vue文件,export出的是一个对象,所以我们现在写HOC,其实也是要最后返回一个对象。
所以我写了下面的函数来生成HOC

/**
 * 使用高阶组件的办法实现了一个无限加载列表
 * 可以根据数据循环渲染出特定的组件,并且管理加载状态
 * @param component 具体项的组件 {props: {data}}
*/
function InfiniteList(listItem) {
    return {
        props:...
        data(){}
        ...
    }
}

而我们如果渲染呢,当然是用Vue的render函数

render(h) {
    return h(component, data, children);
}

我们使用组合的方式,最外层需要用到我们第1步写到的模板,于是导入它,并注册它

import InfiniteListTemplate from "./InfiniteListTemplate";
function InfiniteList(listItem) {
    return {
        ...
        components: {
          InfiniteListTemplate  //  列表框架的模板,这个模板里面只有ui表现
        },
        ...
    }
}

render函数对于熟悉React的程序员来说应该是不难的,官网也有很详细的介绍。

render(h) {
      const self = this;
      // 根据 data 的 dataList循环渲染子组件
      const listItems = ...

      return h(InfiniteListTemplate, {
        props: {
          ...self.$props, // 传递所有参数
          hasMore: self.hasMore,  // 另外的hasMore和loading是这个HOC的state
          loading: self.loading
        },
        attrs: self.$attrs,
        on: {
          // 监听加载按钮事件
          "on-load": () => self.handleLoadData()
        }
      }, listItems);
    },

这里在最外层渲染我们的模板(且称为模板组件),并将当前HOC的props,attrs传递给模板组件。
这里提到了HOC的data,非常简单,就是两个状态和一个数据数组

data() {
      return {
        hasMore: true,
        loading: false,
        dataList: []
      }
    }

然后呢,循环渲染在哪?别急,render中的listItems就是我们循环渲染出来的组件,这里使用了map,相信使用React的人非常熟悉这种风格

const listItems = this.dataList.map(item => h(component, {
            props: {
              data: item
            }
          })
        );

最终返回的就是

return h(InfiniteListTemplate, {options}, listItems);

在哪里维护数据呢?当然是要传入一个加载数据的函数来进行管理,我们在HOC的props里面定义

props: {
      tipColor,
      loadTip,
      loadingTip,
      // 上面的数据都是为了传给模板(组件)
      offset: {
        type: Number,
        default: 5
      },
      // 数据加载的函数,需要的是一个 (index, offset) => Promise<[]>
      loadDataFunc: {
        type: Function,
        default() {
          return (index, offset) => Promise.resolve(new Array(offset).map((o, i) => index + i));
        }
      }
    },

然后我们还记得模板函数发射了个on-load事件么?我们需要在HOC里监听它并且处理逻辑

render(h) {
    return h(InfiniteListTemplate, {
        ...
        on: {
            'on-load': () => self.handleLoadData()
        }
    }, listItems);
},
methods: {
      /**
       * 监听模板点出了加载按钮时的操作
       * 调用数据加载函数加载数据
       * @return {Promise<void>}
       */
      async handleLoadData() {
        try {
          this.loading = true;
          let res = await this.loadDataFunc(this.dataList.length, this.offset);
          if (res && res.length) {
            this.dataList = this.dataList.concat(res);
            this.$Message.success(`成功获取到${res.length}条新数据`);
          } else {
            this.$Message.info(`已经获取了全部数据了`);
            this.hasMore = false;
          }
        } catch (e) {
          this.$Message.error("加载失败" + e.message);
        } finally {
          this.loading = false;
        }
      }
    },

完整InfiniteList.js代码

3

接下来使用一遍

<script>
import MyComponent from "./components/MyComponent";
import InfiniteList from "./components/hoc/InfiniteList";
const InfiniteListComponent = InfiniteList(MyComponent);
...

data() {
    loadDataFunc: (index, offset) => Promise<[]>
}
</script>

<template>
  <div id="app">
    <InfiniteListComponent
      v-if="loadDataFunc"
      v-bind:load-data-func="loadDataFunc">
    </InfiniteListComponent>
  </div>
</template>

MyComponent.vue是个非常简单的组件

<template>
  <div>Hello</div>
</template>

<script>
  export default {
    name: "MyComponent",
    props: {
      data: {
        type: String
      }
    }
  }
</script>

效果图如下

3073855418-5c34b708b68da_articlex.png

总结

在前端开发过程中,HOC是代码利用的利器,但是对抽象的要求高。
我觉得自己爱上了React...Vue实现这个HOC烦死了

以上是Vue的HOC技术如何开发一个无限加载列表(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器