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

史上很全的 JavaScript 模塊化方案和工具

開(kāi)發(fā) 前端
模塊化是大型前端項(xiàng)目的必備要素。JavaScript 從誕生至今,出現(xiàn)過(guò)各種各樣的模塊化方案,讓我們一起來(lái)盤(pán)點(diǎn)下吧。

 模塊化是大型前端項(xiàng)目的必備要素。JavaScript 從誕生至今,出現(xiàn)過(guò)各種各樣的模塊化方案,讓我們一起來(lái)盤(pán)點(diǎn)下吧。

[[325702]]

IIFE 模塊

默認(rèn)情況下,在瀏覽器宿主環(huán)境里定義的變量都是全局變量,如果頁(yè)面引用了多個(gè)這樣的 JavaScript 文件,很容易造成命名沖突。

 

  1. // 定義全局變量 
  2. let count = 0; 
  3. const increase = () => ++count
  4. const reset = () => { 
  5.     count = 0; 
  6.     console.log("Count is reset."); 
  7. }; 
  8.  
  9. // 使用全局變量 
  10. increase(); 
  11. reset(); 

為了避免全局污染,可以用匿名函數(shù)包裹起來(lái),這就是最簡(jiǎn)單的 IIFE 模塊(立即執(zhí)行的函數(shù)表達(dá)式):

 

  1. // 定義 IIFE 模塊 
  2. const iifeCounterModule = (() => { 
  3.     let count = 0; 
  4.     return { 
  5.         increase: () => ++count
  6.         reset: () => { 
  7.             count = 0; 
  8.             console.log("Count is reset."); 
  9.         } 
  10.     }; 
  11. })(); 
  12.  
  13. // 使用 IIFE 模塊 
  14. iifeCounterModule.increase(); 
  15. iifeCounterModule.reset(); 

IIFE 只暴露了一個(gè)全局的模塊名,內(nèi)部都是局部變量,大大減少了全局命名沖突。

每個(gè) IIFE 模塊都是一個(gè)全局變量,這些模塊通常有自己的依賴。可以在模塊內(nèi)部直接使用依賴的全局變量,也可以把依賴作為參數(shù)傳給 IIFE:

 

  1. // 定義帶有依賴的 IIFE 模塊 
  2. const iifeCounterModule = ((dependencyModule1, dependencyModule2) => { 
  3.     let count = 0; 
  4.     return { 
  5.         increase: () => ++count
  6.         reset: () => { 
  7.             count = 0; 
  8.             console.log("Count is reset."); 
  9.         } 
  10.     }; 
  11. })(dependencyModule1, dependencyModule2); 

一些流行的庫(kù)在早期版本都采用這模式,比如大名鼎鼎的 jQuery(最新版本也開(kāi)始用 UMD 模塊了,后面會(huì)介紹)。

還有一種 IIFE,在 API 聲明上遵循了一種格式,就是在模塊內(nèi)部提前定義了這些 API 對(duì)應(yīng)的變量,方便 API 之間互相調(diào)用:

 

  1. // Define revealing module. 
  2. const revealingCounterModule = (() => { 
  3.     let count = 0; 
  4.     const increase = () => ++count
  5.     const reset = () => { 
  6.         count = 0; 
  7.         console.log("Count is reset."); 
  8.     }; 
  9.  
  10.     return { 
  11.         increase, 
  12.         reset 
  13.     }; 
  14. })(); 
  15.  
  16. // Use revealing module. 
  17. revealingCounterModule.increase(); 
  18. revealingCounterModule.reset(); 

CommonJS 模塊(Node.js 模塊)

CommonJS 最初叫 ServerJS,是由 Node.js 實(shí)現(xiàn)的模塊化方案。默認(rèn)情況下,每個(gè) .js 文件就是一個(gè)模塊,模塊內(nèi)部提供了一個(gè)module和exports變量,用于暴露模塊的 API。使用 require 加載和使用模塊。下面這段代碼定義了一個(gè)計(jì)數(shù)器模塊:

 

  1. // 定義 CommonJS 模塊: commonJSCounterModule.js. 
  2. const dependencyModule1 = require("./dependencyModule1"); 
  3. const dependencyModule2 = require("./dependencyModule2"); 
  4.  
  5. let count = 0; 
  6. const increase = () => ++count
  7. const reset = () => { 
  8.     count = 0; 
  9.     console.log("Count is reset."); 
  10. }; 
  11.  
  12. exports.increase = increase; 
  13. exports.reset = reset; 
  14. // 或者這樣: 
  15. module.exports = { 
  16.     increase, 
  17.     reset 
  18. }; 

使用這個(gè)模塊:

 

  1. // 使用 CommonJS 模塊 
  2. const { increase, reset } = require("./commonJSCounterModule"); 
  3. increase(); 
  4. reset(); 
  5. // 或者這樣: 
  6. const commonJSCounterModule = require("./commonJSCounterModule"); 
  7. commonJSCounterModule.increase(); 
  8. commonJSCounterModule.reset(); 

在運(yùn)行時(shí),Node.js 會(huì)將文件內(nèi)的代碼包裹在一個(gè)函數(shù)內(nèi),然后通過(guò)參數(shù)傳遞exports、module變量和require函數(shù)。

 

  1. // Define CommonJS module: wrapped commonJSCounterModule.js. 
  2. (function (exports, require, module, __filename, __dirname) { 
  3.     const dependencyModule1 = require("./dependencyModule1"); 
  4.     const dependencyModule2 = require("./dependencyModule2"); 
  5.  
  6.     let count = 0; 
  7.     const increase = () => ++count
  8.     const reset = () => { 
  9.         count = 0; 
  10.         console.log("Count is reset."); 
  11.     }; 
  12.  
  13.     module.exports = { 
  14.         increase, 
  15.         reset 
  16.     }; 
  17.  
  18.     return module.exports; 
  19. }).call(thisValue, exports, require, module, filename, dirname); 
  20.  
  21. // Use CommonJS module. 
  22. (function (exports, require, module, __filename, __dirname) { 
  23.     const commonJSCounterModule = require("./commonJSCounterModule"); 
  24.     commonJSCounterModule.increase(); 
  25.     commonJSCounterModule.reset(); 
  26. }).call(thisValue, exports, require, module, filename, dirname); 

AMD 模塊(RequireJS 模塊)

AMD(異步模塊定義)也是一種模塊格式,由 RequireJS 這個(gè)庫(kù)實(shí)現(xiàn)。它通過(guò)define函數(shù)定義模塊,并接受模塊名和依賴的模塊名作為參數(shù)。

 

  1. // 定義 AMD 模塊 
  2. define("amdCounterModule", ["dependencyModule1""dependencyModule2"],  
  3.       (dependencyModule1, dependencyModule2) => { 
  4.     let count = 0; 
  5.     const increase = () => ++count
  6.     const reset = () => { 
  7.         count = 0; 
  8.         console.log("Count is reset."); 
  9.     }; 
  10.  
  11.     return { 
  12.         increase, 
  13.         reset 
  14.     }; 
  15. }); 

也用 require加載和使用模塊:

 

  1. require(["amdCounterModule"], amdCounterModule => { 
  2.     amdCounterModule.increase(); 
  3.     amdCounterModule.reset(); 
  4. }); 

跟 CommonJS 不同,這里的 requrie接受一個(gè)回調(diào)函數(shù),參數(shù)就是加載好的模塊對(duì)象。

AMD 的define函數(shù)還可以動(dòng)態(tài)加載模塊,只要給它傳一個(gè)回調(diào)函數(shù),并帶上 require參數(shù):

 

  1. // Use dynamic AMD module. 
  2. define(require => { 
  3.     const dynamicDependencyModule1 = require("dependencyModule1"); 
  4.     const dynamicDependencyModule2 = require("dependencyModule2"); 
  5.  
  6.     let count = 0; 
  7.     const increase = () => ++count
  8.     const reset = () => { 
  9.         count = 0; 
  10.         console.log("Count is reset."); 
  11.     }; 
  12.  
  13.     return { 
  14.         increase, 
  15.         reset 
  16.     }; 
  17. }); 

AMD 模塊還可以給define傳遞module和exports,這樣就可以在內(nèi)部使用 CommonJS 代碼:

 

  1. // 定義帶有 CommonJS 代碼的 AMD 模塊 
  2. define((require, exports, module) => { 
  3.     // CommonJS 代碼 
  4.     const dependencyModule1 = require("dependencyModule1"); 
  5.     const dependencyModule2 = require("dependencyModule2"); 
  6.  
  7.     let count = 0; 
  8.     const increase = () => ++count
  9.     const reset = () => { 
  10.         count = 0; 
  11.         console.log("Count is reset."); 
  12.     }; 
  13.  
  14.     exports.increase = increase; 
  15.     exports.reset = reset; 
  16. }); 
  17.  
  18. // 使用帶有 CommonJS 代碼的 AMD 模塊 
  19. define(require => { 
  20.     // CommonJS 代碼 
  21.     const counterModule = require("amdCounterModule"); 
  22.     counterModule.increase(); 
  23.     counterModule.reset(); 
  24. }); 

UMD 模塊

UMD(通用模塊定義),是一種支持多種環(huán)境的模塊化格式,可同時(shí)用于 AMD 和 瀏覽器(或者 Node.js)環(huán)境。

兼容 AMD 和瀏覽器全局引入:

 

  1. ((root, factory) => { 
  2.     // 檢測(cè)是否存在 AMD/RequireJS 的 define 函數(shù) 
  3.     if (typeof define === "function" && define.amd) { 
  4.         // 如果是,在 define 函數(shù)內(nèi)調(diào)用 factory 
  5.         define("umdCounterModule", ["deependencyModule1""dependencyModule2"], factory); 
  6.     } else { 
  7.         // 否則為瀏覽器環(huán)境,直接調(diào)用 factory 
  8.         // 導(dǎo)入的依賴是全局變量(window 對(duì)象的屬性) 
  9.         // 導(dǎo)出的模塊也是全局變量(window 對(duì)象的屬性) 
  10.         root.umdCounterModule = factory(root.deependencyModule1, root.dependencyModule2); 
  11.     } 
  12. })(typeof self !== "undefined" ? self : this, (deependencyModule1, dependencyModule2) => { 
  13.     // 具體的模塊代碼 
  14.     let count = 0; 
  15.     const increase = () => ++count
  16.     const reset = () => { 
  17.         count = 0; 
  18.         console.log("Count is reset."); 
  19.     }; 
  20.  
  21.     return { 
  22.         increase, 
  23.         reset 
  24.     }; 
  25. }); 

看起來(lái)很復(fù)雜,其實(shí)就是個(gè) IIFE。代碼注釋寫(xiě)得很清楚了,可以看看。

下面來(lái)看兼容 AMD 和 CommonJS(Node.js)模塊的 UMD:

 

  1. (define => define((require, exports, module) => { 
  2.     // 模塊代碼 
  3.     const dependencyModule1 = require("dependencyModule1"); 
  4.     const dependencyModule2 = require("dependencyModule2"); 
  5.  
  6.     let count = 0; 
  7.     const increase = () => ++count
  8.     const reset = () => { 
  9.         count = 0; 
  10.         console.log("Count is reset."); 
  11.     }; 
  12.  
  13.     module.export = { 
  14.         increase, 
  15.         reset 
  16.     }; 
  17. }))(// 判斷 CommonJS 里的 module 變量和 exports 變量是否存在 
  18.     // 同時(shí)判斷 AMD/RequireJS 的define 函數(shù)是否存在 
  19.     typeof module === "object" && module.exports && typeof define !== "function" 
  20.         ? // 如果是 CommonJS/Node.js,手動(dòng)定義一個(gè) define 函數(shù) 
  21.             factory => module.exports = factory(require, exports, module) 
  22.         : // 否則是 AMD/RequireJS,直接使用 define 函數(shù) 
  23.             define); 

同樣是個(gè) IIFE,通過(guò)判斷環(huán)境,選擇執(zhí)行對(duì)應(yīng)的代碼。

ES 模塊(ES6 Module)

前面說(shuō)到的幾種模塊格式,都是用到了各種技巧實(shí)現(xiàn)的,看起來(lái)眼花繚亂。終于,在 2015 年,ECMAScript 第 6 版(ES 2015,或者 ES6 )橫空出世!它引入了一種全新的模塊格式,主要語(yǔ)法就是 import和epxort關(guān)鍵字。來(lái)看 ES6 怎么定義模塊:

 

  1. // 定義 ES 模塊:esCounterModule.js 或 esCounterModule.mjs. 
  2. import dependencyModule1 from "./dependencyModule1.mjs"
  3. import dependencyModule2 from "./dependencyModule2.mjs"
  4.  
  5. let count = 0; 
  6. // 具名導(dǎo)出: 
  7. export const increase = () => ++count
  8. export const reset = () => { 
  9.     count = 0; 
  10.     console.log("Count is reset."); 
  11. }; 
  12. // 默認(rèn)導(dǎo)出 
  13. export default { 
  14.     increase, 
  15.     reset 
  16. }; 

瀏覽器里使用該模塊,在 script標(biāo)簽上加上type="module",表明引入的是 ES 模塊。在 Node.js 環(huán)境中使用時(shí),把擴(kuò)展名改成 .mjs。

 

  1. // Use ES module. 
  2. //瀏覽器: <script type="module" src="esCounterModule.js"></script> or inline. 
  3.  
  4. // 服務(wù)器:esCounterModule.mjs 
  5. import { increase, reset } from "./esCounterModule.mjs"
  6. increase(); 
  7. reset(); 
  8. // Or import from default export: 
  9. import esCounterModule from "./esCounterModule.mjs"
  10. esCounterModule.increase(); 
  11. esCounterModule.reset(); 

瀏覽器如果不支持,可以加個(gè)兜底屬性:

 

 

  1. <script nomodule> 
  2.     alert("Not supported."); 
  3. </script> 

ES 動(dòng)態(tài)模塊(ECMAScript 2020)

2020 年最新的 ESCMA 標(biāo)準(zhǔn)11版中引入了內(nèi)置的 import函數(shù),用于動(dòng)態(tài)加載 ES 模塊。import函數(shù)返回一個(gè) Promise,在它的then回調(diào)里使用加載后的模塊:

 

  1. // 用 Promise API 加載動(dòng)態(tài) ES 模塊 
  2. import("./esCounterModule.js").then(({ increase, reset }) => { 
  3.     increase(); 
  4.     reset(); 
  5. }); 
  6.  
  7. import("./esCounterModule.js").then(dynamicESCounterModule => { 
  8.     dynamicESCounterModule.increase(); 
  9.     dynamicESCounterModule.reset(); 
  10. }); 

由于返回的是 Promise,那肯定也支持await用法:

 

  1. // 通過(guò) async/await 使用 ES 動(dòng)態(tài)模塊 
  2. (async () => { 
  3.     // 具名導(dǎo)出的模塊 
  4.     const { increase, reset } = await import("./esCounterModule.js"); 
  5.     increase(); 
  6.     reset(); 
  7.     // 默認(rèn)導(dǎo)出的模塊 
  8.     const dynamicESCounterModule = await import("./esCounterModule.js"); 
  9.     dynamicESCounterModule.increase(); 
  10.     dynamicESCounterModule.reset(); 
  11. })(); 

各平臺(tái)對(duì)import、export和動(dòng)態(tài)import的兼容情況如下:

 

 

image.png

 

 

 

 

image.png

 

 

System 模塊

SystemJS 是一個(gè) ES 模塊語(yǔ)法轉(zhuǎn)換庫(kù),以便支持低版本的 ES。例如,下面的模塊是用 ES6 語(yǔ)法定義的:

 

  1. // 定義 ES 模塊 
  2. import dependencyModule1 from "./dependencyModule1.js"
  3. import dependencyModule2 from "./dependencyModule2.js"
  4. dependencyModule1.api1(); 
  5. dependencyModule2.api2(); 
  6.  
  7. let count = 0; 
  8. // Named export: 
  9. export const increase = function () { return ++count }; 
  10. export const reset = function () { 
  11.     count = 0; 
  12.     console.log("Count is reset."); 
  13. }; 
  14. // Or default export: 
  15. export default { 
  16.     increase, 
  17.     reset 

如果當(dāng)前的運(yùn)行環(huán)境(比如舊瀏覽器)不支持 ES6 語(yǔ)法,上面的代碼就無(wú)法運(yùn)行。一種方案是把上面的模塊定義轉(zhuǎn)換成 SystemJS 庫(kù)的一個(gè) API, System.register:

 

  1. // Define SystemJS module. 
  2. System.register(["./dependencyModule1.js""./dependencyModule2.js"],  
  3.                 function (exports_1, context_1) { 
  4.     "use strict"
  5.     var dependencyModule1_js_1, dependencyModule2_js_1, count, increase, reset; 
  6.     var __moduleName = context_1 && context_1.id; 
  7.     return { 
  8.         setters: [ 
  9.             function (dependencyModule1_js_1_1) { 
  10.                 dependencyModule1_js_1 = dependencyModule1_js_1_1; 
  11.             }, 
  12.             function (dependencyModule2_js_1_1) { 
  13.                 dependencyModule2_js_1 = dependencyModule2_js_1_1; 
  14.             } 
  15.         ], 
  16.         executefunction () { 
  17.             dependencyModule1_js_1.default.api1(); 
  18.             dependencyModule2_js_1.default.api2(); 
  19.             count = 0; 
  20.             // Named export: 
  21.             exports_1("increase", increase = function () { return ++count }; 
  22.             exports_1("reset", reset = function () { 
  23.                 count = 0; 
  24.                 console.log("Count is reset."); 
  25.             };); 
  26.             // Or default export: 
  27.             exports_1("default", { 
  28.                 increase, 
  29.                 reset 
  30.             }); 
  31.         } 
  32.     }; 
  33. }); 

這樣,import/export關(guān)鍵字就不見(jiàn)了。Webpack、TypeScript 等可以自動(dòng)完成這樣的轉(zhuǎn)換(后面會(huì)講)。

SystemJS 也支持動(dòng)態(tài)加載模塊:

 

  1. // Use SystemJS module with promise APIs. 
  2. System.import("./esCounterModule.js").then(dynamicESCounterModule => { 
  3.     dynamicESCounterModule.increase(); 
  4.     dynamicESCounterModule.reset(); 
  5. }); 

Webpack 模塊(打包 AMD,CJS,ESM)

Webpack 是個(gè)強(qiáng)大的模塊打包工具,可以將 AMD、CommonJS 和 ES Module 格式的模塊轉(zhuǎn)換并打包到單個(gè) JS 文件。

Babel 模塊

Babel 是也個(gè)轉(zhuǎn)換器,可將 ES6+ 代碼轉(zhuǎn)換成低版本的 ES。前面例子中的計(jì)數(shù)器模塊用 Babel 轉(zhuǎn)換后的代碼是這樣的:

 

  1. // Babel. 
  2. Object.defineProperty(exports, "__esModule", { 
  3.     value: true 
  4. }); 
  5. exports["default"] = void 0; 
  6. function _interopRequireDefault(obj)  
  7.          { return obj && obj.__esModule ? obj : { "default": obj }; } 
  8.  
  9. // Define ES module: esCounterModule.js. 
  10. var dependencyModule1 = _interopRequireDefault(require("./amdDependencyModule1")); 
  11. var dependencyModule2 = _interopRequireDefault(require("./commonJSDependencyModule2")); 
  12. dependencyModule1["default"].api1(); 
  13. dependencyModule2["default"].api2(); 
  14.  
  15. var count = 0; 
  16. var increase = function () { return ++count; }; 
  17. var reset = function () { 
  18.     count = 0; 
  19.     console.log("Count is reset."); 
  20. }; 
  21.  
  22. exports["default"] = { 
  23.     increase: increase, 
  24.     reset: reset 
  25. }; 

引入該模塊的index.js將會(huì)轉(zhuǎn)換成:

 

  1. // Babel. 
  2. function _interopRequireDefault(obj)  
  3.          { return obj && obj.__esModule ? obj : { "default": obj }; } 
  4.  
  5. // Use ES module: index.js 
  6. var esCounterModule = _interopRequireDefault(require("./esCounterModule.js")); 
  7. esCounterModule["default"].increase(); 
  8. esCounterModule["default"].reset(); 

以上是 Babel 的默認(rèn)轉(zhuǎn)換行為,它還可以結(jié)合其他插件使用,比如前面提到的 SystemJS。經(jīng)過(guò)配置,Babel 可將 AMD、CJS、ES Module 轉(zhuǎn)換成 System 模塊格式。

TypeScript 模塊

TypeScript 是 JavaScript 的超集,可以支持所有 JavaScript 語(yǔ)法,包括 ES6 模塊語(yǔ)法。它在轉(zhuǎn)換時(shí),可以保留 ES6 語(yǔ)法,也可以轉(zhuǎn)換成 AMD、CJS、UMD、SystemJS 等格式,取決于配置:

 

  1.     "compilerOptions": { 
  2.         "module""ES2020", // None, CommonJS, AMD, System, UMD, ES6, ES2015, ES2020, ESNext. 
  3.     } 

TypeScript 還支持 module和namespace關(guān)鍵字,表示內(nèi)部模塊。

 

  1. module Counter { 
  2.     let count = 0; 
  3.     export const increase = () => ++count
  4.     export const reset = () => { 
  5.         count = 0; 
  6.         console.log("Count is reset."); 
  7.     }; 
  8.  
  9. namespace Counter { 
  10.     let count = 0; 
  11.     export const increase = () => ++count
  12.     export const reset = () => { 
  13.         count = 0; 
  14.         console.log("Count is reset."); 
  15.     }; 

都可以轉(zhuǎn)換成 JavaScript 對(duì)象:

 

  1. var Counter; 
  2. (function (Counter) { 
  3.     var count = 0; 
  4.     Counter.increase = function () { return ++count; }; 
  5.     Counter.reset = function () { 
  6.         count = 0; 
  7.         console.log("Count is reset."); 
  8.     }; 
  9. })(Counter || (Counter = {})); 

總結(jié)

以上提到的各種模塊格式是在 JavaScript 語(yǔ)言演進(jìn)過(guò)程中出現(xiàn)的模塊化方案,各有其適用環(huán)境。隨著標(biāo)準(zhǔn)化推進(jìn),Node.js 和最新的現(xiàn)代瀏覽器都開(kāi)始支持 ES 模塊格式。如果要在舊環(huán)境中使用模塊化,可以通過(guò) Webpack、Babel、TypeScript、SystemJS 等工具進(jìn)行轉(zhuǎn)換。

責(zé)任編輯:華軒 來(lái)源: 1024譯站
相關(guān)推薦

2019-08-28 16:18:39

JavaScriptJS前端

2018-01-03 10:26:51

前端JavaScript模塊

2017-04-10 14:23:01

typescriptjavascriptwebpack

2015-11-23 09:50:15

JavaScript模塊化SeaJs

2010-08-02 08:54:53

Flex模塊化

2013-08-20 18:39:34

JavaScript模requireJS

2020-09-17 10:30:21

前端模塊化組件

2020-09-18 09:02:32

前端模塊化

2022-11-02 18:47:46

場(chǎng)景模塊化跨棧

2019-02-11 14:35:59

Linux硬件監(jiān)控工具命令

2021-10-27 06:02:10

網(wǎng)絡(luò)釣魚(yú)工具包攻擊

2021-12-02 05:57:04

模塊化UPS電源

2022-09-05 09:01:13

前端模塊化

2016-10-09 11:03:41

Javascript模塊化Web

2017-12-28 15:20:50

2013-08-20 18:18:55

CSS模塊化Normalize.c

2022-09-21 11:51:26

模塊化應(yīng)用

2017-05-18 10:23:55

模塊化開(kāi)發(fā)RequireJsJavascript

2013-08-20 15:31:18

前端模塊化

2022-09-02 08:00:00

CSS開(kāi)發(fā)框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

欧美大秀在线观看| 日本三级午夜理伦三级三| 欧美影视资讯| 亚洲三级免费电影| 国产亚洲欧美一区二区| 天天射天天干天天| 综合五月婷婷| 亚洲免费电影在线观看| 成人一区二区三| av在线下载| 久久久国产精品不卡| 成人黄色免费看| 91九色丨porny丨肉丝| 久久免费av| 日韩经典一区二区三区| 中文字幕在线观看日| 亚洲美女炮图| 亚洲午夜免费视频| 一卡二卡3卡四卡高清精品视频| 亚洲精品一区二区三区区别| 青青草精品视频| 午夜精品理论片| 黄色一级大片在线免费观看| 中文字幕伦av一区二区邻居| 欧美不卡123| 在线观看免费不卡av| av电影一区| 亚洲第一综合色| 国产树林野战在线播放| 成年人视频在线看| 91亚洲精品一区二区乱码| 114国产精品久久免费观看| 国产suv精品一区二区33| 国产精品99一区二区| 日韩最新在线视频| 久久午夜福利电影| 人体久久天天| 亚洲国产精品久久久久久| 亚洲综合伊人久久| 国产精品蜜月aⅴ在线| 色国产综合视频| 日韩在线xxx| 成人影院av| 欧美性极品xxxx做受| 中文精品一区二区三区| 91青青在线视频| 久久久亚洲综合| 免费成人深夜夜行视频| 午夜影院免费体验区| 成人在线视频一区| 国产精品久久久久久久久婷婷 | 国产精品一二| 992tv在线成人免费观看| 国产一级生活片| 亚洲三级电影在线观看| 韩国精品久久久999| 久久久精品人妻一区二区三区四| **女人18毛片一区二区| 久久在线精品视频| 久久精品视频免费在线观看| 亚洲精品在线观看91| 久久亚洲国产精品成人av秋霞| 午夜精品久久久久99蜜桃最新版| 久久香蕉国产| 欧美成人黄色小视频| 精品视频久久久久| 在线综合视频| 国产成人啪精品视频免费网| 在线视频播放大全| 国产一区美女在线| 99re在线观看视频| 天天摸天天干天天操| 97超碰欧美中文字幕| 欧美日韩电影一区二区| 黄上黄在线观看| 国产精品乱码妇女bbbb| 黄色网络在线观看| 国产一二三在线| 91成人免费在线视频| 亚洲老女人av| 亚洲日本va中文字幕| 日韩av在线精品| 2019男人天堂| 欧美日韩调教| 青青草成人在线| 一级成人免费视频| 成人午夜精品在线| 日韩av图片| www国产在线观看| 欧美日韩国产精品一区二区三区四区 | 欧美日韩一区二区三区免费看 | 中文字幕第31页| 国产一区久久久| 久久精品一区二区三区不卡免费视频| 国产小视频在线观看| 亚洲精品国产a久久久久久 | 欧美亚洲韩国| 日韩一区二区免费电影| 大地资源二中文在线影视观看| 欧美色婷婷久久99精品红桃| 九九精品视频在线观看| 亚洲中文字幕无码爆乳av| 国产精品自在在线| 日本一区网站| 2020日本在线视频中文字幕| 精品视频在线看| 亚洲天堂美女视频| 亚欧美无遮挡hd高清在线视频 | 影音先锋日韩有码| 久久精品国产亚洲av无码娇色| 天堂蜜桃91精品| 国产精品sss| 日韩子在线观看| 色老头久久综合| 精品久久精品久久| 激情综合闲人网| 亚洲自拍另类综合| 国产又大又黄又猛| 伊甸园亚洲一区| 欧美精品福利在线| 91尤物国产福利在线观看| 久久综合色婷婷| 成人免费观看在线| 电影91久久久| 色妞在线综合亚洲欧美| chinese国产精品| 成人av片在线观看| 国产精品久久久影院| av亚洲一区二区三区| 亚洲精品久久久久中文字幕欢迎你 | 免费在线观看的av网站| 91成人精品在线| 欧美成人四级hd版| 国产三级视频在线播放| 国产精品女上位| 看欧美ab黄色大片视频免费| 神马日本精品| 91po在线观看91精品国产性色 | 欧美一级做a| 亚洲一区二区国产| 日韩黄色片网站| 国产亚洲欧洲997久久综合| 鲁一鲁一鲁一鲁一澡| a看欧美黄色女同性恋| 欧美伦理91i| 亚洲国产精品无码久久| 亚洲综合免费观看高清完整版| 图片区乱熟图片区亚洲| 亚洲高清影视| 亚洲字幕在线观看| 中文字幕伦理免费在线视频| 欧美一级生活片| 免费在线观看日韩| 国产福利视频一区二区三区| 成年在线观看视频| 风间由美性色一区二区三区四区| 欧美大片欧美激情性色a∨久久| 国产成a人亚洲精v品无码| 亚洲欧美激情插| 91亚洲一线产区二线产区| 好吊一区二区三区| 国产综合第一页| 欧美亚洲韩国| xxav国产精品美女主播| 国产免费一区二区三区最新不卡 | 欧美一区二区三区久久| 欧美孕妇与黑人孕交| 蜜桃视频在线观看视频| 欧美午夜精品电影| 欧美三根一起进三p| 成人精品国产一区二区4080| 国产精品后入内射日本在线观看| 羞羞答答一区二区| 国产精品久久久久久久7电影| 18视频免费网址在线观看| 欧美猛男男办公室激情| 精品97人妻无码中文永久在线| 成人听书哪个软件好| 四虎永久在线精品无码视频| 日本高清免费电影一区| 99久久精品免费看国产四区| 国产美女精品写真福利视频| 一本一道久久a久久精品逆3p| 国产精品人人妻人人爽| 图片区小说区国产精品视频| 久久精品国产亚洲av久| 污软件在线观看| 欧洲美女精品免费观看视频| 日韩一中文字幕| 欧美自拍偷拍第一页| 在线视频一区二区三区| 中文字幕手机在线观看| 91亚洲国产成人精品一区二三| 无码无遮挡又大又爽又黄的视频| 日韩av一区二区在线观看| 少妇精品无码一区二区三区| 久久夜色精品| wwwjizzjizzcom| 欧美一性一交| 成人黄色免费网站在线观看| 男女羞羞在线观看| 不卡伊人av在线播放| 亚洲三区在线观看无套内射| 欧美日韩一区二区三区高清| 日本少妇久久久| 日韩美女视频19| a级大片在线观看| 国产99精品国产| 亚洲第一中文av| 99视频一区| 国产日韩欧美大片| 国产成人影院| 国产一区二区三区黄| 国产精品美女久久久久人| 日本精品在线视频 | 日韩视频免费大全中文字幕| 五月天丁香视频| 欧美不卡123| 99产精品成人啪免费网站| 在线观看日韩电影| 午夜精品久久久久久久久久久久久蜜桃| ...xxx性欧美| 一二三四在线观看视频| 久久亚洲精华国产精华液| jjzzjjzz欧美69巨大| 国产精一区二区三区| 亚洲欧美久久久久| 日产国产欧美视频一区精品| 熟女少妇在线视频播放| 激情亚洲成人| 男人天堂av片| 欧美特黄a级高清免费大片a级| 一区二区三视频| 日韩中文首页| 中国人体摄影一区二区三区| re久久精品视频| 午夜精品一区二区在线观看 | 成人永久aaa| 久久久久久久久久影视| 国产成人无遮挡在线视频| 国产成人强伦免费视频网站| 精品综合久久久久久8888| 午夜在线观看av| 麻豆freexxxx性91精品| 中日韩av在线播放| 精品一区二区日韩| 91香蕉视频免费看| 成人精品视频网站| av网页在线观看| 久久一区二区三区四区| 人人妻人人藻人人爽欧美一区| 久久网站最新地址| 国产真人做爰视频免费| 国产精品乱子久久久久| 亚洲欧美精品aaaaaa片| 一区二区三区在线影院| 国产一卡二卡在线| 色综合久久中文综合久久牛| 伦av综合一区| 欧美日韩国产成人在线免费| 国产又大又黑又粗| 精品国产乱码久久久久久久 | www.玖玖玖| 日本中文字幕一区二区视频 | 欧美另类中文字幕| 国产精品久久久久久久久婷婷 | 成人av在线观| 国产精品1000部啪视频| 国产日产欧美精品一区二区三区| 懂色av粉嫩av浪潮av| 亚洲欧美日韩中文字幕一区二区三区 | 国产日韩换脸av一区在线观看| 日韩一区二区三区四区五区| 97视频中文字幕| 西野翔中文久久精品字幕| 四虎永久国产精品| 国产精品www994| www.国产区| 国产精品99久久久久久宅男| 久久久高清视频| 欧美国产精品中文字幕| 欧美日韩成人免费观看| 欧美性xxxx在线播放| 97国产成人无码精品久久久| 亚洲成人亚洲激情| av一本在线| 久久久噜噜噜久久中文字免| 成人软件在线观看| 97se亚洲综合在线| 精品av一区二区| 日b视频免费观看| 日韩国产在线观看| 日本性生活一级片| 国产精品每日更新在线播放网址| 国产精品theporn动漫| 欧美亚洲高清一区二区三区不卡| www.五月婷婷| 在线播放亚洲激情| av中文在线资源| 成人精品视频99在线观看免费| 美女呻吟一区| 成人在线观看www| 视频一区中文字幕国产| 国产污在线观看| 成人欧美一区二区三区小说| 久久久久99精品成人片三人毛片| 国产精品久久久久婷婷二区次| 欧美丝袜在线观看| 91论坛在线播放| 欧美成人手机视频| 欧美色视频在线观看| 天天综合网在线| 乱亲女秽乱长久久久| 成人国产在线| 久久久久久一区| 伊人狠狠色j香婷婷综合| а 天堂 在线| 欧美国产精品v| www.久久久久久久| 亚洲国产日韩欧美在线图片| 在线观看中文| 国产在线高清精品| 久久国产中文字幕| 日韩有码免费视频| wwwwww.欧美系列| 日韩黄色a级片| 精品美女被调教视频大全网站| 麻豆av在线免费看| 国产欧美一区二区三区在线看| 色综合综合网| 人妻内射一区二区在线视频| av不卡免费在线观看| 国产一级做a爱免费视频| 日韩午夜电影在线观看| a级影片在线观看| 97se视频在线观看| 好看的亚洲午夜视频在线| 中文字幕1区2区| 亚洲一区二区三区四区在线| 国产偷人妻精品一区二区在线| 久久久精品在线| 国产精品毛片无码| 一二三在线视频| 丁香六月久久综合狠狠色| 久久久久成人网站| 精品福利一二区| 成人观看网址| 鲁鲁狠狠狠7777一区二区| 亚洲一区二区三区高清不卡| 波多野结衣影院| 色婷婷av久久久久久久| 国产美女性感在线观看懂色av | www.成人在线.com| 欧美一级黄色录像片| 国产精品主播直播| 五月天婷婷网站| 亚洲欧美国产日韩天堂区| 成人免费福利| 波多野结衣三级在线| 高清成人在线观看| 天堂а√在线中文在线新版| 国产一区二区三区日韩欧美| 久久日本片精品aaaaa国产| 国产卡一卡二在线| 成人福利视频网站| 探花视频在线观看| 自拍偷拍亚洲区| 亚洲福利合集| www.爱色av.com| 国产精品传媒入口麻豆| 性欧美一区二区三区| 欧美一区视频在线| 久久综合av| 精品视频站长推荐| 欧洲在线/亚洲| a视频在线免费看| 国产麻豆日韩| 蜜臀国产一区二区三区在线播放| 日韩a级片在线观看| 日韩av网站在线| **国产精品| 噜噜噜久久亚洲精品国产品麻豆| 中文字幕va一区二区三区| 成 人 免费 黄 色| 国产91色在线播放| 中文字幕一区二区三三| 日韩av一二区| 欧美一区二区三区免费在线看| 91在线超碰| 在线免费观看成人网| 99久久综合国产精品| 一级特黄录像免费看| 久久久久久久久久久网站| 精品免费一区二区| 色婷婷狠狠18禁久久| 欧洲av在线精品| 都市激情国产精品| 免费观看中文字幕| 久久久久久久久久久99999| 国产黄a三级三级看三级|