gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

vue頁面渲染是同步還是異步

vue頁面渲染是異步的。vue采用的是異步渲染,這樣可以提升性能;如果不采用異步更新,在每次更新數據都會對當前組件進行重新渲染,為了性能考慮,Vue會在本輪數據更新后,再去異步更新視圖。

vue頁面渲染是同步還是異步

前端(vue)入門到精通課程,老師在線輔導:聯系老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

本教程操作環境:windows7系統、vue3版,DELL G3電腦。

vue頁面渲染是異步的。

Vue在更新DOM時是異步執行的,只要偵聽到數據變化,Vue將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據變更,如果同一個watcher被多次觸發,只會被推入到隊列中一次,這種在緩沖時去除重復數據對于避免不必要的計算和DOM操作是非常重要的,然后,在下一個的事件循環tick中,Vue刷新隊列并執行實際(已去重的)工作,Vue在內部對異步隊列嘗試使用原生的Promise.thenMutationObserversetImmediate,如果執行環境不支持,則會采用setTimeout(fn, 0)代替。(學習視頻分享:vuejs入門教程、編程基礎視頻)

描述

對于Vue為何采用異步渲染,簡單來說就是為了提升性能,因為不采用異步更新,在每次更新數據都會對當前組件進行重新渲染,為了性能考慮,Vue會在本輪數據更新后,再去異步更新視圖,舉個例子,讓我們在一個方法內重復更新一個值。

this.msg = 1; this.msg = 2; this.msg = 3;
登錄后復制

事實上,我們真正想要的其實只是最后一次更新而已,也就是說前三次DOM更新都是可以省略的,我們只需要等所有狀態都修改好了之后再進行渲染就可以減少一些性能損耗。

對于渲染方面的問題是很明確的,最終只渲染一次肯定比修改之后即渲染所耗費的性能少,在這里我們還需要考慮一下異步更新隊列的相關問題,假設我們現在是進行了相關處理使得每次更新數據只進行一次真實DOM渲染,來讓我們考慮異步更新隊列的性能優化。
假設這里是同步更新隊列,this.msg=1,大致會發生這些事: msg值更新 -> 觸發setter -> 觸發Watcherupdate -> 重新調用 render -> 生成新的vdom -> dom-diff -> dom更新,這里的dom更新并不是渲染(即布局、繪制、合成等一系列步驟),而是更新內存中的DOM樹結構,之后再運行this.msg=2,再重復上述步驟,之后的第3次更新同樣會觸發相同的流程,等開始渲染的時候,最新的DOM樹中確實只會存在更新完成3,從這里來看,前2次對msg的操作以及Vue內部對它的處理都是無用的操作,可以進行優化處理。

如果是異步更新隊列,會是下面的情況,運行this.msg=1,并不是立即進行上面的流程,而是將對msg有依賴的Watcher都保存在隊列中,該隊列可能這樣[Watcher1, Watcher2...],當運行this.msg=2后,同樣是將對msg有依賴的Watcher保存到隊列中,Vue內部會做去重判斷,這次操作后,可以認為隊列數據沒有發生變化,第3次更新也是上面的過程,當然,你不可能只對msg有操作,你可能對該組件中的另一個屬性也有操作,比如this.otherMsg=othermessage,同樣會把對otherMsg有依賴的Watcher添加到異步更新隊列中,因為有重復判斷操作,這個Watcher也只會在隊列中存在一次,本次異步任務執行結束后,會進入下一個任務執行流程,其實就是遍歷異步更新隊列中的每一個Watcher,觸發其update,然后進行重新調用render -> new vdom -> dom-diff -> dom更新等流程,但是這種方式和同步更新隊列相比,不管操作多少次msg Vue在內部只會進行一次重新調用真實更新流程,所以,對于異步更新隊列不是節省了渲染成本,而是節省了Vue內部計算及DOM樹操作的成本,不管采用哪種方式,渲染確實只有一次。

此外,組件內部實際使用VirtualDOM進行渲染,也就是說,組件內部其實是不關心哪個狀態發生了變化,它只需要計算一次就可以得知哪些節點需要更新,也就是說,如果更改了N個狀態,其實只需要發送一個信號就可以將DOM更新到最新,如果我們更新多個值。

this.msg = 1; this.age = 2; this.name = 3;
登錄后復制

此處我們分三次修改了三種狀態,但其實Vue只會渲染一次,因為VIrtualDOM只需要一次就可以將整個組件的DOM更新到最新,它根本不會關心這個更新的信號到底是從哪個具體的狀態發出來的。
而為了達到這個目的,我們需要將渲染操作推遲到所有的狀態都修改完成,為了做到這一點只需要將渲染操作推遲到本輪事件循環的最后或者下一輪事件循環,也就是說,只需要在本輪事件循環的最后,等前面更新狀態的語句都執行完之后,執行一次渲染操作,它就可以無視前面各種更新狀態的語法,無論前面寫了多少條更新狀態的語句,只在最后渲染一次就可以了。
將渲染推遲到本輪事件循環的最后執行渲染的時機會比推遲到下一輪快很多,所以Vue優先將渲染操作推遲到本輪事件循環的最后,如果執行環境不支持會降級到下一輪,Vue的變化偵測機制(setter)決定了它必然會在每次狀態發生變化時都會發出渲染的信號,但Vue會在收到信號之后檢查隊列中是否已經存在這個任務,保證隊列中不會有重復,如果隊列中不存在則將渲染操作添加到隊列中,之后通過異步的方式延遲執行隊列中的所有渲染的操作并清空隊列,當同一輪事件循環中反復修改狀態時,并不會反復向隊列中添加相同的渲染操作,所以我們在使用Vue時,修改狀態后更新DOM都是異步的。
當數據變化后會調用notify方法,將watcher遍歷,調用update方法通知watcher進行更新,這時候watcher并不會立即去執行,在update中會調用queueWatcher方法將watcher放到了一個隊列里,在queueWatcher會根據watcher的進行去重,若多個屬性依賴一個watcher,則如果隊列中沒有該watcher就會將該watcher添加到隊列中,然后便會在$nextTick方法的執行隊列中加入一個flushSchedulerQueue方法(這個方法將會觸發在緩沖隊列的所有回調的執行),然后將$nextTick方法的回調加入$nextTick方法中維護的執行隊列,flushSchedulerQueue中開始會觸發一個before的方法,其實就是beforeUpdate,然后watcher.run()才開始真正執行watcher,執行完頁面就渲染完成,更新完成后會調用updated鉤子。

$nextTick

在上文中談到了對于Vue為何采用異步渲染,假如此時我們有一個需求,需要在頁面渲染完成后取得頁面的DOM元素,而由于渲染是異步的,我們不能直接在定義的方法中同步取得這個值的,于是就有了vm.$nextTick方法,Vue$nextTick方法將回調延遲到下次DOM更新循環之后執行,也就是在下次DOM更新循環結束之后執行延遲回調,在修改數據之后立即使用這個方法,能夠獲取更新后的DOM。簡單來說就是當數據更新時,在DOM中渲染完成后,執行回調函數。
通過一個簡單的例子來演示$nextTick方法的作用,首先需要知道Vue在更新DOM時是異步執行的,也就是說在更新數據時其不會阻塞代碼的執行,直到執行棧中代碼執行結束之后,才開始執行異步任務隊列的代碼,所以在數據更新時,組件不會立即渲染,此時在獲取到DOM結構后取得的值依然是舊的值,而在$nextTick方法中設定的回調函數會在組件渲染完成之后執行,取得DOM結構后取得的值便是新的值。

<!DOCTYPE html> <html> <head>     <title>Vue</title> </head> <body>     <div id="app"></div> </body> <script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script> <script type="text/javascript">     var vm = new Vue({         el: '#app',         data: {             msg: 'Vue'         },         template:`             <div>                 <div ref="msgElement">{{msg}}</div>                 <button @click="updateMsg">updateMsg</button>             </div>         `,         methods:{             updateMsg: function(){                 this.msg = "Update";                 console.log("DOM未更新:", this.$refs.msgElement.innerHTML)                 this.$nextTick(() => {                     console.log("DOM已更新:", this.$refs.msgElement.innerHTML)                 })             }         },              }) </script> </html>
登錄后復制

異步機制

官方文檔中說明,Vue在更新DOM時是異步執行的,只要偵聽到數據變化,Vue將開啟一個隊列,并緩沖在同一事件循環中發生的所有數據變更,如果同一個watcher被多次觸發,只會被推入到隊列中一次。這種在緩沖時去除重復數據對于避免不必要的計算和DOM操作是非常重要的。然后,在下一個的事件循環tick中,Vue刷新隊列并執行實際工作。Vue在內部對異步隊列嘗試使用原生的Promise.thenMutationObserversetImmediate,如果執行環境不支持,則會采用 setTimeout(fn, 0)代替。
Js是單線程的,其引入了同步阻塞與異步非阻塞的執行模式,在Js異步模式中維護了一個Event LoopEvent Loop是一個執行模型,在不同的地方有不同的實現,瀏覽器和NodeJS基于不同的技術實現了各自的Event Loop。瀏覽器的Event Loop是在HTML5的規范中明確定義,NodeJSEvent Loop是基于libuv實現的。
在瀏覽器中的Event Loop由執行棧Execution Stack、后臺線程Background Threads、宏隊列Macrotask Queue、微隊列Microtask Queue組成。

  • 執行棧就是在主線程執行同步任務的數據結構,函數調用形成了一個由若干幀組成的棧。
  • 后臺線程就是瀏覽器實現對于setTimeoutsetIntervalXMLHttpRequest等等的執行線程。
  • 宏隊列,一些異步任務的回調會依次進入宏隊列,等待后續被調用,包括setTimeoutsetIntervalsetImmediate(Node)requestAnimationFrameUI renderingI/O等操作。
  • 微隊列,另一些異步任務的回調會依次進入微隊列,等待后續調用,包括Promiseprocess.nextTick(Node)Object.observeMutationObserver等操作。

Js執行時,進行如下流程:

  • 首先將執行棧中代碼同步執行,將這些代碼中異步任務加入后臺線程中。

  • 執行棧中的同步代碼執行完畢后,執行棧清空,并開始掃描微隊列。

  • 取出微隊列隊首任務,放入執行棧中執行,此時微隊列是進行了出隊操作。

  • 當執行棧執行完成后,繼續出隊微隊列任務并執行,直到微隊列任務全部執行完畢。

  • 最后一個微隊列任務出隊并進入執行棧后微隊列中任務為空,當執行棧任務完成后,開始掃面微隊列為空,繼續掃描宏隊列任務,宏隊列出隊,放入執行棧中執行,執行完畢后繼續掃描微隊列為空則掃描宏隊列,出隊執行。

  • 不斷往復...

實例

// Step 1 console.log(1);  // Step 2 setTimeout(() => {   console.log(2);   Promise.resolve().then(() => {     console.log(3);   }); }, 0);  // Step 3 new Promise((resolve, reject) => {   console.log(4);   resolve(); }).then(() => {   console.log(5); })  // Step 4 setTimeout(() => {   console.log(6); }, 0);  // Step 5 console.log(7);  // Step N // ...  // Result /*   1   4   7   5   2   3   6 */
登錄后復制

Step 1

// 執行棧 console // 微隊列 [] // 宏隊列 [] console.log(1); // 1
登錄后復制

Step 2

// 執行棧 setTimeout // 微隊列 [] // 宏隊列 [setTimeout1] setTimeout(() => {   console.log(2);   Promise.resolve().then(() => {     console.log(3);   }); }, 0);
登錄后復制

Step 3

// 執行棧 Promise // 微隊列 [then1] // 宏隊列 [setTimeout1] new Promise((resolve, reject) => {   console.log(4); // 4 // Promise是個函數對象,此處是同步執行的 // 執行棧 Promise console   resolve(); }).then(() => {   console.log(5); })
登錄后復制

Step 4

// 執行棧 setTimeout // 微隊列 [then1] // 宏隊列 [setTimeout1 setTimeout2] setTimeout(() => {   console.log(6); }, 0);
登錄后復制

Step 5

// 執行棧 console // 微隊列 [then1] // 宏隊列 [setTimeout1 setTimeout2] console.log(7); // 7
登錄后復制

Step 6

// 執行棧 then1 // 微隊列 [] // 宏隊列 [setTimeout1 setTimeout2] console.log(5); // 5
登錄后復制

Step 7

// 執行棧 setTimeout1 // 微隊列 [then2] // 宏隊列 [setTimeout2] console.log(2); // 2 Promise.resolve().then(() => {     console.log(3); });
登錄后復制

Step 8

// 執行棧 then2 // 微隊列 [] // 宏隊列 [setTimeout2] console.log(3); // 3
登錄后復制

Step 9

// 執行棧 setTimeout2 // 微隊列 [] // 宏隊列 [] console.log(6); // 6
登錄后復制

分析

在了解異步任務的執行隊列后,回到中$nextTick方法,當用戶數據更新時,Vue將會維護一個緩沖隊列,對于所有的更新數據將要進行的組件渲染與DOM操作進行一定的策略處理后加入緩沖隊列,然后便會在$nextTick方法的執行隊列中加入一個flushSchedulerQueue方法(這個方法將會觸發在緩沖隊列的所有回調的執行),然后將$nextTick方法的回調加入$nextTick方法中維護的執行隊列,在異步掛載的執行隊列觸發時就會首先會首先執行flushSchedulerQueue方法來處理DOM渲染的任務,然后再去執行$nextTick方法構建的任務,這樣就可以實現在$nextTick方法中取得已渲染完成的DOM結構。在測試的過程中發現了一個很有意思的現象,在上述例子中的加入兩個按鈕,在點擊updateMsg按鈕的結果是3 2 1,點擊updateMsgTest按鈕的運行結果是2 3 1

<!DOCTYPE html> <html> <head>     <title>Vue</title> </head> <body>     <div id="app"></div> </body> <script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script> <script type="text/javascript">     var vm = new Vue({         el: '#app',         data: {             msg: 'Vue'         },         template:`             <div>                 <div ref="msgElement">{{msg}}</div>                 <button @click="updateMsg">updateMsg</button>                 <button @click="updateMsgTest">updateMsgTest</button>             </div>         `,         methods:{             updateMsg: function(){                 this.msg = "Update";                 setTimeout(() => console.log(1))                 Promise.resolve().then(() => console.log(2))                 this.$nextTick(() => {                     console.log(3)                 })             },             updateMsgTest: function(){                 setTimeout(() => console.log(1))                 Promise.resolve().then(() => console.log(2))                 this.$nextTick(() => {                     console.log(3)                 })             }         },              }) </script> </html>
登錄后復制

這里假設運行環境中Promise對象是完全支持的,那么使用setTimeout是宏隊列在最后執行這個是沒有異議的,但是使用$nextTick方法以及自行定義的Promise實例是有執行順序的問題的,雖然都是微隊列任務,但是在Vue中具體實現的原因導致了執行順序可能會有所不同,首先直接看一下$nextTick方法的源碼,關鍵地方添加了注釋,請注意這是Vue2.4.2版本的源碼,在后期$nextTick方法可能有所變更。

/**  * Defer a task to execute it asynchronously.  */ var nextTick = (function () {   // 閉包 內部變量   var callbacks = []; // 執行隊列   var pending = false; // 標識,用以判斷在某個事件循環中是否為第一次加入,第一次加入的時候才觸發異步執行的隊列掛載   var timerFunc; // 以何種方法執行掛載異步執行隊列,這里假設Promise是完全支持的    function nextTickHandler () { // 異步掛載的執行任務,觸發時就已經正式準備開始執行異步任務了     pending = false; // 標識置false     var copies = callbacks.slice(0); // 創建副本     callbacks.length = 0; // 執行隊列置空     for (var i = 0; i < copies.length; i++) {       copies[i](); // 執行     }   }    // the nextTick behavior leverages the microtask queue, which can be accessed   // via either native Promise.then or MutationObserver.   // MutationObserver has wider support, however it is seriously bugged in   // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It   // completely stops working after triggering a few times... so, if native   // Promise is available, we will use it:   /* istanbul ignore if */   if (typeof Promise !== 'undefined' && isNative(Promise)) {     var p = Promise.resolve();     var logError = function (err) { console.error(err); };     timerFunc = function () {       p.then(nextTickHandler).catch(logError); // 掛載異步任務隊列       // in problematic UIWebViews, Promise.then doesn't completely break, but       // it can get stuck in a weird state where callbacks are pushed into the       // microtask queue but the queue isn't being flushed, until the browser       // needs to do some other work, e.g. handle a timer. Therefore we can       // "force" the microtask queue to be flushed by adding an empty timer.       if (isIOS) { setTimeout(noop); }     };   } else if (typeof MutationObserver !== 'undefined' && (     isNative(MutationObserver) ||     // PhantomJS and iOS 7.x     MutationObserver.toString() === '[object MutationObserverConstructor]'   )) {     // use MutationObserver where native Promise is not available,     // e.g. PhantomJS IE11, iOS7, Android 4.4     var counter = 1;     var observer = new MutationObserver(nextTickHandler);     var textNode = document.createTextNode(String(counter));     observer.observe(textNode, {       characterData: true     });     timerFunc = function () {       counter = (counter + 1) % 2;       textNode.data = String(counter);     };   } else {     // fallback to setTimeout     /* istanbul ignore next */     timerFunc = function () {       setTimeout(nextTickHandler, 0);     };   }    return function queueNextTick (cb, ctx) { // nextTick方法真正導出的方法     var _resolve;     callbacks.push(function () { // 添加到執行隊列中 并加入異常處理       if (cb) {         try {           cb.call(ctx);         } catch (e) {           handleError(e, ctx, 'nextTick');         }       } else if (_resolve) {         _resolve(ctx);       }     });     //判斷在當前事件循環中是否為第一次加入,若是第一次加入則置標識為true并執行timerFunc函數用以掛載執行隊列到Promise     // 這個標識在執行隊列中的任務將要執行時便置為false并創建執行隊列的副本去運行執行隊列中的任務,參見nextTickHandler函數的實現     // 在當前事件循環中置標識true并掛載,然后再次調用nextTick方法時只是將任務加入到執行隊列中,直到掛載的異步任務觸發,便置標識為false然后執行任務,再次調用nextTick方法時就是同樣的執行方式然后不斷如此往復     if (!pending) {        pending = true;       timerFunc();     }     if (!cb && typeof Promise !== 'undefined') {       return new Promise(function (resolve, reject) {         _resolve = resolve;       })     }   } })();
登錄后復制

回到剛才提出的問題上,在更新DOM操作時會先觸發$nextTick方法的回調,解決這個問題的關鍵在于誰先將異步任務掛載到Promise對象上。

首先對有數據更新的updateMsg按鈕觸發的方法進行debug,斷點設置在Vue.js715行,版本為2.4.2,在查看調用棧以及傳入的參數時可以觀察到第一次執行$nextTick方法的其實是由于數據更新而調用的nextTick(flushSchedulerQueue);語句,也就是說在執行this.msg = "Update";的時候就已經觸發了第一次的$nextTick方法,此時在$nextTick方法中的任務隊列會首先將flushSchedulerQueue方法加入隊列并掛載$nextTick方法的執行隊列到Promise對象上,然后才是自行自定義的Promise.resolve().then(() => console.log(2))語句的掛載,當執行微任務隊列中的任務時,首先會執行第一個掛載到Promise的任務,此時這個任務是運行執行隊列,這個隊列中有兩個方法,首先會運行flushSchedulerQueue方法去觸發組件的DOM渲染操作,然后再執行console.log(3),然后執行第二個微隊列的任務也就是() => console.log(2),此時微任務隊列清空,然后再去宏任務隊列執行console.log(1)

接下來對于沒有數據更新的updateMsgTest按鈕觸發的方法進行debug,斷點設置在同樣的位置,此時沒有數據更新,那么第一次觸發$nextTick方法的是自行定義的回調函數,那么此時$nextTick方法的執行隊列才會被掛載到Promise對象上,很顯然在此之前自行定義的輸出2Promise回調已經被掛載,那么對于這個按鈕綁定的方法的執行流程便是首先執行console.log(2),然后執行$nextTick方法閉包的執行隊列,此時執行隊列中只有一個回調函數console.log(3),此時微任務隊列清空,然后再去宏任務隊列執行console.log(1)

簡單來說就是誰先掛載Promise對象的問題,在調用$nextTick方法時就會將其閉包內部維護的執行隊列掛載到Promise對象,在數據更新時Vue內部首先就會執行$nextTick方法,之后便將執行隊列掛載到了Promise對象上,其實在明白JsEvent Loop模型后,將數據更新也看做一個$nextTick方法的調用,并且明白$nextTick方法會一次性執行所有推入的回調,就可以明白其執行順序的問題了,下面是一個關于$nextTick方法的最小化的DEMO

var nextTick = (function(){      var pending = false;     const callback = [];     var p = Promise.resolve();      var handler = function(){         pending = true;         callback.forEach(fn => fn());     }      var timerFunc = function(){         p.then(handler);     }      return function queueNextTick(fn){         callback.push(() => fn());         if(!pending){             pending = true;             timerFunc();         }     }  })();   (function(){     nextTick(() => console.log("觸發DOM渲染隊列的方法")); // 注釋 / 取消注釋 來查看效果     setTimeout(() => console.log(1))     Promise.resolve().then(() => console.log(2))     nextTick(() => {         console.log(3)     }) })();
登錄后復制

(學習視頻分享:vuejs入門教程、編程基礎視頻)

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
手机视频在线观看| 欧美国产在线一区| 久久www视频| 做爰高潮hd色即是空| 五月婷婷丁香色| 日本888xxxx| 一区二区三区 日韩| 手机看片福利盒子久久| av视屏在线播放| 我看黄色一级片| 天天爽人人爽夜夜爽| 欧美三级午夜理伦三级| 日本韩国欧美在线观看| 日本免费一级视频| 成人3d动漫一区二区三区| 欧美日韩一区二区在线免费观看| 久久久久久久久久久99| 日韩精品xxxx| 久久久国产欧美| 中文字幕剧情在线观看| 美女在线免费视频| 黄色一级视频片| 国产激情在线观看视频| 天天综合网久久| 午夜啪啪免费视频| 精品这里只有精品| 人人干人人干人人| 国产一二三四五| 欧美三级在线观看视频| 9l视频白拍9色9l视频| 偷拍盗摄高潮叫床对白清晰| 996这里只有精品| 激情内射人妻1区2区3区| 91视频福利网| 国产91在线免费| 在线播放黄色av| 国模吧无码一区二区三区| 亚洲国产精品三区| 日本五级黄色片| 爱爱爱爱免费视频| 免费看日本毛片| 国产系列第一页| 国产精品无码av无码| 国内外成人激情免费视频| 国产一区亚洲二区三区| 浴室偷拍美女洗澡456在线| 免费日韩中文字幕| 一级全黄肉体裸体全过程| 激情五月亚洲色图| 女人帮男人橹视频播放| 亚洲精品第三页| 国产裸体舞一区二区三区| 操bbb操bbb| 五月天国产视频| 九九视频精品在线观看| 免费成人午夜视频| japanese在线播放| www.久久com| 在线播放av中文字幕| 日韩一级片播放| 免费日韩视频在线观看| 日本丰满少妇xxxx| 91午夜在线观看| 欧美在线观看视频免费| 国产欧美综合一区| 只有这里有精品| 亚洲天堂av一区二区三区| 亚洲一级免费在线观看| 少妇一级淫免费播放| 亚洲一级片免费| 天天操天天爱天天爽| 一本久道中文无码字幕av| 国产女女做受ⅹxx高潮| 丰满少妇被猛烈进入高清播放| 人体内射精一区二区三区| 成人免费看片'免费看| 成年丰满熟妇午夜免费视频 | 美女网站色免费| 91淫黄看大片| 69久久久久久| 搡的我好爽在线观看免费视频| 天堂av2020| www.18av.com| 九色在线视频观看| 无码人妻精品一区二区三区在线| 草草久久久无码国产专区| 国产 福利 在线| 亚洲人视频在线| 国产日韩欧美大片| 免费在线观看亚洲视频| 成年人视频在线免费| 欧美精品 - 色网| 青青在线视频免费观看| aa在线免费观看| 中文字幕亚洲欧洲| 欧美日韩福利在线| 中文字幕网av| 六月婷婷激情综合| 男女男精品视频站| 国产乱子伦精品视频| 国产精品第12页| 异国色恋浪漫潭| 国产男女激情视频| 伊人再见免费在线观看高清版 | www.偷拍.com| 国产免费毛卡片| 青青草影院在线观看| 丰满少妇被猛烈进入高清播放| 中文字幕12页| av动漫免费看| 黄色一级大片免费| 91精品999| 男女视频一区二区三区| 伊人网在线免费| 三上悠亚av一区二区三区| 日韩黄色片在线| 三级黄色片免费观看| 亚洲中文字幕久久精品无码喷水| 国产人妻互换一区二区| 激情五月亚洲色图| 2018国产在线| 18禁裸男晨勃露j毛免费观看| 一个色综合久久| 五月婷婷激情久久| 午夜肉伦伦影院| 亚洲 欧美 综合 另类 中字| 一区二区久久精品| 污污的视频免费| 日本女优爱爱视频| aaa毛片在线观看| aa在线免费观看| 国产老熟妇精品观看| a级黄色小视频| 超碰成人免费在线| 免费人成自慰网站| 男人添女人下部视频免费| 久久免费一级片| 草草草视频在线观看| 成人小视频在线观看免费| 91香蕉视频免费看| 福利网在线观看| 日本黄网站色大片免费观看| 久久久一二三四| 国产黄色激情视频| www成人免费| 免费在线a视频| 国产一区视频免费观看| 激情内射人妻1区2区3区| 五月婷婷狠狠操| 嫩草视频免费在线观看| 91免费视频黄| 久久人人爽人人爽人人av| 男人用嘴添女人下身免费视频| 日韩a∨精品日韩在线观看| 欧洲黄色一级视频| 国产三级国产精品国产专区50| www.久久av.com| 91传媒免费视频| 日本三级免费网站| 午夜精品免费看| 97在线免费视频观看| 欧美在线观看成人| 国产女同无遮挡互慰高潮91| 精品国产三级a∨在线| 日韩少妇内射免费播放| 亚洲精品高清无码视频| 四虎免费在线观看视频| 自慰无码一区二区三区| www.亚洲自拍| 免费一级特黄特色毛片久久看| 麻豆三级在线观看| 蜜臀av性久久久久蜜臀av| 亚洲人成无码www久久久| 国产av不卡一区二区| 国产天堂在线播放| 天堂а√在线中文在线| 欧美 国产 小说 另类| 国产资源第一页| 男女视频在线看| www.av片| 一本大道东京热无码aⅴ| 另类小说第一页| 3d动漫一区二区三区| 老司机午夜网站| 天天看片天天操| www.欧美日本| 欧美成人xxxxx| 欧美成人三级在线视频| 51自拍视频在线观看| 亚洲77777| 国产精品亚洲αv天堂无码| 国产一区二区四区| 天天操精品视频| gogogo高清免费观看在线视频| 国产成人精品无码播放| 免费无码毛片一区二三区| 国产精品视频二| 超碰10000| 久久久99精品视频| 国产女人18毛片|