利用Vue中HOC技術(shù)開(kāi)發(fā)一個(gè)無(wú)限加載列表的方法?這個(gè)問(wèn)題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見(jiàn)到的。希望通過(guò)這個(gè)問(wèn)題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!
成都創(chuàng)新互聯(lián)2013年開(kāi)創(chuàng)至今,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目做網(wǎng)站、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元連平做網(wǎng)站,已為上家服務(wù),為連平各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話(huà):18982081108
在web開(kāi)發(fā)上,我們都對(duì)數(shù)據(jù)采用分頁(yè)加載的機(jī)制,一種變形就是在頁(yè)面采用循環(huán)加載的機(jī)制,拉到頁(yè)面最下方有個(gè)加載更多的按鈕。問(wèn)題在于,當(dāng)不同的數(shù)據(jù)要展示時(shí),就要寫(xiě)很多這種列表,但是其中的邏輯都是相似的。
維護(hù)一組數(shù)據(jù)
加載更多數(shù)據(jù)
將數(shù)據(jù)用對(duì)應(yīng)的組件顯示出來(lái)
處理加載狀態(tài)等
那有沒(méi)有這么一個(gè)組件,來(lái)完成這一切相同的邏輯呢?
需要有這么一個(gè)InfiniteList組件,它負(fù)責(zé)管理相關(guān)數(shù)據(jù)的加載和維護(hù),然后以列表的形式顯示出來(lái),而列表項(xiàng)必須是由調(diào)用方?jīng)Q定的組件。
高階組件的概念,是React里面經(jīng)常提到的,類(lèi)似于高階函數(shù)。
高階函數(shù):(fn) => otherFn
高階組件:component => otherComponent
高階組件用是代碼復(fù)用的優(yōu)秀工具,主要在處理邏輯方面和普適性上,有著奇效。
所以我決定用HOC來(lái)實(shí)現(xiàn)這個(gè)需求
參考文章:http://hcysun.me/2018/01/05/%...
良心博客
vue
vue的render函數(shù)
我使用的是vue和iview UI庫(kù)
先弄出UI框架先,我用一個(gè)vue文件來(lái)構(gòu)建整個(gè)組件的基本框架。源代碼地址
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>用一個(gè)slot來(lái)分發(fā)要循環(huán)渲染的項(xiàng)目
js部分
一些UI有關(guān)的數(shù)據(jù)(不是很重要)
props: {
loadTip: {
type: String,
default: "加載更多"
}
...
},
computed: {
loadButtonText() {},
tipIcon() {}
}這部分比較重要的只有一個(gè)事件發(fā)射,將點(diǎn)按鈕的行為轉(zhuǎn)換為 請(qǐng)求加載數(shù)據(jù)
handleClickLoad() {
// 發(fā)射 請(qǐng)求加載數(shù)據(jù)的 事件
this.$emit("on-load");
}css部分略
接下來(lái)就是最重要的部分,編寫(xiě)HOC
首先要明白,Vue中的組件,到底是什么。像我們寫(xiě)一個(gè)Vue文件,export出的是一個(gè)對(duì)象,所以我們現(xiàn)在寫(xiě)HOC,其實(shí)也是要最后返回一個(gè)對(duì)象。
所以我寫(xiě)了下面的函數(shù)來(lái)生成HOC
/**
* 使用高階組件的辦法實(shí)現(xiàn)了一個(gè)無(wú)限加載列表
* 可以根據(jù)數(shù)據(jù)循環(huán)渲染出特定的組件,并且管理加載狀態(tài)
* @param component 具體項(xiàng)的組件 {props: {data}}
*/
function InfiniteList(listItem) {
return {
props:...
data(){}
...
}
}而我們?nèi)绻秩灸兀?dāng)然是用Vue的render函數(shù)
render(h) {
return h(component, data, children);
}我們使用組合的方式,最外層需要用到我們第1步寫(xiě)到的模板,于是導(dǎo)入它,并注冊(cè)它
import InfiniteListTemplate from "./InfiniteListTemplate";
function InfiniteList(listItem) {
return {
...
components: {
InfiniteListTemplate // 列表框架的模板,這個(gè)模板里面只有ui表現(xiàn)
},
...
}
}render函數(shù)對(duì)于熟悉React的程序員來(lái)說(shuō)應(yīng)該是不難的,官網(wǎng)也有很詳細(xì)的介紹。
render(h) {
const self = this;
// 根據(jù) data 的 dataList循環(huán)渲染子組件
const listItems = ...
return h(InfiniteListTemplate, {
props: {
...self.$props, // 傳遞所有參數(shù)
hasMore: self.hasMore, // 另外的hasMore和loading是這個(gè)HOC的state
loading: self.loading
},
attrs: self.$attrs,
on: {
// 監(jiān)聽(tīng)加載按鈕事件
"on-load": () => self.handleLoadData()
}
}, listItems);
},這里在最外層渲染我們的模板(且稱(chēng)為模板組件),并將當(dāng)前HOC的props,attrs傳遞給模板組件。
這里提到了HOC的data,非常簡(jiǎn)單,就是兩個(gè)狀態(tài)和一個(gè)數(shù)據(jù)數(shù)組
data() {
return {
hasMore: true,
loading: false,
dataList: []
}
}然后呢,循環(huán)渲染在哪?別急,render中的listItems就是我們循環(huán)渲染出來(lái)的組件,這里使用了map,相信使用React的人非常熟悉這種風(fēng)格
const listItems = this.dataList.map(item => h(component, {
props: {
data: item
}
})
);最終返回的就是
return h(InfiniteListTemplate, {options}, listItems);在哪里維護(hù)數(shù)據(jù)呢?當(dāng)然是要傳入一個(gè)加載數(shù)據(jù)的函數(shù)來(lái)進(jìn)行管理,我們?cè)贖OC的props里面定義
props: {
tipColor,
loadTip,
loadingTip,
// 上面的數(shù)據(jù)都是為了傳給模板(組件)
offset: {
type: Number,
default: 5
},
// 數(shù)據(jù)加載的函數(shù),需要的是一個(gè) (index, offset) => Promise<[]>
loadDataFunc: {
type: Function,
default() {
return (index, offset) => Promise.resolve(new Array(offset).map((o, i) => index + i));
}
}
},然后我們還記得模板函數(shù)發(fā)射了個(gè)on-load事件么?我們需要在HOC里監(jiān)聽(tīng)它并且處理邏輯
render(h) {
return h(InfiniteListTemplate, {
...
on: {
'on-load': () => self.handleLoadData()
}
}, listItems);
},
methods: {
/**
* 監(jiān)聽(tīng)模板點(diǎn)出了加載按鈕時(shí)的操作
* 調(diào)用數(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(`已經(jīng)獲取了全部數(shù)據(jù)了`);
this.hasMore = false;
}
} catch (e) {
this.$Message.error("加載失敗" + e.message);
} finally {
this.loading = false;
}
}
},完整InfiniteList.js代碼
接下來(lái)使用一遍
<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是個(gè)非常簡(jiǎn)單的組件
<template>
<div>Hello</div>
</template>
<script>
export default {
name: "MyComponent",
props: {
data: {
type: String
}
}
}
</script>效果圖如下

在前端開(kāi)發(fā)過(guò)程中,HOC是代碼利用的利器,但是對(duì)抽象的要求高。
我覺(jué)得自己愛(ài)上了React...Vue實(shí)現(xiàn)這個(gè)HOC煩死了
感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)利用Vue中HOC技術(shù)開(kāi)發(fā)一個(gè)無(wú)限加載列表的方法大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享文章:利用Vue中HOC技術(shù)開(kāi)發(fā)一個(gè)無(wú)限加載列表的方法
瀏覽路徑:http://chinadenli.net/article14/gphjde.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、標(biāo)簽優(yōu)化、定制開(kāi)發(fā)、做網(wǎng)站、網(wǎng)站維護(hù)、網(wǎng)站營(yíng)銷(xiāo)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)