首頁 > web前端 > js教程 > Vue的HOC技術如何開發一個無限載入清單(程式碼範例)

Vue的HOC技術如何開發一個無限載入清單(程式碼範例)

不言
發布: 2019-01-10 11:11:47
轉載
3478 人瀏覽過

這篇文章帶給大家的內容是關於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>
    <div>
      <slot></slot>
    </div>
    <div>
      <button>
        {{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;
        }
      }
    },</void>
登入後複製
完整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>
    <infinitelistcomponent>
    </infinitelistcomponent>
  </div>
</template>
登入後複製

#MyComponent .vue是個非常簡單的元件

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

<script>
  export default {
    name: "MyComponent",
    props: {
      data: {
        type: String
      }
    }
  }
</script>
登入後複製
效果圖如下

Vue的HOC技術如何開發一個無限載入清單(程式碼範例)

總結

在前端開發過程中,HOC是程式碼利用的利器,但是對抽象的要求高。

我覺得自己愛上了React...Vue實現這個HOC煩死了

以上是Vue的HOC技術如何開發一個無限載入清單(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板