精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

「源碼剖析」如何實現一個虛擬DOM算法

開發 前端 算法
我們希望是在更新的時候通過新渲染的虛擬DOM樹和舊的虛擬DOM樹進行對比,記錄這兩顆樹的差異。記錄下來的不同就是我們需要對頁面真正的DOM操作,然后把它們渲染在真正的DOM結構上,頁面就對應的變化了。

 [[378869]]

 上篇文章《虛擬DOM如何進化為真實DOM》中講到了如何通過虛擬DOM樹轉化為真實DOM渲染到頁面中。但是在渲染的過程中,我們直接將新的虛擬DOM樹轉化成真實DOM替換掉舊的DOM結構。當真實的DOM中的狀態或者內容發生變化的時候,重新渲染新的虛擬DOM樹再替換掉舊的,這樣的話會顯得很無力。設想一種情景,當我們對整個DOM結構中只是修改了一個小的數據甚至是一個標點符號的時候或者數據量很大的時候,我們要把原來舊的DOM結構全部替換掉,這樣的話對計算機而言太浪費性能了。

故我們希望是在更新的時候通過新渲染的虛擬DOM樹和舊的虛擬DOM樹進行對比,記錄這兩顆樹的差異。記錄下來的不同就是我們需要對頁面真正的DOM操作,然后把它們渲染在真正的DOM結構上,頁面就對應的變化了。這樣就實現了:看似視圖全部結構得到了最新的渲染,但是最后操作DOM結構的時候只是改變了與原結構不同的地方。

即虛擬DOM的diff算法的主體思路是:

1.將虛擬DOM結構轉化為真實的DOM結構替換到舊的DOM(第一次舊的為undefined),渲染到頁面中。

2.當狀態變化的時候,新渲染一顆虛擬DOM樹和原來舊的虛擬DOM樹對比,對比之后記錄下差異。

3.將最終由差異的部分轉化成真實DOM結構渲染到頁面上。

實現

在舊的虛擬節點和新的虛擬節點的對比過程中會出現以下幾種情況,下面我們以Vue為例看Vue2.0是Diff算法是怎么實現的:

比較兩個元素的標簽

如果標簽不一樣的話直接替換掉,例如:div變成p

  1. div->p 
  2.  
  3. <<<<<<<HEAD 
  4. <p>前端簡報</p> 
  5.  
  6. ========= 
  7.  
  8. <div>前端簡報</div> 
  9. >>>>>>>> 

  判斷虛擬節點的tag屬性是否相等,如果不相等將新的虛擬DOM樹轉化為真實DOM結構把原來節點替換掉

  1. if (oldVnode.tag != vnode.tag) { 
  2.   return oldVnode.el.parentNode.replaceChild(createElm(vnode), oldVnode.el); 

效果圖:

圖片

比較兩個元素的文本

當標簽一樣的時候比較文本是否一樣。如果文本不一樣的話那么直接替換掉文本內容。

  1. <<<<<<<HEAD 
  2. <div>前端</div> 
  3. ========= 
  4. <div>簡報</div> 
  5. >>>>>>>> 

 兩個節點的tag都是div,故比較孩子虛擬DOM樹的是否一樣,孩子的tag為undefined說明是文本節點,此時比較本文內容text是否一致即可

  1. if (!oldVnode.tag) { 
  2.     //文本的對比 
  3.     if (oldVnode.text != vnode.text) { 
  4.       return (oldVnode.el.textContent = vnode.text); 
  5.     } 
  6.   } 

效果圖:

圖片

比較標簽屬性

如果兩個標簽一樣那么比較標簽的屬性,當屬性更新的時候通過新舊屬性的對比會出現下面幾種情況:

1、屬性對比

如果舊的虛擬節點有,新的虛擬節點沒有那么需要刪除舊的虛擬節點上的屬性。

  1. let newProps = vnode.data || {}; //新的屬性 
  2. let el = vnode.el; 
  3. //老的有 新的沒有 需要刪除屬性 
  4. for (let key in oldProps) { 
  5.   if (!newProps[key]) { 
  6.     el.removeAttribute(key); //移除真實dom的屬性 
  7.   } 

反過來,如果舊的虛擬節點沒有,新的虛擬節點有那么直接設置新的屬性即可

  1. //新的有 那就直接用新的去更新即可 
  2. for (let key in newProps) { 
  3.     el.setAttribute(key, newProps[key]); 
  • 對應的源碼地址:src\platforms\web\runtime\modules\attrs.js

2、樣式處理

如果老的樣式中存在新的樣式沒有那么刪除老的樣式。

  1. - style={color:red} 
  2. + style={background:red} 

  1. let newStyle = newProps.style || {}; 
  2. let oldStyle = oldProps.style || {}; 
  3. //老的樣式中有的 新的沒有  刪除老的樣式 
  4. for (let key in oldStyle) { 
  5.   if (!newStyle[key]) { 
  6.     el.style[key] = ""
  7.   } 

相反如果老的樣式沒有,新的樣式存在那么直接更新新的樣式即可

  1. for (let key in newProps) { 
  2.   if (key == "style") { 
  3.     for (let styleName in newProps.style) { 
  4.       el.style[styleName] = newProps.style[styleName]; 
  5.     } 
  6.   }  
  • 對應的源碼地址:src\platforms\web\runtime\modules\style.js

3、類名處理

對于類名處理我們使用新節點的類名

  1. - class="title ant-title" 
  2. + class="title ant-mian-title" 

  1. for (let key in newProps) { 
  2.  if (key == "class") { 
  3.     el.className = newProps.class; 
  • 對應的源碼地址src\platforms\web\runtime\modules\class.js

比較兒子

在比較兒子的過程中可以分為以下幾種情況:

1、老節點有兒子,新節點沒有兒子刪除老節點的兒子即可

  1. if (isDef(oldCh)) { 
  2.   removeVnodes(oldCh, 0, oldCh.length - 1) 
  3. }  
  4. ========================================= 
  5. if (oldChildren.length > 0) { 
  6.      el.innerHTML = ""

2、老節點沒有兒子,新節點有兒子遍歷children轉化為真實的DOM結構添加到頁面中

  1. if (isDef(ch)) { 
  2.   if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, ''
  3.   addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue) 
  4. }  
  5. =============================================================== 
  6. if (newChildren.length > 0) { 
  7.   for (let i = 0; i < newChildren.length; i++) { 
  8.      let child = newChildren[i]; 
  9.      el.appendChild(createElm(child)); 
  10.   } 

3、老節點有兒子,新節點有兒子

當老節點的兒子和新節點的兒子都存在并且不相等的時候,這種情況比較復雜也是diff算法的核心。

在vue2.0中比較老節點和新節點區別的時候采用了雙指針的方式,通過同時向同一個方向循環老節點和新節點,只要有一個節點循環完成就結束循環。如果是老節點先結束,那么將新節點剩余的元素添加到渲染列表;如果是新節點先結束,那么將舊節點剩余的元素刪除即可。

定義開頭指針其中包括老節點的開始位置和結束位置,新節點的開始位置和結束位置。

  1. let oldStartIndex = 0; //老的索引 
  2.  let oldStartVnode = oldChildren[0]; //老的索引指向的節點 
  3.  let oldEndIndex = oldChildren.length - 1; 
  4.  let oldEndVnode = oldChildren[oldEndIndex]; 
  5.  
  6.  let newStartIndex = 0; //新的索引 
  7.  let newStartVnode = newChildren[0]; //新的索引指向的節點 
  8.  let newEndIndex = newChildren.length - 1; 
  9.  let newEndVnode = newChildren[newEndIndex]; 

通過判斷兩個節點的key和tag是否相等來確定同一元素

  1. function sameVnode (a, b) { 
  2.   return ( 
  3.     a.key === b.key && ( 
  4.       ( 
  5.         a.tag === b.tag && 
  6.         ... 
  7.       ) || ( 
  8.         ... 
  9.       ) 
  10.     ) 
  11.   ) 

正序排列

如果多余的節點的右邊的話,那么從左往右依次判斷老的開始節點和新的開始節點是否是同一節點,如果是同一節點調用patchVode方法去遞歸子節點,將老節點和新節點的下標加1向右移動,直到下標大于children的長度。


  1. if (sameVnode(oldStartVnode, newStartVnode)) { 
  2.   patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx) 
  3.   oldStartVnode = oldCh[++oldStartIdx] 
  4.   newStartVnode = newCh[++newStartIdx] 
  5. }  

效果圖:

圖片

如果是新節點多余添加到渲染視圖,如上圖從左到右對比時,g節點的下一個el是null,insertBefore相當于appendChild方法向后插入;如果是從右向左,g節點的下一個el是a,那么采用insertBefore相當于向a前面插入節點。

  1. if (oldStartIndex > oldEndIndex) { 
  2.      for (let i = newStartIndex; i <= newEndIndex; i++) { 
  3.       let ele = 
  4.         newChildren[newEndIndex + 1] == null 
  5.           ? null 
  6.           : newChildren[newEndIndex + 1].el; 
  7.       parent.insertBefore(createElm(newChildren[i]), ele); 
  8.     } 

如果是老節點多余,那么說明這些節點是不需要的,刪除掉即可,如果在刪除的過程中出現null,說明這個節點已經處理過了跳過即可。

  1. if(newStartIdx > newEndIdx){ 
  2.   for (let i = oldStartIndex; i <= oldEndIndex; i++) { 
  3.      let child = oldChildren[i]; 
  4.      if(child!= undefined){ 
  5.        parent.removeChild(child.el); 
  6.      } 
  7.   } 

如果多余的節點在左邊,從新老節點的結束節點開始下標依次減1

  1. if (sameVnode(oldEndVnode, newEndVnode)) { 
  2.   patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx) 
  3.   oldEndVnode = oldCh[--oldEndIdx] 
  4.   newEndVnode = newCh[--newEndIdx] 

反轉排列

如果遇到新老節點反轉的情況,通過老節點的開始節點和新節點的結束節點作對比或者老節點和結束節點和新節點的開始節點作對比。


如果老節點的開始節點和新節點的結束節點是同一節點,那么將老的開始節點插入到老的結束節點的下一個節點之前,然后依次分別向右向左移動節點對應的下標,獲取對應的值繼續遍歷。

  1. if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right 
  2.   patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx) 
  3.   canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm)) 
  4.   oldStartVnode = oldCh[++oldStartIdx] 
  5.   newEndVnode = newCh[--newEndIdx] 

如果老節點的結束節點和新節點的開始節點是同一節點嗎,那么將老節點的結束節點插入到老節點的開始節點前面,然后依次分別向左向右移動節點對應的下標,獲取對應的值繼續遍歷。

  1. if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left 
  2.   patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx) 
  3.   canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm) 
  4.   oldEndVnode = oldCh[--oldEndIdx] 
  5.   newStartVnode = newCh[++newStartIdx] 
  6. }  

毫無關系排列

如果在對比的過程中兒子之間沒有任何的關系,通過從新節點的開始節點開始依次和老節點的所有節點作對比,如果沒有相同的就創建新的節點插入的老節點的開始節點之前,如果在循環的過程中找到了相同的元素,那么直接復用老元素,將和新節點相同的老節點插入到老節點的開始節點之前,為了防止數組的塌陷問題,將移走的老節點的位置設為undefined,最后將多余的老節點全部刪除即可。


設置緩存組使用老節點的key和下標做一個映射表,新節點的key去老的映射表里篩選,如果沒有篩選到,那么就不復用直接創建新節點插入到老節點的開始節點之前。

  1. function createKeyToOldIdx (children) { 
  2.   let i, key 
  3.   const map = {} 
  4.    children.forEach((item, index) => { 
  5.       if (isDef(item.key)) { 
  6.         map[item.key] = index; //{a:0,b:1,c:2,d:3,e:4,f:5,g:6} 
  7.       } 
  8.   return map 

如果在老節點中找到,那么移動老節點到老節點開始節點之前

  1. let map = createKeyToOldIdx(oldChildren); 
  2.  //兒子之間沒有關系 
  3. let moveIndex = map[newStartVnode.key];  //拿到開頭的虛擬節點的key去老的里面找 
  4.  
  5. if(moveIndex == undefined){ 
  6.   parent.insertBefore(createElm(newStartVnode),oldStartVnode.el); 
  7. }else
  8.   let moveVNode = oldChildren[moveIndex];  //這個老的虛擬節點需要移動 
  9.   oldChildren[moveIndex] = null
  10.   parent.insertBefore(moveVNode.el,oldStartVnode.el); 
  11.   patch(moveVNode,newStartVnode)  //比較屬性和兒子 
  12. newStartVnode = newChildren[++newStartIndex]  //用新的不停的去老的里面找 

在移動的過程中開始指針和結束指針可能存在指向null的情況,如果指向null的話那么無法在進行比較,可以直接跳過,指向下一個元素即可。

  1. if (isUndef(oldStartVnode)) { 
  2.   oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left 
  3. else if (isUndef(oldEndVnode)) { 
  4.   oldEndVnode = oldCh[--oldEndIdx] 

源碼地址:src/core/vdom/patch.js

為什么要使用key?

人丑話不多先看圖

圖片

有key

圖片

沒有key

如上圖所示,第一個圖為有key的情況,第二個圖為沒有key的情況,可以很明顯的看到所展示內容如果有key的話,復用了key為A,B,C,D的4個節點,結果只是將新創建的E節點插入到C節點的前面完成渲染。如果沒有key的話,那么創建了E,C,D三個節點,降低了復用率,性能方面肯定沒有有key 的情況高。

為什么不能用index作為key呢?

平時開發過程中,如果只是通過頁面靜態渲染是可以使用index作為key的,如果在頁面上有復雜的邏輯變化,那么使用index作為key相當于沒有key。

  1. <li index=0>A</li>      <li index=0>C</li> 
  2. <li index=1>B</li>      <li index=1>B</li> 
  3. <li index=2>C</li>      <li index=2>A</li> 

 

如上代碼所示,將下標為0和2的A和C變換位置之后需要重新創建節點A和C,此時C的下標為0,A的下標為2。而以id或者唯一標識作為key的話,相當于是將A和C元素的位置進行平移。平移的性能比創建節點的性能高。

在使用index作為key的時候還會產生意想不到的問題,假如我們把B節點刪除,我們最開始取值為B,現在取值變成了C。

總結

Vue2.0的diff算法pathVode方法的基本思路可以總結為以下幾點:

1.判斷oldVode和newVode是否是同一對象,如果是的話直接return。2.是定義真實DOM為el。

3.如果oldVode和newVode都有文本節點并且不相等,那么將old的文本節點設置為newVode的文本節點。

4.如果oldVode有子節點newVode沒有,那么刪掉子節點。

5.如果oldVode沒有子節點newVode有。那么將子節點轉化為真實DOM添加到el中。6.如果都有子節點,那么執行updateChildren函數比較子節點

以上就是Diff算法的整個過程,它對整個Vue渲染過程的性能有著至關重要的作用。

 

責任編輯:姜華 來源: 前端簡報
相關推薦

2017-08-11 17:55:48

前端JavaScript模板引擎

2022-11-29 17:34:43

虛擬形象系統

2020-10-26 08:19:53

算法隊列

2018-06-22 10:30:56

C語言虛擬機編譯器

2021-01-18 07:15:22

虛擬DOM真實DOMJavaScript

2021-07-04 10:07:04

Virtual DO閱讀源碼虛擬DOM

2017-12-12 15:24:32

Web Server單線程實現

2018-07-30 16:31:00

javascriptaxioshttp

2009-07-22 17:15:04

C#實現

2009-09-02 15:21:48

2014-02-14 09:37:01

JavascriptDOM

2023-02-26 01:37:57

goORM代碼

2023-03-01 09:39:40

調度系統

2020-08-17 08:20:16

iOSAOP框架

2024-06-12 10:18:33

2015-06-15 12:30:10

Hadooplong編碼剖析

2022-01-26 16:30:47

代碼虛擬機Linux

2014-07-21 10:25:12

ENode開發論壇

2010-09-28 13:24:34

DOM文檔對象模型

2021-11-10 11:40:42

數據加解密算法
點贊
收藏

51CTO技術棧公眾號

亚洲精品国产品国语在线app| 日韩**一区毛片| 精品噜噜噜噜久久久久久久久试看 | 国产成人午夜99999| 性欧美办公室18xxxxhd| 97人妻精品一区二区三区免| 成人av观看| 中文字幕乱码久久午夜不卡| 97超碰人人看人人| 中文字幕免费观看| 亚洲欧美偷拍自拍| 亚洲精品一区在线观看香蕉| 在线视频日韩欧美| 奇米777日韩| 亚洲美女视频在线观看| 欧美凹凸一区二区三区视频| 国产成人精品一区二区无码呦 | 日韩中文av| 91麻豆精品国产无毒不卡在线观看| 男人的天堂狠狠干| 秋霞成人影院| av午夜精品一区二区三区| 国产欧美一区二区白浆黑人| 日韩免费一级片| 亚洲一区二区| 亚洲免费av电影| 丰满人妻一区二区三区免费视频棣| www.久久| 色欧美乱欧美15图片| 黄网站色视频免费观看| 91在线导航| 91看片淫黄大片一级在线观看| 95av在线视频| 国产一区二区在线不卡| 日韩激情视频网站| 欧美激情欧美狂野欧美精品| 久久久久人妻一区精品色| 日韩欧美ww| 精品国产污网站| 久久久久亚洲av片无码v| 国产三级一区| 欧美日韩亚洲激情| 欧美日韩在线一| 9765激情中文在线| 日韩美女视频一区二区| 亚洲国产精品日韩| 成人三级黄色免费网站| 国产婷婷一区二区| 欧美亚洲丝袜| 国产精品99999| 国产欧美久久久精品影院| 欧美lavv| h视频在线播放| 中文字幕第一区第二区| 少妇免费毛片久久久久久久久 | 最近2019中文字幕一页二页| 欧美黄色一级生活片| 亚洲精品中文字幕99999| 亚洲精品国产精品国产自| 污污污www精品国产网站| 国产suv精品一区二区四区视频| 日韩网站在线看片你懂的| 91亚洲国产成人久久精品网站| 欧美一区二区三区不卡视频| 久久国产免费| 国产精品电影久久久久电影网| 久久夜色精品国产噜噜亚洲av| 欧美亚洲三区| 国产精品成人免费视频| 中文无码av一区二区三区| 久久精品99国产国产精| 成人免费网站在线观看| 国产成人精品白浆久久69| 高清视频一区二区| 精品视频免费观看| 国产毛片在线看| 中文字幕一区二区5566日韩| 狠狠干视频网站| www.综合网.com| 亚洲成人动漫一区| 亚洲午夜无码av毛片久久| 主播大秀视频在线观看一区二区| 欧美日韩日日摸| 国产精品欧美性爱| 亚洲黄页网站| 久久久国产影院| 久久精品国产亚洲av高清色欲| 亚洲一区中文| 国产综合久久久久久| 免费a视频在线观看| 99久精品国产| 在线视频一区观看| 999福利在线视频| 欧美四级电影在线观看| 国产又粗又猛又爽又黄| 久久久久久毛片免费看 | 国产在线免费av| 亚洲无线视频| 国产精品电影久久久久电影网| 国产精品一区二区三区在线免费观看 | 天堂av电影在线观看| 中文字幕av在线一区二区三区| 好吊色这里只有精品| 黄色在线免费观看网站| 欧美日韩午夜在线| 在线xxxxx| 99精品在线| 欧洲午夜精品久久久| 91无套直看片红桃| 91一区在线观看| 青青草原网站在线观看| 影视一区二区三区| 亚洲精品久久久久久久久久久久| 青青青视频在线播放| 在线亚洲成人| 国产99在线免费| 日韩成人影视| 日本精品视频一区二区| 国产人成视频在线观看| **女人18毛片一区二区| 欧亚精品中文字幕| 人妻无码中文字幕| 一区二区视频在线| 女同激情久久av久久| 精品国产乱码久久久久久1区2匹| 久久久久久国产精品久久| 在线中文字幕网站| 国产日韩一级二级三级| a在线视频观看| theporn国产在线精品| x99av成人免费| 波多野结衣一区二区三区在线| 成人国产在线观看| 99久久免费观看| 高清国产一区二区三区四区五区| 尤物99国产成人精品视频| 国产精品久免费的黄网站| 99久精品国产| 国产美女网站在线观看| 精品国内亚洲2022精品成人| 久久999免费视频| 国产麻豆精品一区| 亚洲三级小视频| 亚洲欧美手机在线| 天天做天天爱天天综合网2021| 国产精品久久久久久搜索| 欧美美乳在线| 欧美在线一区二区| 影音先锋制服丝袜| 奇米影视一区二区三区| 久久久综合亚洲91久久98| 日韩伦理在线一区| 亚洲人成啪啪网站| 亚洲欧美另类在线视频| 国产亚洲欧美日韩日本| 午夜欧美福利视频| 日韩久久视频| 亚洲www视频| 欧美6一10sex性hd| 亚洲黄色在线观看| 欧美一级特黄视频| 国产欧美一区二区三区网站 | 国产成人精品1024| av在线观看地址| 日韩a级大片| 国产成人福利网站| 欧美三级理伦电影| 日韩欧美中文字幕公布| 日本黄色片视频| 久久蜜臀中文字幕| 天天干天天操天天做| 91精品国产91久久久久久黑人| 99中文字幕| 日韩脚交footjobhd| 中日韩美女免费视频网址在线观看| 在线观看国产黄| 一区二区三区四区高清精品免费观看| 亚洲av无码一区东京热久久| 国产精品久久久久久模特| 日韩精品欧美在线| 国产精品美女久久久久人| 久久久久国产精品www| 国产露出视频在线观看| 91精品一区二区三区久久久久久| 国产网站在线看| 国产精品人妖ts系列视频| 少妇欧美激情一区二区三区| 亚洲最黄网站| 99精品一级欧美片免费播放| 国产三级精品三级在线观看国产| 日韩美女免费视频| 91最新在线视频| 日韩成人在线免费观看| 91麻豆国产在线| 欧美视频在线免费看| 久久福利免费视频| 91网址在线看| 亚洲国产日韩在线一区| 日韩精品91亚洲二区在线观看 | 尤物视频在线看| 亚洲精品一区av在线播放| 国产日韩欧美一区二区东京热| 欧美日韩激情视频| 国产黄色的视频| 久久精品在线观看| 久久久久亚洲AV成人网人人小说| 日韩—二三区免费观看av| 国产日韩亚洲欧美在线| 日韩一区二区在线| 欧美人与物videos另类| 中文在线综合| 91在线中文字幕| 午夜激情成人网| 国内精品中文字幕| 国产在线一区二区视频| 亚洲欧洲偷拍精品| 无码精品在线观看| 日韩欧美国产精品一区| 亚洲中文字幕一区二区| 色综合久久天天| 亚洲国产成人精品激情在线| 一区二区三区四区国产精品| 九九热视频在线免费观看| 国产午夜精品福利| 国产精品边吃奶边做爽| 国产不卡视频在线观看| 一级做a免费视频| 男男视频亚洲欧美| 超碰影院在线观看| 亚洲尤物影院| 国产女大学生av| 亚洲激情网址| www.av毛片| 激情欧美日韩一区| 少妇大叫太大太粗太爽了a片小说| 天天影视欧美综合在线观看| 亚洲区一区二区三区| 精品国产一区二区三区噜噜噜 | 亚洲视频大全| www..com日韩| 99这里有精品| 无码播放一区二区三区| 亚洲黄色影院| 亚洲中文字幕无码专区| 亚洲精品四区| 日本黄网站免费| 葵司免费一区二区三区四区五区| 2022亚洲天堂| 天堂在线一区二区| 一区二区三区视频在线观看免费| 日本少妇一区二区| 黑森林精品导航| 老司机免费视频一区二区三区| 亚洲这里只有精品| 精品一区二区久久| 亚洲天堂一区二区在线观看| 国产精品18久久久久久vr| 久久久久久久久久久影视| 国产乱国产乱300精品| 国产精品99精品无码视亚| 国产suv精品一区二区883| 成年人看片网站| 成人高清免费观看| av直播在线观看| 国产喂奶挤奶一区二区三区| 极品久久久久久久| 成人免费一区二区三区视频| 黄页网站免费观看| 欧美日韩亚洲一区二区三区| 在线观看日本网站| 欧美亚州韩日在线看免费版国语版| 中文天堂在线播放| 日韩一级免费观看| 五月天婷婷社区| 亚洲男人天堂手机在线| 最近高清中文在线字幕在线观看| 久久久精品影院| 精品精品导航| 日韩美女视频免费在线观看| 亚洲二区av| 国产精品区二区三区日本| 日韩一级电影| 亚洲日本理论电影| 亚洲黄色影片| 亚洲欧美视频二区| 国产成人99久久亚洲综合精品| 日本aaa视频| 日韩毛片精品高清免费| 日本亚洲色大成网站www久久| 色av综合在线| av综合在线观看| 日韩精品在线免费观看视频| 欧美成人精品一区二区男人看| 久久久久久久久久久免费 | 午夜日韩在线| 人妻无码视频一区二区三区| 国产乱码精品1区2区3区| 国产高清自拍视频| 亚洲天堂2014| 五月婷婷激情视频| 日韩精品综合一本久道在线视频| 久草视频视频在线播放| 欧美成人精品不卡视频在线观看| 欧美xoxoxo| www.久久艹| 91亚洲国产成人久久精品| 久久视频这里有精品| 久久99精品久久久| 老鸭窝一区二区| 亚洲黄色小视频| 中文字幕在线网址| 日韩av最新在线| 免费网站在线观看人| 国产精品香蕉国产| 亚洲成a人片77777在线播放 | 久久精品人人做人人爽电影| 综合天堂久久久久久久| 污片在线免费看| 久久久久久久综合日本| 国产一级二级毛片| 欧美一区二区播放| 又爽又大又黄a级毛片在线视频| 91av在线精品| 美女视频亚洲色图| 国产 欧美 日本| 国产一区二区三区四区在线观看| 久久精品三级视频| 在线国产电影不卡| 欧美日韩国产综合视频| 国模吧一区二区三区| 亚洲国产中文在线二区三区免| 一本色道久久综合亚洲二区三区| 裸体素人女欧美日韩| 国产成人无码一区二区在线观看 | 免费看毛片的网址| 国产成人亚洲综合a∨猫咪| 羞羞在线观看视频| 欧美日韩精品一区视频| av成人手机在线| 国产精品久久久久久久久久东京| 国产影视精品一区二区三区| 青青草原成人网| 久久综合久久99| 精品国产一区二区三区四| 日韩成人在线视频观看| 亚洲天堂免费电影| 欧美精品一区三区在线观看| 老牛嫩草一区二区三区日本| 国产一区二区三区精品在线| 91成人在线免费观看| 精品视频二区| 国产成一区二区| 日韩成人激情| 中文字幕国产高清| 一区2区3区在线看| 日本激情一区二区三区| 91精品国产99| 久久av导航| a在线观看免费视频| 中文字幕一区免费在线观看| 国产女18毛片多18精品| 欧美激情中文网| 欧美freesex8一10精品| 日韩一级在线免费观看| 亚洲国产精品黑人久久久| 国产精品羞羞答答在线| 欧美激情视频一区二区| 色天下一区二区三区| 天天天干夜夜夜操| 中文字幕一区不卡| 国精品人妻无码一区二区三区喝尿| 97在线视频精品| 日韩精品欧美激情一区二区| 亚洲制服在线观看| 精品久久久中文| 91短视频版在线观看www免费| 91日韩在线视频| 国产日韩1区| 国产精品一区二区亚洲| 日韩欧美一区中文| 最新中文字幕在线播放| 在线免费观看一区二区三区| 成人丝袜18视频在线观看| 免费视频网站在线观看入口| 久久久国产精品视频| 一呦二呦三呦国产精品| 欧美视频国产视频| 精品久久久免费| 国产不卡在线| 欧美人与性禽动交精品| 国产精品综合在线视频| 人妻丰满熟妇av无码区| 久久夜色精品国产亚洲aⅴ| 特黄特色欧美大片| 国产无色aaa| 色狠狠一区二区| 蜜桃传媒在线观看免费进入| 亚洲国产精品视频一区| av亚洲精华国产精华| 国产日产亚洲系列最新|