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

前端不得不知道的,Vue.set 的副作用

開發 前端
我個人覺得Vue.set這種添加和修改不一致的表現是vue的一個缺陷。還沒看Vue 3.0代碼,看過的朋友可以告訴我下,是不是也有這樣的問題?

Vue雖然用挺久了,還是會踩到坑,來看下面這段很簡單的🌰:點擊a和b按鈕,下面代碼會提示什么?

  1. <html> 
  2. <head> 
  3.     <meta charset="utf-8"> 
  4.     <script src="https://cdn.staticfile.org/vue/2.5.17/vue.min.js"></script> 
  5. </head>  
  6. <body> 
  7. <div id="app"> 
  8.     <p>{{ JSON.stringify(this.testObj) }}</p> 
  9.     <button @click="set('a')">設置testObj屬性a</button> 
  10.     <button @click="set('b')">設置testObj屬性b</button> 
  11. </div> 
  12.  
  13. <script> 
  14.   new Vue({ 
  15.     el: '#app', 
  16.     data: { 
  17.       testObj: {}, 
  18.     }, 
  19.     watch: { 
  20.       'testObj.a'() { 
  21.         alert('a') 
  22.       }, 
  23.       'testObj.b'() { 
  24.         alert('b') 
  25.       }, 
  26.     }, 
  27.     methods: { 
  28.       set(val) { 
  29.         Vue.set(this.testObj, val, {}); 
  30.       } 
  31.     }, 
  32.   }) 
  33. </script> 
  34. </body> 
  35. </html> 
 

答案是:

點a的時候alert a,點b的時候alert a,接著alert b。

如果再接著點a,點b,提示什么?

答案是:

點a的時候alert a,點b的時候alert b。

我們把代碼做一個很小的改動:把Vue.set的值由對象改為true。這時候點擊a和b按鈕,下面代碼會提示什么?

  1. <html> 
  2. <head> 
  3.     <meta charset="utf-8"> 
  4.     <script src="https://cdn.staticfile.org/vue/2.5.17/vue.min.js"></script> 
  5. </head>  
  6. <body> 
  7. <div id="app"> 
  8.     <p>{{ JSON.stringify(this.testObj) }}</p> 
  9.     <button @click="set('a')">設置testObj屬性a</button> 
  10.     <button @click="set('b')">設置testObj屬性b</button> 
  11. </div> 
  12.  
  13. <script> 
  14.   new Vue({ 
  15.     el: '#app', 
  16.     data: { 
  17.       testObj: {}, 
  18.     }, 
  19.     watch: { 
  20.       'testObj.a'() { 
  21.         alert('a') 
  22.       }, 
  23.       'testObj.b'() { 
  24.         alert('b') 
  25.       }, 
  26.     }, 
  27.     methods: { 
  28.       set(val) { 
  29.         Vue.set(this.testObj, val, true); 
  30.       } 
  31.     }, 
  32.   }) 
  33. </script> 
  34. </body> 
  35. </html> 

答案是:

點a的時候alert a,點b的時候alert b。

如果再接著點a,點b,提示什么?

答案是:

沒有提示。

先總結一下發現的現象:用Vue.set為對象o添加屬性,如果添加的屬性是一個對象,那么o的所有屬性會被觸發響應。

是不是不明白?且請聽我講解一下。

要回答上面這些問題,我們首先需要理解一下Vue的響應式原理。

從Vue官網這幅圖上我們可以看出:當我們訪問data里某個數據屬性p時,會通過getter將這個屬性對應的Watcher加入該屬性的依賴列表;當我們修改屬性p的值時,通過setter通知p依賴的Watcher觸發相應的回調函數,從而讓虛擬節點重新渲染。

所以響不響應關鍵是看依賴列表有沒有這個屬性的watcher。

為了把依賴列表和實際的數據結構聯系起來,我畫出了vue響應式的主要數據結構,箭頭表示它們之間的包含關系:

Vue里的依賴就是一個Dep對象,它內部有一個subs數組,這個數組里每個元素都是一個Watcher,分別對應對象的每個屬性。Dep對象里的這個subs數組就是依賴列表。

從圖中我們可以看到這個Dep對象來自于__ob__對象的dep屬性,這個__ob__對象又是怎么來的呢?這就是我們new Vue對象時候Vue初始化做的工作了。Vue初始化最重要的工作就是讓對象的每個屬性成為響應式,具體則是通過observe函數對每個屬性調用下面的defineReactive來完成的:

  1. /** 
  2.  * Define a reactive property on an Object. 
  3.  */ 
  4. function defineReactive ( 
  5.   obj, 
  6.   key, 
  7.   val, 
  8.   customSetter, 
  9.   shallow 
  10. ) { 
  11.   var dep = new Dep(); 
  12.  
  13.   var property = Object.getOwnPropertyDescriptor(obj, key); 
  14.   if (property && property.configurable === false) { 
  15.     return 
  16.   } 
  17.  
  18.   // cater for pre-defined getter/setters 
  19.   var getter = property && property.get; 
  20.   if (!getter && arguments.length === 2) { 
  21.     val = obj[key]; 
  22.   } 
  23.   var setter = property && property.set; 
  24.  
  25.   var childOb = !shallow && observe(val); 
  26.   Object.defineProperty(obj, key, { 
  27.     enumerable: true, 
  28.     configurable: true, 
  29.     get: function reactiveGetter () { 
  30.       var value = getter ? getter.call(obj) : val; 
  31.       if (Dep.target) { 
  32.         dep.depend(); 
  33.         if (childOb) { 
  34.           childOb.dep.depend(); 
  35.           if (Array.isArray(value)) { 
  36.             dependArray(value); 
  37.           } 
  38.         } 
  39.       } 
  40.       return value 
  41.     }, 
  42.     set: function reactiveSetter (newVal) { 
  43.       var value = getter ? getter.call(obj) : val; 
  44.       /* eslint-disable no-self-compare */ 
  45.       if (newVal === value || (newVal !== newVal && value !== value)) { 
  46.         return 
  47.       } 
  48.       /* eslint-enable no-self-compare */ 
  49.       if (process.env.NODE_ENV !== 'production' && customSetter) { 
  50.         customSetter(); 
  51.       } 
  52.       if (setter) { 
  53.         setter.call(obj, newVal); 
  54.       } else { 
  55.         val = newVal
  56.       } 
  57.       childOb = !shallow && observe(newVal); 
  58.       dep.notify(); 
  59.     } 
  60.   }); 

讓一個對象成為響應式其實就是給對象的所有屬性加上getter和setter(defineReactive做的工作),然后在對象里加__ob__屬性(observe做的工作),因為__ob__里包含了對象的依賴列表,所以這個對象就可以響應數據變化。

可以看到defineReactive里也調用了observe,所以讓一個對象成為響應式這個動作是遞歸的。即如果這個對象的屬性又是一個對象,那么屬性對象也會成為響應式。就是說這個屬性對象也會加__ob__然后所有屬性加上getter和setter。

剛才說有沒有響應看“依賴列表有沒有這個屬性的watcher”,但是實際上,ob 只存在屬性所在的對象上,所以依賴列表是在對象上的依賴列表,通過依賴列表里Watcher的expression關聯到對應屬性(見圖2)。說以準確的說:有沒有響應應該是看“對象的依賴列表里有沒有屬性的watcher”。

注意我們在data里只定義了testObj空對象,testObj并沒有任何屬性,所以testObj的依賴列表一開始是空的。

但是因為代碼有定義Vue對象的watch,初始化代碼會對每個watch屬性新建watcher,并添加到testObj的依賴隊列__ob__.dep.subs里。這里的添加方法非常巧妙:新建watcher時候會一層層訪問watch的屬性。比如watch 'testObj.a',vue會先訪問testObj,再訪問testObj.a。因為testObj已經初始化成響應式的,訪問testObj時會調用defineReactive里定義的getter,getter又會調用dep.depend()從而把testObj.a對應的watcher加到依賴隊列__ob__.dep.subs里。于是新建watcher的同時完成了把watcher自動添加到對應對象的依賴列表這個動作。

小結一下:Vue對象初始化時會給data里對象的所有屬性加上getter和setter,添加__ob__屬性,并把watch屬性對應的watcher放到__ob__.dep.subs依賴列表里。

所以經過初始化,testObj的依賴列表里已經有了屬性a和b對應的watcher。

有了以上基礎知識我們再來看Vue.set也就是下面的set函數做了些什么。

  1. /** 
  2.  * Set a property on an object. Adds the new property and 
  3.  * triggers change notification if the property doesn't 
  4.  * already exist. 
  5.  */ 
  6. function set (target, key, val) { 
  7.   if (process.env.NODE_ENV !== 'production' && 
  8.     (isUndef(target) || isPrimitive(target)) 
  9.   ) { 
  10.     warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target)))); 
  11.   } 
  12.   if (Array.isArray(target) && isValidArrayIndex(key)) { 
  13.     target.length = Math.max(target.length, key); 
  14.     target.splice(key, 1, val); 
  15.     return val 
  16.   } 
  17.   if (key in target && !(key in Object.prototype)) { 
  18.     target[key] = val; 
  19.     return val 
  20.   } 
  21.   var ob = (target).__ob__; 
  22.   if (target._isVue || (ob && ob.vmCount)) { 
  23.     process.env.NODE_ENV !== 'production' && warn( 
  24.       'Avoid adding reactive properties to a Vue instance or its root $data ' + 
  25.       'at runtime - declare it upfront in the data option.' 
  26.     ); 
  27.     return val 
  28.   } 
  29.   if (!ob) { 
  30.     target[key] = val; 
  31.     return val 
  32.   } 
  33.   defineReactive(ob.value, key, val); 
  34.   ob.dep.notify(); 
  35.   return val 

我們關心的主要就最后這兩句:defineReactive(ob.value, key, val); 和ob.dep.notify();。

defineReactive的作用就是讓一個對象屬性成為響應式。ob.dep.notify()則是通知對象依賴列表里面所有的watcher:數據變化了,看看你是不是要做點啥?具體做什么就是圖2 Watcher里面的cb。當我們在vue 里面寫了 watch: { p: function(oldValue, newValue) {} } 時候我們就是為p的watcher添加了cb。

所以Vue.set實際上就做了這兩件事:

  • 把屬性變成響應式 。
  • 通知對象依賴列表里所有watcher數據發生變化。

那么問題來了,既然依賴列表一直包含a和b的watcher,那應該每次Vue.set時候,a和b的cb都應該被調用,為什么結果不是這樣呢?奧妙就藏在下面的watcher的run函數里。

  1. /** 
  2.  * Scheduler job interface. 
  3.  * Will be called by the scheduler. 
  4.  */ 
  5. Watcher.prototype.run = function run () { 
  6.   if (this.active) { 
  7.     var value = this.get(); 
  8.     if ( 
  9.       value !== this.value || 
  10.       // Deep watchers and watchers on Object/Arrays should fire even 
  11.       // when the value is the same, because the value may 
  12.       // have mutated. 
  13.       isObject(value) || 
  14.       this.deep 
  15.     ) { 
  16.       // set new value 
  17.       var oldValue = this.value; 
  18.       this.value = value; 
  19.       if (this.user) { 
  20.         try { 
  21.           this.cb.call(this.vm, value, oldValue); 
  22.         } catch (e) { 
  23.           handleError(e, this.vm, ("callback for watcher \"" + (this.expression) + "\"")); 
  24.         } 
  25.       } else { 
  26.         this.cb.call(this.vm, value, oldValue); 
  27.       } 
  28.     } 
  29.   } 
  30. }; 

dep.notify通知watcher后,watcher會執行run函數,這個函數才是真正調用cb的地方。我們可以看到有這樣一個判斷 if (value !==this.value || isObject(value) || this.deep) 就是說值不相等或者值是對象或者是深度watch的時候,都會觸發cb回調。所以當我們用Vue.set給對象添加新的對象屬性的時候,依賴列表里的每個watcher都會通過這個判斷(新添加屬性因為{} !== {} 所以value !==this.value成立,已有屬性因為isObject(value)),都會觸發cb回調。而當我們Vue.set給對象添加新的非對象屬性的時候,只有新添加的屬性通過value !==this.value 判斷會觸發cb,其他屬性因為值沒變所以不會觸發cb回調。這就解釋了為什么第一次點擊按鈕b的時候場景一和場景二的效果不一樣了。

那既然依賴列表沒變為什么第二次點擊按鈕效果就不一樣了呢?

這就是set函數里面這個判斷起的作用了:

  1. if (key in target && !(key in Object.prototype)) { 
  2.   target[key] = val; 
  3.   return val 

這個判斷會判斷對象屬性是否已經存在,如果存在的話只是做一個賦值操作。不會走到下面的defineReactive(ob.value, key, val); 和ob.dep.notify();里,這樣watcher沒收到notify,就不會觸發cb回調了。那第二次點擊按鈕的回調是哪里觸發的呢?還記得剛才的defineReactive里定義的setter嗎?因為testObj已經成為了響應式,所以進行屬性賦值操作會觸發這個屬性的setter,在set函數最后有個dep.notify();就是它通知了watcher從而觸發cb回調。

就算是這樣第二次點擊不是應該a和b都觸發的嗎?依賴列表不是一直包含有a和b的watcher嗎?

這里就要涉及到另一個概念“依賴收集”,不同于__ob__.dep.subs這個依賴列表,響應式對象還有一個依賴列表,就是defineReactive里面定義的var dep,每個屬性都有一個dep,以閉包形式出現,我暫且稱它為內部依賴列表。在前面的set函數判斷里,判斷通過會執行target[key]= val; 這句賦值語句會首先觸發getter,把屬性key對應的watcher添加到內部依賴列表,這個步驟就是Vue官網那張圖里的“collect as dependencies”;然后觸發setter,調用dep.notify()通知watcher執行watcher.run。因為這時候內部依賴列表只有一個watcher也就是屬性對應的watcher。所以只觸發了屬性本身的回調。

根據以上分析我們還原一下兩個場景:

場景1:Vue.set 一個對象屬性

  • 點擊按鈕a: Vue.set把屬性a變成響應式,通知依賴列表數據變化,依賴列表中watcher-a發現數據變化,執行a的回調。
  • 點擊按鈕b: Vue.set把屬性b變成響應式,通知依賴列表數據變化,依賴列表中watcher-a發現a是對象,watcher-b發現數據變化,均滿足觸發cb條件,于是執行a和b的回調。
  • 再點擊按鈕a: Vue.set給a屬性賦值,觸發getter收集依賴,內部依賴列表收集到依賴watcher-a,觸發setter通知內部依賴列表數據變化,watcher-a發現數據變化,執行a的回調。
  • 再點擊按鈕b: Vue.set給b屬性賦值,觸發getter收集依賴,內部依賴列表收集到依賴watcher-b,觸發setter通知內部依賴列表數據變化,watcher-b發現數據變化,執行b的回調。

場景2:Vue.set 一個非對象屬性

  • 點擊按鈕a: Vue.set把屬性a變成響應式,通知依賴列表數據變化,依賴列表中watcher-a發現數據變化,執行a的回調。
  • 點擊按鈕b: Vue.set把屬性b變成響應式,通知依賴列表數據變化,watcher-b發現數據變化,執行b的回調。
  • 再點擊按鈕a: Vue.set給a屬性賦值,觸發getter收集依賴,內部依賴列表收集到依賴watcher-a,觸發setter,發現數據沒變化,返回。
  • 再點擊按鈕b: Vue.set給b屬性賦值,觸發getter收集依賴,內部依賴列表收集到依賴watcher-b,觸發setter,發現數據沒變化,返回。

原因總結:

  • Vue響應式對象有內部、外部兩個依賴列表。
  • Vue.set有添加屬性、修改屬性兩種功能。
  • Watcher在判斷是否需要觸發回調時有對象屬性、非對象屬性的區別。

結論:

  • 用Vue.set添加對象屬性,對象的所有屬性都會觸發一次響應。
  • 用Vue.set修改對象屬性,只有當前修改的屬性會觸發一次響應。

我個人覺得Vue.set這種添加和修改不一致的表現是vue的一個缺陷。還沒看Vue 3.0代碼,看過的朋友可以告訴我下,是不是也有這樣的問題?

規避方法:

添加一個對象屬性會讓所有屬性觸發響應這個特性應該不是我們想要的效果。目前沒想到好的解決方法,只能在data里定義對象時先把對象的屬性全寫上。避免使用Vue.set設置對象屬性。

 

責任編輯:趙寧寧 來源: 前端下午茶
相關推薦

2020-10-21 09:36:40

Vue項目技巧

2020-08-11 06:53:33

Vue前端代碼

2020-05-18 09:33:27

前端開發工具

2022-08-08 11:13:35

API接口前端

2022-08-30 23:54:42

MySQL數據庫工具

2022-10-27 09:55:00

2017-08-10 16:54:47

MySQL優化MySQL

2019-07-17 10:55:40

Kubernetes工具Katacoda

2020-02-13 18:05:18

數組reduce前端

2023-08-29 08:41:42

2015-09-22 10:03:25

大數據秘訣

2015-09-23 10:27:04

大數據秘訣

2017-11-02 06:51:38

5G移動網絡技術

2017-09-22 09:10:41

2024-12-23 07:00:00

C++并發編程

2011-03-31 10:46:54

LinuxCLI軟件

2017-08-16 18:03:12

Docker安全工具容器

2020-06-04 13:52:00

CRM選型

2024-06-05 11:36:28

2009-05-31 09:02:23

點贊
收藏

51CTO技術棧公眾號

99久久99久久精品| 亚洲一区二区欧美激情| 国产性猛交xxxx免费看久久| wwwwww欧美| 天天av天天翘| 蜜桃一区二区三区在线| 日韩精品免费一线在线观看| 亚洲国产精品福利| www.日本少妇| 高清中文字幕一区二区三区| 激情欧美一区二区| 欧美成人四级hd版| 日本人添下边视频免费| 欧美日韩国产v| 一区二区三区四区在线免费观看| 免费在线观看一区二区| 亚洲无码精品在线播放| 亚洲看片一区| 久久久电影免费观看完整版| 精品人妻一区二区三区视频| 国产专区精品| 91福利社在线观看| 婷婷视频在线播放| 国产在线资源| 97精品视频在线观看自产线路二| 成人精品在线观看| 欧美一区二区三区网站| 欧美日韩1区2区3区| 中文字幕亚洲一区| 欧美狂猛xxxxx乱大交3| 99久久人爽人人添人人澡| 在线视频中文字幕一区二区| 97超碰国产精品| 大片免费在线看视频| 成人91在线观看| 91精品国产一区二区三区动漫| 欧美三级午夜理伦| 亚洲第一毛片| 欧美精品激情视频| 日本老熟俱乐部h0930| 欧美精品一区二区三区中文字幕 | 亚洲欧美在线看| 无码人妻一区二区三区免费n鬼沢| 国产成人精品一区二区三区在线 | 欧美激情一区二区三区蜜桃视频| 精品久久中出| 性插视频在线观看| www.成人网.com| 国产精品三区在线| 亚洲黄色一级大片| 成人三级伦理片| 国产精品一区二区三区成人| 最近中文在线观看| 麻豆91在线看| 成人黄色免费网站在线观看| 一级特黄aaa大片在线观看| 久久精品九九| 国产精品欧美久久久| youjizz在线视频| 免费亚洲网站| 欧美一级片在线播放| 国产专区第一页| av不卡免费看| 人妖精品videosex性欧美| 久久久免费高清视频| 久久久国产精品一区二区中文| 97精品视频在线| 中文字幕免费在线观看视频| 丝袜美腿成人在线| 国产精品中文字幕在线观看| 91精品中文字幕| 三级久久三级久久| 成人激情综合网| 精品人妻无码一区二区| 北条麻妃国产九九精品视频| 久久久久久欧美精品色一二三四| 九色视频成人自拍| 中文字幕国产一区| 国产对白在线播放| 好了av在线| 午夜日韩在线电影| 人妻无码视频一区二区三区| 久久xxx视频| 欧美精品在线观看一区二区| 亚洲美女精品视频| 亚洲亚洲免费| 久久精品一本久久99精品| 妺妺窝人体色www聚色窝仙踪| 久久久国产精品| 久久色在线播放| 亚洲免费在线观看av| 美腿丝袜亚洲三区| 国产精品国产精品| 成人免费一区二区三区视频网站| 亚洲欧洲一区二区三区| 男人添女荫道口喷水视频| 高清不卡av| 777奇米四色成人影色区| 黑森林av导航| 久久国产亚洲精品| 久久久久久久久久久久久久久久久久av | 国产区精品在线| 99国产精品国产精品毛片| 明星裸体视频一区二区| 中文字幕伦理免费在线视频| 亚洲午夜免费福利视频| 男操女免费网站| 精品按摩偷拍| 日韩三级成人av网| 毛片视频网站在线观看| 国产精品88av| 日韩欧美在线观看强乱免费| www久久日com| 欧美日韩一区中文字幕| 青青草视频网站| 色999日韩| 日本电影亚洲天堂| 亚洲毛片在线播放| 国产精品美女一区二区在线观看| 中文字幕成人一区| 78精品国产综合久久香蕉| 精品福利一区二区三区免费视频| 99成人在线观看| 日本中文在线一区| 国内精品二区| 色在线视频网| 日韩欧美中文字幕精品| 性色av蜜臀av色欲av| 亚洲天堂成人| 超碰在线97av| av文字幕在线观看| 欧美乱妇20p| 中国美女黄色一级片| 日韩经典一区二区| 欧美一区二区三区精美影视| 成人免费观看在线观看| 欧美精品在线一区二区三区| 国产传媒在线看| 99国产精品视频免费观看一公开 | 国产日韩欧美中文在线| 最新亚洲国产精品| 免费看av在线| 中文字幕不卡在线观看| 手机在线看福利| 日韩综合一区| 国产精品久久久久秋霞鲁丝| 国产在线你懂得| 欧美性猛交xxxx富婆| 性欧美丰满熟妇xxxx性仙踪林| 亚洲午夜久久久久久尤物| 高清不卡日本v二区在线| 男女视频在线| 日韩欧美国产综合| 波多野结衣家庭教师在线观看| 鲁大师成人一区二区三区| 农村寡妇一区二区三区| 日本综合字幕| 亚洲人成电影网站色| 欧美亚洲另类小说| 国产精品污污网站在线观看| 黄色在线视频网| 欧美gvvideo网站| 成人免费自拍视频| 午夜羞羞小视频在线观看| 精品国产乱码久久| 69成人免费视频| 欧美经典三级视频一区二区三区| 美女网站视频黄色| 91精品动漫在线观看| av一本久道久久波多野结衣| 国产精品yjizz视频网| 亚洲欧美中文字幕| 国产又爽又黄又嫩又猛又粗| 亚洲品质自拍视频网站| 亚洲av成人片无码| 日韩精品久久久久久| 久久精品国产精品亚洲精品色| 试看120秒一区二区三区| 91精品国产91久久久久福利| 番号集在线观看| 欧美精选午夜久久久乱码6080| 青青青在线视频| 久久嫩草精品久久久久| 在线免费看v片| 最新日韩欧美| 久久精品综合一区| 成人国产一区二区三区精品麻豆| 亚洲欧美日韩视频一区| 91麻豆一区二区| 精品久久久久久久久久国产 | www.夜夜爽| 日本欧美视频| 91精品天堂| 成人性生活av| 欧美放荡办公室videos4k| 日韩电影网址| 日韩精品一区二区三区在线播放| 国产又大又黄视频| 亚洲人成在线观看一区二区| 日韩一级视频在线观看| 精品一区二区三区在线播放| 黄色一级视频片| 成人在线亚洲| 精品无人区一区二区三区| 成人自拍视频| 国产精品久久久久99| 99热99re6国产在线播放| 色老头一区二区三区| 日本高清视频在线| 欧美在线免费观看视频| 久久综合久久鬼| 成人免费在线视频| 亚洲码无人客一区二区三区| 国产91精品在线观看| www.久久av.com| 在线日韩视频| 日韩中文在线字幕| 久久久影院免费| 欧美一区二区综合| 日韩三级视频| 国产嫩草一区二区三区在线观看| 91精品国产色综合久久不卡粉嫩| 久久久久久网站| 色呦呦在线观看视频| 中文字幕无线精品亚洲乱码一区 | 亚洲男人天堂一区| 亚洲色图 激情小说| 久久久精品国产99久久精品芒果 | 91精品成人久久| 爱情岛亚洲播放路线| 久久这里有精品| 免费黄色网址在线观看| 亚洲网址你懂得| 日本黄色一区二区三区| 精品国产91洋老外米糕| 日韩一级片免费在线观看| 精品久久久久久亚洲综合网| 国产白浆在线观看| 欧美一区中文字幕| 精品人妻伦一二三区久久| 欧美一级高清片| 精品国产免费无码久久久| 欧美日韩大陆在线| 91麻豆国产视频| 91精品国产91热久久久做人人 | wwwjizzjizzcom| 91不卡在线观看| 成人在线观看毛片| 亚洲天堂成人| 欧美成人精品免费| 日韩一级精品| 久无码久无码av无码| 午夜欧美理论片| 拔插拔插海外华人免费| 亚洲作爱视频| 久久久噜噜噜www成人网| 久久精品卡一| 小明看看成人免费视频| 精品中文av资源站在线观看| 国产aⅴ爽av久久久久| 日韩av高清在线观看| 色免费在线视频| 国产真实精品久久二三区| 绯色av蜜臀vs少妇| jvid福利写真一区二区三区| 成人啪啪18免费游戏链接| 91影院在线免费观看| 久久久久久九九九九九| 国产精品传媒入口麻豆| 国产大片免费看| 亚洲国产欧美在线| 久久青青草原亚洲av无码麻豆| 欧美亚洲愉拍一区二区| 亚洲天堂中文在线| 日韩精品中午字幕| 欧美天堂在线视频| 亚洲日韩欧美视频一区| 毛片在线看片| 国内精品视频久久| xxxxx性欧美特大| 国产精品稀缺呦系列在线| 99热播精品免费| 成人精品水蜜桃| 深爱激情综合网| 粉嫩av一区二区三区天美传媒 | 国内精品久久久久久| 瑟瑟视频在线看| 成人免费看吃奶视频网站| 精品嫩草影院| 亚洲不卡中文字幕| 欧美先锋影音| 天天干天天干天天干天天干天天干| 国产精品影视天天线| 亚洲第一香蕉网| 成人欧美一区二区三区1314| 国产毛片aaa| 日韩情涩欧美日韩视频| 青青草在线视频免费观看| 另类视频在线观看| 制服诱惑亚洲| 国产视频一区二区不卡| 99tv成人| 久久网站免费视频| 国产精品一二三| 免费在线观看污| 午夜欧美2019年伦理| 亚洲在线免费观看视频| 亚洲激情视频在线播放| av网站大全在线| 欧美一区第一页| 久久精品一级| 亚洲精品国产一区| 久久免费黄色| 亚洲天堂美女视频| 国产人成亚洲第一网站在线播放| 伊人国产在线观看| 欧美日韩国产综合久久| 欧美日韩免费做爰大片| 高清亚洲成在人网站天堂| 亚洲二区av| 久久av二区| 亚洲毛片一区| 亚洲 自拍 另类 欧美 丝袜| 欧美国产精品一区| 六月丁香在线视频| 日韩美女天天操| 黄页网站在线观看免费| 亚洲自拍小视频| 99久久www免费| 911福利视频| 国产精品久久久久久久久免费桃花 | 亚洲开发第一视频在线播放| 久久激情中文| 色婷婷在线影院| 在线亚洲一区观看| 国产资源在线看| 久久人91精品久久久久久不卡 | 欧美大黄免费观看| 最新国产在线拍揄自揄视频| 91精品视频在线| 亚洲乱码电影| 国产999免费视频| 国产精品人成在线观看免费| 久久久久久无码精品大片| 亚洲欧洲在线播放| 欧美暴力调教| 亚洲不卡中文字幕| 精品夜夜嗨av一区二区三区| 黄色激情小视频| 欧美一区二区黄| 成人免费网址| 国产激情美女久久久久久吹潮| 韩国av一区| 一级国产黄色片| 亚洲综合一区在线| 国产哺乳奶水91在线播放| 欧美精品日韩三级| 精品国产18久久久久久洗澡| 日本福利视频在线| 日本一区二区三区国色天香| 国产又黄又猛又粗又爽| 国产一区二区三区高清在线观看| 日韩欧美2区| 在线观看av的网址| 国产成人综合在线播放| 日韩精品成人在线| 亚洲午夜性刺激影院| 日韩成人一区| 一区二区三区四区免费观看| 丝袜亚洲另类欧美综合| 久久人妻无码aⅴ毛片a片app| 欧美人狂配大交3d怪物一区| 日韩特级毛片| 国产91视觉| 老司机精品福利视频| 日本免费网站视频| 欧美精品少妇一区二区三区| 日韩欧美一起| 日产精品高清视频免费| 国产在线一区二区| 日韩精品视频播放| 亚洲人成网站色ww在线| 欧美成人毛片| 免费看黄在线看| 国产精品私人影院| 亚洲国产剧情在线观看| 日本精品久久久久影院| 羞羞色午夜精品一区二区三区| 亚洲精品乱码久久久久久久| 欧美日韩不卡视频| 伊人222成人综合网| 国产伦精品一区二区三毛| 日韩国产在线观看一区| 久久成人国产精品入口| 亚洲电影天堂av| 欧美三区四区| 日韩一级片免费视频| 中文字幕色av一区二区三区| 懂色av一区二区三区四区| 国产免费一区二区三区在线能观看|