国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

【W(wǎng)eb技術(shù)】1346- 前端虛擬列表的實(shí)現(xiàn)原理

共 3816字,需瀏覽 8分鐘

 ·

2022-06-09 19:23

作者:字節(jié)跳動(dòng) fe @程翯

近期在某平臺(tái)開(kāi)發(fā)迭代的過(guò)程中遇到了超長(zhǎng)List嵌套在antd Modal里加載慢,卡頓的情況。于是心血來(lái)潮決定從零自己實(shí)現(xiàn)一個(gè)虛擬滾動(dòng)列表來(lái)優(yōu)化一下整體的體驗(yàn)。

改造前:

img

我們可以看出來(lái)在改造之前,打開(kāi)編輯窗口Modal的時(shí)候會(huì)出現(xiàn)短暫的卡頓,并且在點(diǎn)擊Cancel關(guān)閉后也并不是立即響應(yīng)而是稍作遲疑之后才關(guān)閉的

改造后:

img

改造完成后我們可以觀察到整個(gè)Modal的打開(kāi)比之前變得流暢了不少,可以做到立即響應(yīng)用戶的點(diǎn)擊事件喚起/關(guān)閉Modal

  • 性能對(duì)比Demo: https://codesandbox.io/s/a-v-list-has-dynamic-inner-height-modal-demo-l66py

0x0 基礎(chǔ)知識(shí)

所以什么是虛擬滾動(dòng)/列表呢?

一個(gè)虛擬列表是指當(dāng)我們有成千上萬(wàn)條數(shù)據(jù)需要進(jìn)行展示但是用戶的“視窗”(一次性可見(jiàn)內(nèi)容)又不大時(shí)我們可以通過(guò)巧妙的方法只渲染用戶最大可見(jiàn)條數(shù)+“BufferSize”個(gè)元素并在用戶進(jìn)行滾動(dòng)時(shí)動(dòng)態(tài)更新每個(gè)元素中的內(nèi)容從而達(dá)到一個(gè)和長(zhǎng)list滾動(dòng)一樣的效果但花費(fèi)非常少的資源。

img

(從上圖中我們可以發(fā)現(xiàn)實(shí)際用戶每次能看到的元素/內(nèi)容只有item-4 ~ item-13 也就是9個(gè)元素)

0x1 實(shí)現(xiàn)一個(gè)“定高”虛擬列表

  • 首先我們需要定義幾個(gè)變量/名稱。
    • 從上圖中我們可以看出來(lái)用戶實(shí)際可見(jiàn)區(qū)域的開(kāi)始元素是Item-4,所以他在數(shù)據(jù)數(shù)組中對(duì)應(yīng)的下標(biāo)也就是我們的startIndex
    • 同理Item-13對(duì)應(yīng)的數(shù)組下標(biāo)則應(yīng)該是我們的endIndex
    • 所以Item-1,Item-2和Item-3則是被用戶的向上滑動(dòng)操作所隱藏,所以我們稱它為startOffset(scrollTop)

因?yàn)槲覀冎粚?duì)可視區(qū)域的內(nèi)容做了渲染,所以為了保持整個(gè)容器的行為和一個(gè)長(zhǎng)列表相似(滾動(dòng))我們必須保持原列表的高度,所以我們將HTML結(jié)構(gòu)設(shè)計(jì)成如下


<div?className="vListContainer">
??<div?className="phantomContent">
????...
????
????
????
????....
??div>
div>
  • 其中:

    • vListContainer 為可視區(qū)域的容器,具有 overflow-y: auto 屬性。
    • phantom 中的每條數(shù)據(jù)都應(yīng)該具有 position: absolute 屬性
    • phantomContent 則是我們的“幻影”部分,其主要目的是為了還原真實(shí)List的內(nèi)容高度從而模擬正常長(zhǎng)列表滾動(dòng)的行為。
  • 接著我們對(duì) vListContainer 綁定一個(gè)onScroll的響應(yīng)函數(shù),并在函數(shù)中根據(jù)原生滾動(dòng)事件的scrollTop 屬性來(lái)計(jì)算我們的 startIndexendIndex

    • 列表總高度: phantomHeight = total * rowHeight
    • 可視范圍內(nèi)展示元素?cái)?shù):limit = Math.ceil(height/rowHeight)
    • 我們需要一個(gè)固定的列表元素高度:rowHeight
    • 我們需要知道當(dāng)前l(fā)ist一共有多少條數(shù)據(jù): total
    • 我們需要知道當(dāng)前用戶可視區(qū)域的高度: height
    • 在開(kāi)始計(jì)算之前,我們先要定義幾個(gè)數(shù)值:
    • 在有了上述數(shù)據(jù)之后我們可以通過(guò)計(jì)算得出下列數(shù)據(jù):

(注意此處我們用的是向上取整)

  • 所以我們可以在onScroll 回調(diào)中進(jìn)行下列計(jì)算:
onScroll(evt:?any)?{
??//?判斷是否是我們需要響應(yīng)的滾動(dòng)事件
??if?(evt.target?===?this.scrollingContainer.current)?{
????const?{?scrollTop?}?=?evt.target;
????const?{?startIndex,?total,?rowHeight,?limit?}?=?this;

????//?計(jì)算當(dāng)前startIndex
????const?currentStartIndex?=?Math.floor(scrollTop?/?rowHeight);

????//?如果currentStartIndex?和?startIndex?不同(我們需要更新數(shù)據(jù)了)
????if?(currentStartIndex?!==?startIndex?)?{
??????this.startIndex?=?currentStartIndex;
??????this.endIndex?=?Math.min(currentStartIndedx?+?limit,?total?-?1);
??????this.setState({?scrollTop?});
????}
??}
}
  • 當(dāng)我們一旦有了startIndex 和 endIndex 我們就可以渲染其對(duì)應(yīng)的數(shù)據(jù):
renderDisplayContent?=?()?=>?{
??const?{?rowHeight,?startIndex,?endIndex?}?=?this;
??const?content?=?[];
??
??//?注意這塊我們用了?<=?是為了渲染x+1個(gè)元素用來(lái)在讓滾動(dòng)變得連續(xù)(永遠(yuǎn)渲染在判斷&渲染x+2)
??for?(let?i?=?startIndex;?i?<=?endIndex;?++i)?{
????//?rowRenderer?是用戶定義的列表元素渲染方法,需要接收一個(gè)?index?i?和
????//????當(dāng)前位置對(duì)應(yīng)的style
????content.push(
??????rowRenderer({
????????index:?i,?
????????style:?{
??????????width:?'100%',
??????????height:?rowHeight?+?'px',
??????????position:?"absolute",
??????????left:?0,
??????????right:?0,
??????????top:?i?*?rowHeight,
??????????borderBottom:?"1px?solid?#000",
????????}
??????})
????);
??}
??
??return?content;
};

線上Demo:https://codesandbox.io/s/a-naive-v-list-f0ghm

原理:

  • 所以這個(gè)滾動(dòng)效果究竟是怎么實(shí)現(xiàn)的呢?首先我們?cè)趘ListContainer中渲染了一個(gè)真實(shí)list高度的“幻影”容器從而允許用戶進(jìn)行滾動(dòng)操作。其次我們監(jiān)聽(tīng)了onScroll事件,并且在每次用戶觸發(fā)滾動(dòng)是動(dòng)態(tài)計(jì)算當(dāng)前滾動(dòng)Offset(被滾上去隱藏了多少)所對(duì)應(yīng)的開(kāi)始下標(biāo)(index)是多少。當(dāng)我們發(fā)現(xiàn)新的下邊和我們當(dāng)前展示的下標(biāo)不同時(shí)進(jìn)行賦值并且setState觸發(fā)重繪。當(dāng)用戶當(dāng)前的滾動(dòng)offset未觸發(fā)下標(biāo)更新時(shí),則因?yàn)楸旧韕hantom的長(zhǎng)度關(guān)系讓虛擬列表?yè)碛泻推胀斜硪粯拥臐L動(dòng)能力。當(dāng)觸發(fā)重繪時(shí)因?yàn)槲覀冇?jì)算的是startIndex 所以用戶感知不到頁(yè)面的重繪(因?yàn)楫?dāng)前滾動(dòng)的下一幀和我們重繪完的內(nèi)容是一致的)。

優(yōu)化:

  • 對(duì)于上邊我們實(shí)現(xiàn)的虛擬列表,大家不難發(fā)現(xiàn)一但進(jìn)行了快速滑動(dòng)就會(huì)出現(xiàn)列表閃爍的現(xiàn)象/來(lái)不及渲染、空白的現(xiàn)象。還記得我們一開(kāi)始說(shuō)的 **渲染用戶最大可見(jiàn)條數(shù)+“BufferSize” 么?對(duì)于我們渲染的實(shí)際內(nèi)容,我們可以對(duì)其上下加入Buffer的概念(即上下多渲染一些元素用來(lái)過(guò)渡快速滑動(dòng)時(shí)來(lái)不及渲染的問(wèn)題)。優(yōu)化后的onScroll 函數(shù)如下:
onScroll(evt:?any)?{
??........
??//?計(jì)算當(dāng)前startIndex
??const?currentStartIndex?=?Math.floor(scrollTop?/?rowHeight);
????
??//?如果currentStartIndex?和?startIndex?不同(我們需要更新數(shù)據(jù)了)
??if?(currentStartIndex?!==?originStartIdx)?{
????//?注意,此處我們引入了一個(gè)新的變量叫originStartIdx,起到了和之前startIndex
????//????相同的效果,記錄當(dāng)前的?真實(shí)?開(kāi)始下標(biāo)。
????this.originStartIdx?=?currentStartIndex;
????//?對(duì)?startIndex?進(jìn)行?頭部?緩沖區(qū)?計(jì)算
????this.startIndex?=?Math.max(this.originStartIdx?-?bufferSize,?0);
????//?對(duì)?endIndex?進(jìn)行?尾部?緩沖區(qū)?計(jì)算
????this.endIndex?=?Math.min(
??????this.originStartIdx?+?this.limit?+?bufferSize,
??????total?-?1
????);

????this.setState({?scrollTop:?scrollTop?});
??}
}

線上Demo:https://codesandbox.io/s/A-better-v-list-bkw1t

0x2 列表元素高度自適應(yīng)

現(xiàn)在我們已經(jīng)實(shí)現(xiàn)了“定高”元素的虛擬列表的實(shí)現(xiàn),那么如果說(shuō)碰到了高度不固定的超長(zhǎng)列表的業(yè)務(wù)場(chǎng)景呢?

  • 一般碰到不定高列表元素時(shí)有三種虛擬列表實(shí)現(xiàn)方式:
  1. 對(duì)輸入數(shù)據(jù)進(jìn)行更改,傳入每一個(gè)元素對(duì)應(yīng)的高度 dynamicHeight[i] = x x 為元素i 的行高

    需要實(shí)現(xiàn)知道每一個(gè)元素的高度(不切實(shí)際)

  2. 將當(dāng)前元素先在屏外進(jìn)行繪制并對(duì)齊高度進(jìn)行測(cè)量后再將其渲染到用戶可視區(qū)域內(nèi)

    這種方法相當(dāng)于雙倍渲染消耗(不切實(shí)際)

  3. 傳入一個(gè)estimateHeight 屬性先對(duì)行高進(jìn)行估計(jì)并渲染,然后渲染完成后獲得真實(shí)行高并進(jìn)行更新和緩存

    會(huì)引入多余的transform(可以接受),會(huì)在后邊講為什么需要多余的transform...

  • 讓我們暫時(shí)先回到 HTML 部分

"vListContainer">
??"phantomContent">
????...
????
????
????
????....
??</div>
div>



"vListContainer"
>
??"phantomContent"?/>
??"actualContent">
????...
????
????
????
????....
??</div>
div>
  • 在我們實(shí)現(xiàn) “定高” 虛擬列表時(shí),我們是采用了把元素渲染在phantomContent 容器里,并且通過(guò)設(shè)置每一個(gè)item的positionabsolute 加上定義top 屬性等于 i * rowHeight 來(lái)實(shí)現(xiàn)無(wú)論怎么滾動(dòng),渲染內(nèi)容始終是在用戶的可視范圍內(nèi)的。在列表高度不能確定的情況下,我們就無(wú)法準(zhǔn)確的通過(guò)estimateHeight 來(lái)計(jì)算出當(dāng)前元素所處的y位置,所以我們需要一個(gè)容器來(lái)幫我們做這個(gè)絕對(duì)定位。
  • actualContent 則是我們新引入的列表內(nèi)容渲染容器,通過(guò)在此容器上設(shè)置position: absolute 屬性來(lái)避免在每個(gè)item上設(shè)置。
  • 有一點(diǎn)不同的是,因?yàn)槲覀兏挠胊ctualContent 容器。當(dāng)我們進(jìn)行滑動(dòng)時(shí)需要?jiǎng)討B(tài)的對(duì)容器的位置進(jìn)行一個(gè) y-transform 從而實(shí)現(xiàn)容器永遠(yuǎn)處于用戶的視窗之中:
getTransform()?{
??const?{?scrollTop?}?=?this.state;
??const?{?rowHeight,?bufferSize,?originStartIdx?}?=?this;

??//?當(dāng)前滑動(dòng)offset?-?當(dāng)前被截?cái)嗟模](méi)有完全消失的元素)距離?-?頭部緩沖區(qū)距離
??return?`translate3d(0,${
????scrollTop?-
????(scrollTop?%?rowHeight)?-
????Math.min(originStartIdx,?bufferSize)?*?rowHeight
??}
px,0)`
;

}

線上Demo:https://codesandbox.io/s/a-v-list-achieved-by-transform-container-29mbc

(注:當(dāng)沒(méi)有高度自適應(yīng)要求時(shí)且沒(méi)有實(shí)現(xiàn)cell復(fù)用時(shí),把元素通過(guò)absolute渲染在phantom里會(huì)比通過(guò)transform的性能要好一些。因?yàn)槊看武秩綾ontent時(shí)都會(huì)進(jìn)行重排,但是如果使用transform時(shí)就相當(dāng)于進(jìn)行了( 重排 + transform) > 重排)

  • 回到列表元素高度自適應(yīng)這個(gè)問(wèn)題上來(lái),現(xiàn)在我們有了一個(gè)可以在內(nèi)部進(jìn)行正常block排布的元素渲染容器(actualContent ),我們現(xiàn)在就可以直接在不給定高度的情況下先把內(nèi)容都渲染進(jìn)去。對(duì)于之前我們需要用rowHeight 做高度計(jì)算的地方,我們統(tǒng)一替換成estimateHeight 進(jìn)行計(jì)算。
    • limit = Math.ceil(height / estimateHeight)
    • phantomHeight = total * estimateHeight
  • 同時(shí)為了避免重復(fù)計(jì)算每一個(gè)元素渲染后的高度(getBoundingClientReact().height) 我們需要一個(gè)數(shù)組來(lái)存儲(chǔ)這些高度
interface?CachedPosition?{
??index:?number;?????????//?當(dāng)前pos對(duì)應(yīng)的元素的下標(biāo)
??top:?number;???????????//?頂部位置
??bottom:?number;????????//?底部位置
??height:?number;????????//?元素高度
??dValue:?number;????????//?高度是否和之前(estimate)存在不同
}

cachedPositions:?CachedPosition[]?=?[];

//?初始化cachedPositions
initCachedPositions?=?()?=>?{
??const?{?estimatedRowHeight?}?=?this;
??this.cachedPositions?=?[];
??for?(let?i?=?0;?i?this.total;?++i)?{
????this.cachedPositions[i]?=?{
??????index:?i,
??????height:?estimatedRowHeight,?????????????//?先使用estimateHeight估計(jì)
??????top:?i?*?estimatedRowHeight,????????????//?同上
??????bottom:?(i?+?1)?*?estimatedRowHeight,???//?same?above
??????dValue:?0,
????};
??}
};
  • 當(dāng)我們計(jì)算完(初始化完) cachedPositions 之后由于我們計(jì)算了每一個(gè)元素的top和bottom,所以phantom 的高度就是cachedPositions 中最后一個(gè)元素的bottom值
this.phantomHeight?=?this.cachedPositions[cachedPositionsLen?-?1].bottom;
  • 當(dāng)我們根據(jù)estimateHeight 渲染完用戶視窗內(nèi)的元素后,我們需要對(duì)渲染出來(lái)的元素做實(shí)際高度更新,此時(shí)我們可以利用componentDidUpdate 生命周期鉤子來(lái)計(jì)算、判斷和更新:
componentDidUpdate()?{
??......
??//?actualContentRef必須存在current?(已經(jīng)渲染出來(lái))?+?total?必須?>?0
??if?(this.actualContentRef.current?&&?this.total?>?0)?{
????this.updateCachedPositions();
??}
}

updateCachedPositions?=?()?=>?{
??//?update?cached?item?height
??const?nodes:?NodeListOf<any>?=?this.actualContentRef.current.childNodes;
??const?start?=?nodes[0];

??//?calculate?height?diff?for?each?visible?node...
??nodes.forEach((node:?HTMLDivElement)?=>?{
????if?(!node)?{
??????//?scroll?too?fast?...
??????return;
????}
????const?rect?=?node.getBoundingClientRect();
????const?{?height?}?=?rect;
????const?index?=?Number(node.id.split('-')[1]);
????const?oldHeight?=?this.cachedPositions[index].height;
????const?dValue?=?oldHeight?-?height;

????if?(dValue)?{
??????this.cachedPositions[index].bottom?-=?dValue;
??????this.cachedPositions[index].height?=?height;
??????this.cachedPositions[index].dValue?=?dValue;
????}
??});

??//?perform?one?time?height?update...
??let?startIdx?=?0;
??
??if?(start)?{
????startIdx?=?Number(start.id.split('-')[1]);
??}
??
??const?cachedPositionsLen?=?this.cachedPositions.length;
??let?cumulativeDiffHeight?=?this.cachedPositions[startIdx].dValue;
??this.cachedPositions[startIdx].dValue?=?0;

??for?(let?i?=?startIdx?+?1;?i?????const?item?=?this.cachedPositions[i];
????//?update?height
????this.cachedPositions[i].top?=?this.cachedPositions[i?-?1].bottom;
????this.cachedPositions[i].bottom?=?this.cachedPositions[i].bottom?-?cumulativeDiffHeight;

????if?(item.dValue?!==?0)?{
??????cumulativeDiffHeight?+=?item.dValue;
??????item.dValue?=?0;
????}
??}

??//?update?our?phantom?div?height
??const?height?=?this.cachedPositions[cachedPositionsLen?-?1].bottom;
??this.phantomHeight?=?height;
??this.phantomContentRef.current.style.height?=?`${height}px`;
};
  • 當(dāng)我們現(xiàn)在有了所有元素的準(zhǔn)確高度和位置值時(shí),我們獲取當(dāng)前scrollTop (Offset)所對(duì)應(yīng)的開(kāi)始元素的方法修改為通過(guò) cachedPositions 獲?。?/p>

    因?yàn)槲覀兊腸achedPositions 是一個(gè)有序數(shù)組,所以我們?cè)谒阉鲿r(shí)可以利用二分查找來(lái)降低時(shí)間復(fù)雜度

getStartIndex?=?(scrollTop?=?0)?=>?{
??let?idx?=?binarySearchnumber>(this.cachedPositions,?scrollTop,?
????(currentValue:?CachedPosition,?targetValue:?number)?=>?{
??????const?currentCompareValue?=?currentValue.bottom;
??????if?(currentCompareValue?===?targetValue)?{
????????return?CompareResult.eq;
??????}

??????if?(currentCompareValue?????????return?CompareResult.lt;
??????}

??????return?CompareResult.gt;
????}
??);

??const?targetItem?=?this.cachedPositions[idx];

??//?Incase?of?binarySearch?give?us?a?not?visible?data(an?idx?of?current?visible?-?1)...
??if?(targetItem.bottom?????idx?+=?1;
??}

??return?idx;
};

??

onScroll?=?(evt:?any)?=>?{
??if?(evt.target?===?this.scrollingContainer.current)?{
????....
????const?currentStartIndex?=?this.getStartIndex(scrollTop);
????....
??}
};
  • 二分查找實(shí)現(xiàn):
export?enum?CompareResult?{
??eq?=?1,
??lt,
??gt,
}



export?function?binarySearch<T,?VT>(list:?T[],?value:?VT,?compareFunc:?(current:?T,?value:?VT)?=>?CompareResult)?{
??let?start?=?0;
??let?end?=?list.length?-?1;
??let?tempIndex?=?null;

??while?(start?<=?end)?{
????tempIndex?=?Math.floor((start?+?end)?/?2);
????const?midValue?=?list[tempIndex];
????const?compareRes:?CompareResult?=?compareFunc(midValue,?value);

????if?(compareRes?===?CompareResult.eq)?{
??????return?tempIndex;
????}
????
????if?(compareRes?===?CompareResult.lt)?{
??????start?=?tempIndex?+?1;
????}?else?if?(compareRes?===?CompareResult.gt)?{
??????end?=?tempIndex?-?1;
????}
??}

??return?tempIndex;
}
  • 最后,我們滾動(dòng)后獲取transform的方法改造成如下:
getTransform?=?()?=>
????`translate3d(0,${this.startIndex?>=?1???this.cachedPositions[this.startIndex?-?1].bottom?:?0}px,0)`;

線上Demo: https://codesandbox.io/s/a-v-list-has-dynamic-inner-height-yh0r7

瀏覽 68
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 国产淫荡视频| 福利网站在线观看| 国产TS变态重口人妖| 五月婷婷综合激情| 久久久精品少妇| 6969电视影片最新更新| 久热精品视频| 婷婷伊人| 欧美特黄AAAAAAAAA片| 2026国产精品视频| 国产麻豆一区二区三区| av网站导航| 免费观看高清无码视频| 熊猫视频91| 亚洲精品电影| 激情五月天成人| 西西444WWW无码大胆| 骚熟妇| 综合激情AV| 91一起草高清资源| 国产精品视频导航| 中文字幕免费一区| 日韩大码无码| 综合色国产精品欧美在线观看| 国产AV天堂| 东京热视频网| 中文字幕精品亚洲熟女| 天天综合干| 日皮视频在线免费观看| 黄片无码视频| jt33免费观看高清| 伊人激情五月| 友田真希一级婬片A片| 欧美插插插| 国产高清做爱免费在线视频| 久久一级片| 操逼网页| 大香蕉三级片| 亚洲黄片免费看| 天天色情| 麻豆激情| 国产伦精一品二品三品app| 大香蕉综合视频| 北条麻妃在线一区二区| 国产av中文| 免费观看亚洲视频| 日韩av综合| 日韩无码中文字| 日韩成人片无码| 中文字幕高清在线中文字幕中文字幕| 天天久久| 91啪啪| 国内操逼视频| 亚洲日韩视频在线观看| 色猫av| 免费草逼视频| 五月丁香中文字幕| AV天堂亚洲| 一本色道久久综合无码人妻 | 欧美日韩亚洲一区二区三区| AV1区二区| 亚洲性爱手机版| 男女操逼视频网站免费| 日本成片网| 在线观看免费完整版中文字幕视频 | 久久婷五月天| 欧美黄色片网站| 毛茸茸BBBBBB毛茸茸| 丰满人妻一区二区三区四区53| 俺也去官网| 日韩日韩日韩日韩日韩| 豆花视频在线免费观看| 97人人爽人人爽人人爽人人爽| 久久久国产精品在线| AV电影一区| 亚洲人人18XXX—20HD| 亚洲无码少妇| 伊人激情五月| 四虎www| 在线观看亚洲中文字幕| 苍井空无码在线观看| 欧美国产第一页| 在线www| 影音先锋av成人电影| 日韩永久免费| 91精品婷婷国产综合久久蝌蚪| 中文字幕成人影片| 国产avwww| 五月天黄色片| 亚洲XXXXX| 亚洲中文字幕色| 天堂婷婷| 懂色AV一区二区三区国产中文在线| 51AV在线| 国产一级片网站| 亚洲精品久久久久avwww潮水| 波多野结衣亚洲视频| 日韩无码内射| 久久久夜夜夜| AV一区二区三区四区| 人妻丰满熟妇av无码区| 99爱爱| 欧美视频中文字幕| 久久99综合| 很很撸| 操逼A片| 99视频精品| 丝袜人妻被操视频| 91双飞会所双飞在线| 乱伦99| 国产成人三级在线| 日韩av成人| 9一区二区三区| 天天日少妇| 国产亚洲成人综合| www日本色| 俺来也俺也啪WWW色| 日本A片免费观看| 日韩无码久久久| 午夜AV无码| 丁香五月婷婷综合| 国产无码激情| 永久免费不卡在线观看黄网站| av不卡免费观看| 午夜成人黄色| 九七无码| 国产免费av在线| 日韩免费三级| 999国产视频| 黄色一级免费电影| 伊人久久免费视频| 99re视频在线| 一区二区三区四区在线| 性色a| 成人亚洲精品一区二区三区| 亚洲欧美在线成人| 丁香六月婷婷综合激情欧美| 91无码人妻精品一区二区蜜桃| 国产色呦呦| 六月丁香网| 国产成人av在线播放| 蜜桃一区二区三区| 波多野结衣无码流出| 国产成人tv| 久操免费在线观看| 久久人人操人人| 成人中文字幕在线观看| 三根一起进菊眼| 尻屄视频在线观看| 成人午夜福利| 亚洲国产一区二区三区四区| 午夜成人国产| 日本一区二区在线视频| 国产精品91在线| 成人无码日韩| 成人乱妇无码AV在线| 亚洲无码偷拍| 最新久欠一区二区免费看| 91精品国产综合久久久蜜臀粉嫩 | 亚洲骚货| 招土一级黄色片| 国产三级片网| 手机看片1024你懂的| 亚洲AV无码成人精品区在线欢看 | 无码人妻精品一区二区50| 日韩三区在线| 大香蕉黄色片| 亚洲免费成人视频| 欧美后门菊门交| 亚洲高清在线| 91丨豆花丨国产极品| 97人妻人人| 日韩三级在线播放| 免费看黄色一级片| 四虎一区| 国产精品资源| 五月丁香在线播放| 久久在线| 国产精品久久久久久久久久久久久 | 北条麻妃无码视频在线| 无套内射无码| 久久久精品免费| 无码啪啪啪| 69av在线| 无码av网| 五月丁香婷婷基地| 一级片在线视频| 久久午夜夜伦鲁鲁一区二区| 翔田千里被躁120分钟| 一区二区三区四区在线视频| 无码五区| 麻豆激情| 伊人成人在线观看| 国产玖玖爱| 精品免费在线| AA毛片| 日韩AV小说| 伊人久久福利视频| 制服.丝袜.亚洲.中文.豆花| 国产成人自拍视频在线观看| 日韩无码免费播放| 一区二区三区免费观看| 一级黄色影片| 国产成人精品一区二区三区视频| 天天色天天爱| 91蜜桃视频| 国产色秘乱码一区二区三区| 91视频福利| 亚洲人成小说| 天堂中文网| 成人视频123| 欧美日韩a片| av无码免费| 福利久久| 69久久久久久久久久| 大香蕉久在线| 亚洲无码91| 国产精品99久久久久的广告情况| 操逼电影| 欧美视频在线观看| 成人电影A片| 九九韩剧网最新电视剧免费观看| 亚洲天堂2025| 黄片www| 最新毛片网站〖网:.〗| 一区二区三区四区五区| 日韩人妻在线视频| 狠狠操狠狠操| 欧美日韩视频一区二区| 激情免费视频| 懂色aV| 人妻av一区二区三区| 日韩色逼| 夜夜高潮夜夜爽| 不迷路福利视频| 久久久久久久久毛片| 免费做a爰片77777| 精品二区| 西西4444www大胆无吗| 精品国产久久久久久| 国产精品午夜成人免费| 五月天av在线观看| 久精久久| 午夜a片| 黄片视频免费| 国产中文字字幕乱码无限| 成人无码区免费A片在线软件| h网站在线观看| 人人摸人人操人人爽| 黄色视频免费在线观看网站| 操BBBB| 一级黄色视频日逼片| 国产乱子伦精品久久| 无码视频一区二区三区| 99视频在线| 亚洲伊人影院| 成人无码日韩| 中文字幕免费在线看一区七区| 久久久久久久久黄色| 麻豆高清无码| 国产成人av| 在线观看三级| 男女69视频| 日韩经典视频在线播放| 成人精品秘久久久按摩下载| 俺也去啦WWW色官网| 无码av无码AV| 怡春院在线视频| 九色PORNY国产成人| 欧洲肥胖BBBBBBBBBB| 亚洲视频福利| 人人操天天操| 天堂无吗| 中文字幕成人A片| 一级AV| 五月丁香婷中文字幕| 高清无码中文字幕在线观看| 91大香蕉| 亚洲AV无码乱码国产精品黑人| 无码操逼视频| 国产偷拍精品视频| 影音先锋成人在线资源| 日韩成人无码视频| 青青草Av| 亚洲精品秘一区二区三小| 丰满人妻一区二区三区| 日本豆花视频| 国产一级a一级a免费视频| 伊人AV在线| 99精品视频16在线免费观看| 亚洲黄片免费观看| 夜夜天天人人| 综合中文字幕| 色婷婷激情五月天| 日韩操屄视频| 日本三级片在线| 欧美一级生活片| 国产综合av| 人人干人人操人人爱| NP玩烂了公用爽灌满视频播放 | 国产成人网站免费观看| 欧美老妇操逼| 爱爱中文字幕| 成人视频在线观看黄色18| 尹人香蕉久久| 亚洲黄色三级| 国产黄色免费看| 午夜爱爱爱| 爆操91| 日韩精品黄片| 国产亚洲日韩在线| 欧美日韩在线观看一区| 成人免费A片喷| 午夜爽爽| 国产成人精品无码片子的价格| 日韩人妻精品无码制服| 粉嫩99精品99久久久久久特污兔 | 五月久久婷婷| 五月丁香综合在线| 中文字幕无码Av在线看| 国产精品精品| 九色国产在线| 超碰中文在线| 欧美一区二区三区不卡| 欧美日韩免费在线播放电影在线播放电影在线播放电影免费 | 亚洲无码中文视频| 国产免费小视频| 大香蕉网站视频| 亚洲无码黄片| 免费无遮挡视频网站视频| 97精品人人妻人人| 高潮喷水AⅤ| 一级黄色操逼视频| 淫乱骚穴| 51妺嘿嘿午夜福利在线| 18禁网址| 9久9久9久9久女女女女| 伊人网在线观看| 91麻花| 亚洲高清免费视频| 黄色免费av| 久久思思热| 亚洲欧洲高清无码| 有码在线| 亚洲二区视频| 操逼大全| 四季AV之日韩人妻无码| 91免费观看视频| 91影音先锋| 日韩人妻无码视频| 国产无码高清在线观看| 亚洲无码视频播放| 天天看天天爽| 韩国AV在线| 口工视频| 天天肏| 暖暖日本在线| 日韩无码中文字幕| 亚洲免费观看高清完整版在线观 | 99re这里| 青娱在线视频| 插插插视频| 欧美一级无码| 亚洲另类色图| 91伊人久热精品| 高清av无码| 高H网站| 免费在线观看黄色| 人人操人人爽人人妻| 天堂综合网| 人成无码| 久久午夜无码鲁丝片午夜精品| 我和岳m愉情XXXⅩ视频| 成人aV免费观看| 自拍偷拍av| 欧美成人社区| 西西4444WWW无码精品| 色情片在线播放| 亚洲AV男人天堂| av无码av天天av天天爽| 国产内射在线观看| 无码免费在线观看视频| 国产xxxx| 少妇做爱| JlZZJLZZJlZZ亚洲女人17| 99精品视频免费看| 日韩资源站| 91精品丝袜久久久久久久久久粉嫩| 欧美成人免费观看| 欧美日韩精品| 亚洲黄色毛片| 91麻豆国产在线观看| 熟妇人妻丰满久久久久久久无码| 69精品免费视频| 国产激情网| 国精自拍| 91丨露脸丨熟女| 大香蕉尹人视频| 亚洲国产精品一区二区三区| 五月天开心网| 免费的黄色视频网站| 五月天无码视频| 91网站在线播放| 日韩人妻无码专区一区二区| 黄色一级免费电影| 欧美三区四区| 欧美级毛片一进一出| AV乱伦网站| www.大吊视频| 在线观看国产一区| 国产男女无套免费| 69免费视频| 99久热在线精品视频| 懂色一区二区三区免费| 2025AV天堂| 曰韩精品| 人妻无码中文字幕免费视频蜜桃| 成人黄色性爱视频| 2025天天操夜夜操| 你懂的在线播放| 在线观看日韩欧美| 国产三级黄色AV| 欧美一区不卡| 中文字幕在线无码视频| 水蜜桃视频网站| AV午夜| 国产毛片18水真多18精品| 久久久久久免费视频| www.五月天.con| 亚洲AV无码成人精品区天堂小说| 91在线无码精品秘入口三人| 北条麻妃九九九在线视频| 男女啪啪免费| 欧美亚洲自拍偷拍| 黄片网址在线观看| 蜜臀色欲AV无码人妻| www三级片| 成人在线看片| 欧美日韩国产一区二区三区| av女人的天堂| 韩国三级AV| 躁BBB躁BBB添BBBBBB| 99免费热视频在线| 熊猫视频91| 无码一二三四| 天天日天天色天天干| 五月天激情午夜福利| 成人毛片18| 成人黄色在线| 91热热| 苍井空一区二区三区四区| 18禁在线| 苍井空精毛片精品久久久| 亚洲艹| 国产人妖TS重口系列网站观看| 老妇bbw| 久久夜色精品| 搡女人视频国产一级午夜片| 男女日皮视频| 亚洲日韩成人在线| 操国产美女| 成人精品免费视频| 午夜在线观看视频| 久久夜色精品| 肏网站| 日韩资源站| 成人视频网站在线观看| 亚洲va视频| 加勒比无码人妻| 成全在线观看高清的| 人人弄人人| 久久久国产视频| 五月丁香性爱| 少妇在厨房| 日韩久久综合| 欧美亚洲成人在线观看| 嫩BBB搡BBB搡BBB搡| www.91熊猫成人网| 中文字幕乱码亚洲无线码按摩| 玩弄人妻少妇500系列视频| 91黑人丨人妻丨国产丨| 波多野成人无码精品69| 国产成人A∨| 在线无码高清| 啪啪视频最新地址发布页| 北条麻妃91视频| 精品久久免费| 俺去也视频| 99热3| 日韩中字幕无码| 免费精品黄色网页| 麻豆mdapp01.tⅴ| 国产视频不卡| 欧美深夜福利视频| 日本一区二区三区免费看| 人人爽人人干| 热久在线| 国产又爽又黄免费观看| 怡春院熟女精品AV| 久久大鸡吧| 一道本一区二区三区| 久久视频在线| 美女裸体视频网站| 男女av| 人妻丰满熟妇av无码区| 3D动漫精品一区二区在线播放免费| 苍井空在线播放| www.操逼| 水密桃网站| 男女操逼视频网站| 爱射网| 欧美精品久久久久久久久爆乳| 午夜香蕉| 艳妇乳肉豪妇荡乳AV无码福利| 国产无码影视| 欧美XXXXBBBB| 久久三级| 内射无码专区久久亚洲| 丁香五月激情啪啪啪| 黄色大片视频| 午夜av在线播放| 免费a在线| 五月天狠狠干| 91精片| 91在线视频免费播放| 欧美综合网在线观看| 成人免费无码婬片在线| www.91国产| 久久婷婷五月综合伊人| 天天色天天撸| 四虎激情影院| 亚洲视屏| 成人免费黄色| 成人精品视频网站| 亚州v| 伊人啪啪| 成人肏逼视频在线| 一区视频| 日皮视频免费在线观看| 久久嫩草国产成人一区| 亚洲日韩欧美色图| 炮友五月天| 九九r在线精品观看视频| 无码视频一区二区| 亚洲无码精品在线观看| 欧美日韩高清一区二区三区| 波多野结衣AV在线观看| AV第一页| 最全av在线| 日韩黄色三级片| 国产亚洲激情| 免费av片| 五月天丁香花| 一级片在线免费看| av色站| 一本一道久久综合狠狠躁牛牛影视| 亚洲一区在线播放| 国产aⅴ激情无码久久久无码| 神马午夜精品91| 午夜操逼逼| 欧美一级特黄AAAAAA片在线视频| 台湾省成人网站| 91人人澡人人爽人人看| 日韩无码二区| 毛片黄色| 日韩精品成人片| 国产精品国产三级国产| 学生妹一级| 日韩精品你懂的| 国产精品一区二区三区四区| 久久精品国产视频| 国产色视频在线| 神马午夜秋霞不卡| 国产精品99视频| 国产在线一区二区三区四区| 亚洲精品少妇| 欧美肏逼网| 最新中文字幕一区| 国产AV大全| 插菊花综合网2| 中文字幕国产在线| 麻豆国产91在线播放| 久久一二三四| 四川少BBB搡BBB爽爽爽| AV高清无码在线观看| 国产一级免费观看| aaa在线免费视频| 人人操人人射| www.av在线| 俺也去在线视频| 国产精品三级在线观看| 99热在线观看免费| 国产99自拍| 精品国产va久久久久久久| A免费在线观看| 欧美一级片网站| 亚洲综合网在线| 中文字幕日本电影| 色欲国产精品欧美在线密| 日本精品人妻无码77777| 四虎国产| 午夜AV影院| 性爱av在线| 91丨九色丨老农村| 日本中文字幕免费| 国产成人亚洲综合AV婷婷 | 特级西西人体WWWWW| 日本一级视频| 91人妻无码精品一区二区三区| 天堂在线中文网| 久久婷婷五月丁香| 日本久久久久| 伊人免费视频在线观看| 影音先锋女人aV鲁色资源网站 | 成人AV电影在线观看| 日韩成人片| 中文字幕精品无码亚| 黄色三级视频在线观看| 成人无码毛片| 日韩AV高清| 日韩免费无码视频| 亚洲高清无码在线播放| 天天插天天狠天天透| 亚州无码一区| 三级无码电影| 一级A色情大片| 色骚综合| 欧美成人视频网| 免费国产在线视频| 青青草小视频| 亚洲黄色一级电影| 色先锋资源站| 91亚洲国产精品| 欧美精品黄| 91日韩高清| 六十路老熟女码视频| 国产一区二区不卡视频| 色丁香五月| 九九综合精品| 久久性爱免费视频| 特一级黄A片| 人妻无码在线观看| 在线视频三区| 手机在线看片av| 人妖黃色一級A片| 久久中文字幕无码| 色五月婷婷五月天激情| 午夜AV福利影院| 蝌蚪窝免费在线视频| 自拍偷拍福利视频网站| 中文无码高清在线| 未满十八18禁止免费无码网站| 男女啪啪啪| 91在线成人视频| 国产一区2区| 伊人久久久影视大全| 欧美日韩V| 超碰碰碰| 日本A∨在线| 色片免费| 激情人妻网站| 欧美国产在线观看| 新BBWBBWBBWBBW| 欧美成人电影在线观看| 亚洲AV成人无码一区二区三区| 亚洲有码中文字幕| 天天干天天射天天爽| 搡老熟女-91Porn| 99精品全国免费观看| 亚洲日韩视频在线播放| 国产99久久九九精品无码免费| 成人视频一区| 真实野外打野视频| 国产又爽又黄免费网站在线看| 超碰人人摸| 69式荫蒂被添全过程频| 午夜精品久久久久久久| 无码婷婷| 夜夜骑夜夜操| 青草免费视频| 人人草人人摸| 女人的天堂AV在线观看| 国产精品久久久一区二区三区| 很色很黄的A片一| 国产污视频| 日本天天色| PORNY九色视频9l自拍| 仓井空一区二区三区| 性生活无码视频| 亚洲色五月天| 日韩无码性爱视频| 在线观看日韩AV| 操人网站| 青青成人| 国产AA| 男人天堂网站| 91大神在线免费看| 黄色片久久久| 色哟哟AV| 在线成人网站| 亚洲女人天堂| 国产成人超碰| 久草在在线视频| 大地8免费高清视频观看大全| 久久久久人| 特一级黄A片| 中文字幕在线视频无码| 欧美精品黄| a片免费观看视频| 青青草公开视频| 黄色电影一区二区| 欧美性少妇| 中文字幕日韩视频| 一级理论片| 亚洲无码视频免费看| 四虎精品一区二区三区| 欧美操操操| 99成人乱码一区二区三区在线 | 中文字幕激情精品| 久久撸视频| 久久久精品999| 少妇搡BBBB搡BBB搡18禁| 91一起草高清资源| 日韩网站在线观看| 无码中文字幕在线视频| 国产色综合视频| 亚洲色欲色欲www在线成人网| 特级西西444www高清| 中日韩无码| 国产—a毛—a毛A免费| 久久综合中文字幕| 黄色无码视频| 成人AV婷婷| 亚洲女人天堂AV| 欧美一区二区三区系列电影| 美女久久久久| 精品一区电影| 日本翔田千里奶水| 天天日天天射天天干| 夜夜欢天天干| 你懂的在线视频| 国内成人自拍| 欧美熟妇擦BBBB擦BBBB| 伊人成人片| av在线资源播放| 亚洲激情视频在线观看| 亚洲日韩av在线| 五月天激情婷婷| 色婷婷五月天| 人人澡人人爽欧一区| 精品一区二区免费视频| 波多野结衣Av在线| 精品无码在线| a在线免费| 123操逼| 亚洲精品欧美久久婷婷| 久久精品国产AV一区二区三区| 91亚洲精华国产精华精华液| 日本韩国欧美18| 韩国三级HD久久精品HD| 久草青青草| 日本中文字幕无码| 91人妻人人澡人人爽人人精品| 麻豆91精品91久久久停运原因| 国产无遮挡又黄又爽又色视频软件 | 婷婷国产视频| 站街大龄熟女x| 淫揉BBB揉揉揉BBBBB| 国产精品久久久久久久久免费无码| 9991区二区三区四区| 亚洲欧美视频| 麻豆一二三区| 超碰人人在线观看| 亚洲操逼片| 青春草在线视频| 免费一级黄色毛片| 日韩porn| 亚洲无码视频看看| 国产成人高潮毛片| 亚洲人BBwBBwBBWBBw| 中文字幕乱伦性爱| 中文字幕AV免费观看| 九色欧美| 国产乱伦对白| 国产乱子伦一区二区三精品| 三级无码视频| 嫖中国站街老熟女HD| 91精品丝袜久久久久久| 亚洲另类天堂| 婷婷丁香综合| 亚洲一级无码| 自拍偷拍一区二区三区| 五月婷婷导航| 午夜福利国产| 成人午夜视频在线观看| 999精品视频| 91久久精品国产91久久公交车| 日韩少妇无码| 亚洲国产精品成人综合| 中文字幕亚洲在线观看| 亚洲无码门| 水果派解说AV无码一区| 日韩欧美中文字幕公布| 四虎永久在线精品| 天天做天天爱| 午夜九九| A片免费在线| 成人精品在线视频| 无套免费视频欧美| 久9久9久9久9久9久9| 色噜噜狠狠一区二区三区牛牛影视| 97人妻一区二区三区| 热热AV| 日韩黄色电影在线观看| 一级a片在线| 天天爱av| 豆花视频logo| 日韩在线视频免费观看| 亚洲最新无码视频| 天天干人人干| 在线观看无码高清| 亚洲无码在线播放| 北条麻妃九九九在线视频| 亚洲成人免费观看| 国产56页| 久久久亚洲AV无码精品色午夜| 91aV视频| 国产综合在线播放| 国产www| 成人五月天黄色电影| 黄色天堂| 黄色成人视频在线免费观看| 韩国中文字幕HD久久| 免费三级怡红院| 91精品国产综合久久久蜜臀主演| 中文字幕不卡+婷婷五月| 亚洲精品鲁一鲁一区二区三区| 91天天爽| 国产免费一区二区| 2025AV中文字幕| 青青草网址| 一本一道伊人99久久综| 亚洲AV免费| 国产精品免费一区二区三区四区视频 | 婷婷丁香五月激情一区综合网| 91视频免费| 日韩在线中文字幕视频| 野花av| aaa国产精品| 人人色人人看| 国产在线第一页| 国产日韩a| 国产精品一区二区三区在线| 无码免费一区二区| 特特级毛片| 麻豆91精品91久久久| 久久久久久精| 成人女人18女人毛片| 久久久成人影片| 国产综合AV| 无码日韩AV| 男女av网站| eeuss一区| 中文字幕乱码亚洲无线码按摩| 免费黄色福利视频| 特级西西WWW444人体聚色| 欧美又粗又大AAA片| AV自拍| 青草精品视频| 亚洲中文字幕播放| 中文一区在线| 少妇特黄A一区二区三区| 精品视频在线免费| 无码一区二区久久| 无码一道本| 激情开心站| 天天射天天射| 日韩综合在线| 啪啪动漫| 无码AV电影| 国产不卡网| 羞羞午夜| 欧美精品在线播放| 69AV视频网站| 一区二区入口| www日韩| 高清无码直接看| 婷婷五月综合在线| 淫荡少妇美红久久久久久久久久| 亚洲一区二区久久| 一道本一区| 日韩综合不卡| 久久女人网| www.蜜桃| 日本A∨在线| www.A片| 中文字幕视频一区日日骚| 精品国产va久久久久久久 | 日韩一区二区三免费高清在线观看 | 狠狠色噜噜狠狠狠888|