利用Vue中HOC技術開發(fā)一個無限加載列表的方法

利用Vue中HOC技術開發(fā)一個無限加載列表的方法?這個問題可能是我們日常學習或工作經常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純热荩屛覀円黄饋砜纯窗桑?/p>

成都創(chuàng)新互聯(lián)2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目做網(wǎng)站、成都網(wǎng)站建設網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元連平做網(wǎng)站,已為上家服務,為連平各地企業(yè)和個人服務,聯(lián)系電話:18982081108

在web開發(fā)上,我們都對數(shù)據(jù)采用分頁加載的機制,一種變形就是在頁面采用循環(huán)加載的機制,拉到頁面最下方有個加載更多的按鈕。問題在于,當不同的數(shù)據(jù)要展示時,就要寫很多這種列表,但是其中的邏輯都是相似的。

  1. 維護一組數(shù)據(jù)

  2. 加載更多數(shù)據(jù)

  3. 將數(shù)據(jù)用對應的組件顯示出來

  4. 處理加載狀態(tài)等

那有沒有這么一個組件,來完成這一切相同的邏輯呢?

需求

需要有這么一個InfiniteList組件,它負責管理相關數(shù)據(jù)的加載和維護,然后以列表的形式顯示出來,而列表項必須是由調用方決定的組件

HOC

高階組件的概念,是React里面經常提到的,類似于高階函數(shù)。
高階函數(shù):(fn) => otherFn
高階組件:component => otherComponent
高階組件用是代碼復用的優(yōu)秀工具,主要在處理邏輯方面和普適性上,有著奇效。

所以我決定用HOC來實現(xiàn)這個需求

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

本文涉及的知識

  • vue

  • vue的render函數(shù)

實現(xiàn)

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來分發(fā)要循環(huán)渲染的項目

  • js部分

一些UI有關的數(shù)據(jù)(不是很重要)

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

這部分比較重要的只有一個事件發(fā)射,將點按鈕的行為轉換為 請求加載數(shù)據(jù)

handleClickLoad() {
        // 發(fā)射 請求加載數(shù)據(jù)的 事件
        this.$emit("on-load");
      }
  • css部分略

2

接下來就是最重要的部分,編寫HOC
首先要明白,Vue中的組件,到底是什么。像我們寫一個Vue文件,export出的是一個對象,所以我們現(xiàn)在寫HOC,其實也是要最后返回一個對象。
所以我寫了下面的函數(shù)來生成HOC

/**
 * 使用高階組件的辦法實現(xiàn)了一個無限加載列表
 * 可以根據(jù)數(shù)據(jù)循環(huán)渲染出特定的組件,并且管理加載狀態(tài)
 * @param component 具體項的組件 {props: {data}}
*/
function InfiniteList(listItem) {
    return {
        props:...
        data(){}
        ...
    }
}

而我們如果渲染呢,當然是用Vue的render函數(shù)

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

我們使用組合的方式,最外層需要用到我們第1步寫到的模板,于是導入它,并注冊它

import InfiniteListTemplate from "./InfiniteListTemplate";
function InfiniteList(listItem) {
    return {
        ...
        components: {
          InfiniteListTemplate  //  列表框架的模板,這個模板里面只有ui表現(xiàn)
        },
        ...
    }
}

render函數(shù)對于熟悉React的程序員來說應該是不難的,官網(wǎng)也有很詳細的介紹。

render(h) {
      const self = this;
      // 根據(jù) data 的 dataList循環(huán)渲染子組件
      const listItems = ...

      return h(InfiniteListTemplate, {
        props: {
          ...self.$props, // 傳遞所有參數(shù)
          hasMore: self.hasMore,  // 另外的hasMore和loading是這個HOC的state
          loading: self.loading
        },
        attrs: self.$attrs,
        on: {
          // 監(jiān)聽加載按鈕事件
          "on-load": () => self.handleLoadData()
        }
      }, listItems);
    },

這里在最外層渲染我們的模板(且稱為模板組件),并將當前HOC的props,attrs傳遞給模板組件。
這里提到了HOC的data,非常簡單,就是兩個狀態(tài)和一個數(shù)據(jù)數(shù)組

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

然后呢,循環(huán)渲染在哪?別急,render中的listItems就是我們循環(huán)渲染出來的組件,這里使用了map,相信使用React的人非常熟悉這種風格

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

最終返回的就是

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

在哪里維護數(shù)據(jù)呢?當然是要傳入一個加載數(shù)據(jù)的函數(shù)來進行管理,我們在HOC的props里面定義

props: {
      tipColor,
      loadTip,
      loadingTip,
      // 上面的數(shù)據(jù)都是為了傳給模板(組件)
      offset: {
        type: Number,
        default: 5
      },
      // 數(shù)據(jù)加載的函數(shù),需要的是一個 (index, offset) => Promise<[]>
      loadDataFunc: {
        type: Function,
        default() {
          return (index, offset) => Promise.resolve(new Array(offset).map((o, i) => index + i));
        }
      }
    },

然后我們還記得模板函數(shù)發(fā)射了個on-load事件么?我們需要在HOC里監(jiān)聽它并且處理邏輯

render(h) {
    return h(InfiniteListTemplate, {
        ...
        on: {
            'on-load': () => self.handleLoadData()
        }
    }, listItems);
},
methods: {
      /**
       * 監(jiān)聽模板點出了加載按鈕時的操作
       * 調用數(shù)據(jù)加載函數(shù)加載數(shù)據(jù)
       * @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}條新數(shù)據(jù)`);
          } else {
            this.$Message.info(`已經獲取了全部數(shù)據(jù)了`);
            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>

效果圖如下

利用Vue中HOC技術開發(fā)一個無限加載列表的方法

在前端開發(fā)過程中,HOC是代碼利用的利器,但是對抽象的要求高。
我覺得自己愛上了React...Vue實現(xiàn)這個HOC煩死了

感謝各位的閱讀!看完上述內容,你們對利用Vue中HOC技術開發(fā)一個無限加載列表的方法大概了解了嗎?希望文章內容對大家有所幫助。如果想了解更多相關文章內容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享文章:利用Vue中HOC技術開發(fā)一個無限加載列表的方法
瀏覽路徑:http://muchs.cn/article14/gphjde.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供響應式網(wǎng)站、標簽優(yōu)化、定制開發(fā)、做網(wǎng)站、網(wǎng)站維護、網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化