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

從零開始編寫自己的JavaScript框架(一)

開發 前端
一個框架想要能支撐較大的應用,首先要考慮怎么做模塊化。有了內核和模塊加載系統,外圍的模塊就可以一個一個增加。不同的JavaScript框架,實現模塊化方式各有不同,我們來選擇一種比較優雅的方式作個講解。

1. 模塊的定義和加載

1.1 模塊的定義

一個框架想要能支撐較大的應用,首先要考慮怎么做模塊化。有了內核和模塊加載系統,外圍的模塊就可以一個一個增加。不同的JavaScript框架,實現模塊化方式各有不同,我們來選擇一種比較優雅的方式作個講解。

先問個問題:我們做模塊系統的目的是什么?如果覺得這個問題難以回答,可以從反面來考慮:假如不做模塊系統,有什么樣的壞處?

我們經歷過比較粗放、混亂的前端開發階段,頁面里充滿了全局變量,全局函數。那時候要復用js文件,就是把某些js函數放到一個文件里,然后讓多個頁面都來引用。

考慮到一個頁面可以引用多個這樣的js,這些js互相又不知道別人里面寫了什么,很容易造成命名的沖突,而產生這種沖突的時候,又沒有哪里能夠提示出來。所以我們要有一種辦法,把作用域比較好地隔開。

JavaScript這種語言比較奇怪,奇怪在哪里呢,它的現有版本里沒package跟class,要是有,我們也沒必要來考慮什么自己做模塊化了。那它是要用什么東西來隔絕作用域呢?

在很多傳統高級語言里,變量作用域的邊界是大括號,在{}里面定義的變量,作用域不會傳到外面去,但我們的JavaScript大人不是這樣的,他的邊界是function。所以我們這段代碼,i仍然能打出值:

  1. for (var i=0; i<5; i++) { 
  2.     //do something 
  3. alert(i); 

那么,我們只能選用function做變量的容器,把每個模塊封裝到一個function里。現在問題又來了,這個function本身的作用域是全局的,怎么辦?我們想不到辦法,拔劍四顧心茫然。

我們有沒有什么可參照的東西呢?這時候,腦海中一群語言飄過: C語言飄過:“我不是面向對象語言哦~不需要像你這么組織哦~”,“死開!” Java飄過:“我是純面向對象語言哦,連main都要在類中哦,編譯的時候通過裝箱清單指定入口哦~”,“死開!” C++飄過:“我也是純面向對象語言哦”,等等,C++是純面向對象的語言嗎?你的main是什么???main是特例,不在任何類中!

啊,我們發現了什么,既然無法避免全局的作用域,那與其讓100個function都全局,不如只讓一個來全局,其他的都由它管理。

本來我們打算自己當上帝的,現在只好改行先當個工商局長。你想開店嗎?先來注冊,不然封殺你!于是良民們紛紛來注冊。店名叫什么,從哪進貨,賣什么的,一一登記在案,為了方便下面的討論,我們連進貨的過程都讓工商局管理起來。

店名,指的就是這里的模塊名,從哪里進貨,代表它依賴什么其他模塊,賣什么,表示它對外提供一些什么特性。

好了,考慮到我們的這個注冊管理機構是個全局作用域,我們還得把它掛在window上作為屬性,然后再用一個function隔離出來,要不然,別人也定義一個同名的,就把我們覆蓋掉了。

  1. (function() { 
  2.     window.thin = { 
  3.         define: function(name, dependencies, factory) { 
  4.             //register a module 
  5.         } 
  6.     }; 
  7. })(); 

在這個module方法內部,應當怎么去實現呢?我們的module應當有一個地方存儲,但存儲是要在工商局內部的,不是隨便什么人都可以看到的,所以,這個存儲結構也放在工商局同樣的作用域里。

用什么結構去存儲呢?工商局備案的時候,店名不能跟已有的重復,所以我們發現這是用hash的很好場景,考慮到JavaScript語言層面沒有hash,我們弄個Object來存。

  1. (function() { 
  2.     var moduleMap = {}; 
  3.     window.thin = { 
  4.         define: function(name, dependencies, factory) { 
  5.             if (!moduleMap[name]) { 
  6.                 var module = { 
  7.                     name: name, 
  8.                     dependencies: dependencies, 
  9.                     factory: factory 
  10.                 }; 
  11.                 moduleMap[name] = module; 
  12.             } 
  13.             return moduleMap[name]; 
  14.         } 
  15.     }; 
  16. })(); 

現在,模塊的存儲結構就搞好了。

1.2 模塊的使用

存的部分搞好了,我們來看看怎么取。現在來了一個商家,賣木器的,他需要從一個賣釘子的那邊進貨,賣釘子的已經來注冊過了,現在要讓這個木器廠能買 到釘子。現在的問題是,兩個商家處于不同的作用域,也就是說,它們互相不可見,那通過什么方式,我們才能讓他們產生調用關系呢?

個人解決不了的問題還是得靠政府,有困難要堅決克服,沒有困難就制造困難來克服。現在困難有了,該克服了。商家說,我能不能給你我的進貨名單,你幫我查一下它們在哪家店,然后告訴我?這么簡單的要求當然一口答應下來,但是采用什么方式傳遞給你呢?這可犯難了。

我們參考AngularJS框架,寫了一個類似的代碼:

  1. thin.define("A", [], function() { 
  2.     //module A 
  3. }); 
  4.  
  5. thin.define("B", ["A"], function(A) { 
  6.     //module B 
  7.     var a = new A(); 
  8. }); 

看這段代碼特別在哪里呢?模塊A的定義,毫無特別之處,主要看模塊B。它在依賴關系里寫了一個字符串的A,然后在工廠方法的形參寫了一個真真切切的A類 型。嗯?這個有些奇怪啊,你的A類型要怎么傳遞過來呢?其實是很簡單的,因為我們聲明了依賴項的數組,所以可以從依賴項,挨個得到對應的工廠方法,然后創 建實例,傳進來。

  1. use: function(name) { 
  2.     var module = moduleMap[name]; 
  3.  
  4.     if (!module.entity) { 
  5.         var args = []; 
  6.         for (var i=0; i<module.dependencies.length; i++) { 
  7.             if (moduleMap[module.dependencies[i]].entity) { 
  8.                 args.push(moduleMap[module.dependencies[i]].entity); 
  9.             } 
  10.             else { 
  11.                 args.push(this.use(module.dependencies[i])); 
  12.             } 
  13.         } 
  14.  
  15.         module.entity = module.factory.apply(noop, args); 
  16.     } 
  17.  
  18.     return module.entity; 

#p#

我們可以看到,這里面遞歸獲取了依賴項,然后當作參數,用這個模塊的工廠方法來實例化了一下。這里我們多做了一個判斷,如果模塊工廠已經執行過,就緩存在entity屬性上,不需要每次都創建。以此類推,假如一個模塊有多個依賴項,也可以用類似的方式寫,毫無壓力:

  1. thin.define("D", ["A""B""C"], function(A, B, C) { 
  2.     //module D 
  3.     var a = new A(); 
  4.     var b = new B(); 
  5.     var c = new C(); 
  6. }); 

注意了,D模塊的工廠,實參的名稱未必就要是跟依賴項一致,比如,以后我們代碼較多,可以給依賴項和模塊名稱加命名空間,可能變成這樣:

  1. thin.define("foo.D", ["foo.A""foo.B""foo.C"], function(A, B, C) { 
  2.     //module D 
  3.     var a = new A(); 
  4.     var b = new B(); 
  5.     var c = new C(); 
  6. }); 

這段代碼仍然可以正常運行。我們來做另外一個測試,改變形參的順序:

  1. thin.define("A", [], function() { 
  2.     return "a"
  3. }); 
  4.  
  5. thin.define("B", [], function() { 
  6.     return "b"
  7. }); 
  8.  
  9. thin.define("C", [], function() { 
  10.     return "c"
  11. }); 
  12.  
  13. thin.define("D", ["A""B""C"], function(B, A, C) { 
  14.     return B + A + C; 
  15. }); 
  16.  
  17. var D = thin.use("D"); 
  18. alert(D); 

試試看,我們的D打出什么結果呢?結果是"abc",所以說,模塊工廠的實參只跟依賴項的定義有關,跟形參的順序無關。我們看到,在AngularJS里面,并非如此,實參的順序是跟形參一致的,這是怎么做到的呢?

我們先離開代碼,思考這么一個問題:如何得知函數的形參名數組?對,我們是可以用func.length得到形參個數,但無法得到每個形參的變量名,那怎么辦呢?

AngularJS使用了一種比較極端的辦法,分析了函數的字面量。眾所周知,在JavaScript中,任何對象都隱含了toString方法, 對于一個函數來說,它的toString就是自己的實現代碼,包含函數簽名和注釋。下面我貼一下AngularJS里面的這部分代碼:

  1. var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; 
  2. var FN_ARG_SPLIT = /,/; 
  3. var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; 
  4. var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; 
  5. function annotate(fn) { 
  6.   var $inject, 
  7.       fnText, 
  8.       argDecl, 
  9.       last; 
  10.  
  11.   if (typeof fn == 'function') { 
  12.     if (!($inject = fn.$inject)) { 
  13.       $inject = []; 
  14.       fnText = fn.toString().replace(STRIP_COMMENTS, ''); 
  15.       argDecl = fnText.match(FN_ARGS); 
  16.       forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ 
  17.         arg.replace(FN_ARG, function(all, underscore, name){ 
  18.           $inject.push(name); 
  19.         }); 
  20.       }); 
  21.       fn.$inject = $inject; 
  22.     } 
  23.   } else if (isArray(fn)) { 
  24.     last = fn.length - 1; 
  25.     assertArgFn(fn[last], 'fn'); 
  26.     $inject = fn.slice(0, last); 
  27.   } else { 
  28.     assertArgFn(fn, 'fn'true); 
  29.   } 
  30.   return $inject; 

可以看到,這個代碼也不長,重點是類型為function的那段,首先去除了注釋,然后獲取了形參列表字符串,這段正則能獲取到兩個結果,***個是 全函數的實現,第二個才是真正的形參列表,取第二個出來split,就得到了形參的字符串列表了,然后按照這個順序再去加載依賴模塊,就可以讓形參列表不 對應于依賴項數組了。

AngularJS的這段代碼很強大,但是要損耗一些性能,考慮到我們的框架首要原則是簡單,甚至可以為此犧牲一些靈活性,我們不做這么復雜的事情了。

1.3 模塊的加載

到目前為止,我們可以把多個模塊都定義在一個文件中,然后手動引入這個js文件,但是如果一個頁面要引用很多個模塊,引入工作就變得比較麻煩,比如 說,單頁應用程序(SPA)一般比較復雜,往往包含數以萬計行數的js代碼,這些代碼至少分布在幾十個甚至成百上千的模塊中,如果我們也在主界面就加載它 們,載入時間會非常難以接受。但我們可以這樣看:主界面加載的時候,并不是用到了所有這些功能,能否先加載那些必須的,而把剩下的放在需要用的時候再去加 載?

所以我們可以考慮***的AJAX,從服務端獲取一個js的內容,然后……,怎么辦,你當然說不能eval了,因為據說eval很evil啦,但是它 evil在哪里呢?主要是破壞全局作用域啦,怎么怎么,但是如果這些文件里面都是按照我們規定的模塊格式寫,好像也沒有什么在全局作用域的……,好吧。

算了,我們還是用最簡單的方式了,就是動態創建script標簽,然后設置src,添加到document.head里,然后監聽它們的完成事件, 做后續操作。真的很簡單,因為我們的框架不需要考慮那么多種情況,不需要AMD,不需要require那么麻煩,用這框架的人必須按照這里的原則寫。

所以,說真的我們這里沒那么復雜啦,要是你們想看更詳細原理的不如去看這個,解釋得比我好哎:http://coolshell.cn/articles/9749.html#jtss-tsina

我也偷懶了,只是貼一下代碼,順便解釋一下,界面把所依賴的js文件路徑放在數組里,然后挨個創建script標簽,src設置為路徑,添加到 head中,監聽它們的完成事件。在這個完成時間里,我們要做這么一些事情:在fileMap里記錄當前js文件的路徑,防止以后重復加載,檢查列表中所 有文件,看看是否全部加載完了,如果全加載好了,就執行回調。

#p#

  1. require: function (pathArr, callback) { 
  2.     for (var i = 0; i < pathArr.length; i++) { 
  3.         var path = pathArr[i]; 
  4.  
  5.         if (!fileMap[path]) { 
  6.             var head = document.getElementsByTagName('head')[0]; 
  7.             var node = document.createElement('script'); 
  8.             node.type = 'text/javascript'
  9.             node.async = 'true'
  10.             node.src = path + '.js'
  11.             node.onload = function () { 
  12.                 fileMap[path] = true
  13.                 head.removeChild(node); 
  14.                 checkAllFiles(); 
  15.             }; 
  16.             head.appendChild(node); 
  17.         } 
  18.     } 
  19.  
  20.     function checkAllFiles() { 
  21.         var allLoaded = true
  22.         for (var i = 0; i < pathArr.length; i++) { 
  23.             if (!fileMap[pathArr[i]]) { 
  24.                 allLoaded = false
  25.                 break
  26.             } 
  27.         } 
  28.  
  29.         if (allLoaded) { 
  30.             callback(); 
  31.         } 
  32.     } 

1.4 小結

到此為止,我們的簡易框架的模塊定義系統就完成了。完整的代碼如下:

  1. (function () { 
  2.     var moduleMap = {}; 
  3.     var fileMap = {}; 
  4.  
  5.     var noop = function () { 
  6.     }; 
  7.  
  8.     var thin = { 
  9.         define: function(name, dependencies, factory) { 
  10.             if (!moduleMap[name]) { 
  11.                 var module = { 
  12.                     name: name, 
  13.                     dependencies: dependencies, 
  14.                     factory: factory 
  15.                 }; 
  16.  
  17.                 moduleMap[name] = module; 
  18.             } 
  19.  
  20.             return moduleMap[name]; 
  21.         }, 
  22.  
  23.         use: function(name) { 
  24.             var module = moduleMap[name]; 
  25.  
  26.             if (!module.entity) { 
  27.                 var args = []; 
  28.                 for (var i=0; i<module.dependencies.length; i++) { 
  29.                     if (moduleMap[module.dependencies[i]].entity) { 
  30.                         args.push(moduleMap[module.dependencies[i]].entity); 
  31.                     } 
  32.                     else { 
  33.                         args.push(this.use(module.dependencies[i])); 
  34.                     } 
  35.                 } 
  36.  
  37.                 module.entity = module.factory.apply(noop, args); 
  38.             } 
  39.  
  40.             return module.entity; 
  41.         }, 
  42.  
  43.         require: function (pathArr, callback) { 
  44.             for (var i = 0; i < pathArr.length; i++) { 
  45.                 var path = pathArr[i]; 
  46.  
  47.                 if (!fileMap[path]) { 
  48.                     var head = document.getElementsByTagName('head')[0]; 
  49.                     var node = document.createElement('script'); 
  50.                     node.type = 'text/javascript'
  51.                     node.async = 'true'
  52.                     node.src = path + '.js'
  53.                     node.onload = function () { 
  54.                         fileMap[path] = true
  55.                         head.removeChild(node); 
  56.                         checkAllFiles(); 
  57.                     }; 
  58.                     head.appendChild(node); 
  59.                 } 
  60.             } 
  61.  
  62.             function checkAllFiles() { 
  63.                 var allLoaded = true
  64.                 for (var i = 0; i < pathArr.length; i++) { 
  65.                     if (!fileMap[pathArr[i]]) { 
  66.                         allLoaded = false
  67.                         break
  68.                     } 
  69.                 } 
  70.  
  71.                 if (allLoaded) { 
  72.                     callback(); 
  73.                 } 
  74.             } 
  75.         } 
  76.     }; 
  77.  
  78.     window.thin = thin; 
  79. })(); 

測試代碼如下:

  1. thin.define("constant.PI", [], function() { 
  2.     return 3.14159; 
  3. }); 
  4.  
  5. thin.define("shape.Circle", ["constant.PI"], function(pi) { 
  6.     var Circle = function(r) { 
  7.         this.r = r; 
  8.     }; 
  9.  
  10.     Circle.prototype = { 
  11.         area : function() { 
  12.             return pi * this.r * this.r; 
  13.         } 
  14.     } 
  15.  
  16.     return Circle; 
  17. }); 
  18.  
  19. thin.define("shape.Rectangle", [], function() { 
  20.     var Rectangle = function(l, w) { 
  21.         this.l = l; 
  22.         this.w = w; 
  23.     }; 
  24.  
  25.     Rectangle.prototype = { 
  26.         area: function() { 
  27.             return this.l * this.w; 
  28.         } 
  29.     }; 
  30.  
  31.     return Rectangle; 
  32. }); 
  33.  
  34. thin.define("ShapeTypes", ["shape.Circle""shape.Rectangle"], function(Circle, Rectangle) { 
  35.     return { 
  36.         CIRCLE: Circle, 
  37.         RECTANGLE: Rectangle 
  38.     }; 
  39. }); 
  40.  
  41. thin.define("ShapeFactory", ["ShapeTypes"], function(ShapeTypes) { 
  42.     return { 
  43.         getShape: function(type) { 
  44.             var shape; 
  45.  
  46.             switch (type) { 
  47.                 case "CIRCLE": { 
  48.                     shape = new ShapeTypes[type](arguments[1]); 
  49.                     break
  50.                 } 
  51.                 case "RECTANGLE":  { 
  52.                     shape = new ShapeTypes[type](arguments[1], arguments[2]); 
  53.                     break
  54.                 } 
  55.             } 
  56.  
  57.             return shape; 
  58.         } 
  59.     }; 
  60. }); 
  61.  
  62. var ShapeFactory = thin.use("ShapeFactory"); 
  63. alert(ShapeFactory.getShape("CIRCLE", 5).area()); 
  64. alert(ShapeFactory.getShape("RECTANGLE", 3, 4).area()); 

在這個例子里定義了四個模塊,每個模塊只需要定義自己所直接依賴的模塊,其他的可以不必定義。也可以來這里看測試鏈接:http://xufei.github.io/thin/demo/demo.0.1.html

原文鏈接:http://www.ituring.com.cn/article/48461

責任編輯:陳四芳 來源: 圖靈社區
相關推薦

2013-07-11 10:03:36

JavaScript框架

2023-12-05 13:10:00

ReflexPython

2022-09-01 10:46:02

前端組件庫

2015-11-17 16:11:07

Code Review

2019-01-18 12:39:45

云計算PaaS公有云

2018-04-18 07:01:59

Docker容器虛擬機

2024-12-06 17:02:26

2020-07-02 15:32:23

Kubernetes容器架構

2016-11-02 14:18:45

搭建論壇Flask框架

2016-11-02 13:33:43

2013-09-11 09:37:17

企業級移動應用

2011-04-19 13:32:01

jQueryjavascript

2018-09-14 17:16:22

云計算軟件計算機網絡

2010-05-26 17:35:08

配置Xcode SVN

2024-05-15 14:29:45

2020-02-11 16:49:24

React前端代碼

2018-08-20 08:15:50

編程語言Go語言切片

2021-12-30 09:10:28

游戲開發開發技術熱點

2015-10-15 14:16:24

2024-04-10 07:48:41

搜索引擎場景
點贊
收藏

51CTO技術棧公眾號

亚洲一区二区三区乱码aⅴ| 久久久精品免费视频| 黄在线观看网站| 成人在线二区| 国产成人综合亚洲网站| 91成人免费观看网站| 国产精品麻豆一区| 免费成人三级| 在线电影一区二区三区| 美女av免费观看| 成人高清在线| 91在线观看视频| 成人国产精品一区| 国产99久久久| 精品1区2区3区4区| 日韩中文在线观看| 美女又爽又黄视频毛茸茸| **日韩最新| 色屁屁一区二区| 日韩中文字幕在线免费| 一广人看www在线观看免费视频| 成人激情小说乱人伦| 国产欧美日韩中文字幕在线| 亚洲伊人成人网| 欧美日韩mv| 久久精品国产91精品亚洲| 亚洲区免费视频| 红杏aⅴ成人免费视频| 777午夜精品免费视频| 欧在线一二三四区| 黄色18在线观看| 一区二区三区四区不卡在线| 在线看成人av电影| av电影在线播放高清免费观看| aaa亚洲精品| 国产经品一区二区| 国产99对白在线播放| 老司机午夜精品| 国产精品麻豆va在线播放| 中文字幕视频网站| 一本久道综合久久精品| 久久久久久久久久久av| 精品国产乱码久久久久久鸭王1 | 久久午夜精品视频| 蜜桃一区二区三区| 精品偷拍一区二区三区在线看| 俄罗斯黄色录像| a看欧美黄色女同性恋| 日韩三级精品电影久久久| 性生活一级大片| 日韩中文一区二区| 91麻豆精品国产91久久久久| 午夜视频在线网站| 亚洲欧美一级| 欧美一级夜夜爽| 中文字幕一二三| 亚洲啊v在线免费视频| 日韩欧美国产系列| 成人区人妻精品一区二| 国产精品中文字幕制服诱惑| 亚洲福利视频在线| 日韩 中文字幕| 在线视频亚洲专区| 亚洲最新av在线网站| 九九九视频在线观看| 色综合狠狠操| 插插插亚洲综合网| 国产无遮挡又黄又爽在线观看| 99伊人成综合| 国产精品成人aaaaa网站| 午夜视频网站在线观看| 精品综合免费视频观看| 444亚洲人体| 免费看日韩av| 久久久不卡网国产精品二区| 亚洲国产婷婷香蕉久久久久久99| 日本在线免费看| 一区二区久久久久| 欧美性大战久久久久xxx| 日本一区二区三区视频在线| 欧美丰满美乳xxx高潮www| 亚洲熟女一区二区三区| 免费看成人哺乳视频网站| 中文字幕免费精品一区高清| 欧美黑人性猛交xxx| 狠狠色丁香久久综合频道| 国产91对白在线播放| 91精品国产综合久| 99精品欧美一区二区三区综合在线| 欧美一区国产一区| 成人影欧美片| 欧美性xxxx极品高清hd直播| 奇米视频888| 人妖一区二区三区| 久久久国产精品视频| 亚洲男人第一av| 狠狠色丁香久久婷婷综| 久久精品二区| 高清免费电影在线观看| 色综合天天综合网国产成人综合天| 中文字幕22页| 免费看成人吃奶视频在线| 欧美福利视频在线观看| 亚洲大尺度在线观看| 国产高清无密码一区二区三区| 欧美日韩在线一区二区三区| 成人影院在线观看| 精品婷婷伊人一区三区三| 国产艳妇疯狂做爰视频| 婷婷激情综合| 国产精品成人av性教育| 手机av在线免费观看| 亚洲欧美aⅴ...| 日日摸天天爽天天爽视频| 日本在线一区二区三区| 啊v视频在线一区二区三区 | 成人信息集中地| 国产美女一区| 国产不卡一区二区三区在线观看| 最新国产在线观看| 色乱码一区二区三区88| 日本三级日本三级日本三级极| 久久一区91| 国产成人精品日本亚洲| 污视频网站免费观看| 亚洲精品国产视频| 天堂av8在线| 日韩免费特黄一二三区| 国产精品久久久久久久久久| 亚洲 精品 综合 精品 自拍| 亚洲在线观看免费| 人妻精油按摩bd高清中文字幕| 水蜜桃久久夜色精品一区| 国产成人av在线播放| 污视频网站免费观看| 午夜精品久久久久久久久久久 | 久久精品无码一区二区三区| 国产精品裸体瑜伽视频| www.爱久久| 色中色综合影院手机版在线观看| 国产欧美日韩成人| 亚洲乱码一区二区三区在线观看| 日本高清久久久| 色乱码一区二区三区网站| 国产精品久久久久久久久免费看| 国产在线日本| 欧美色欧美亚洲另类二区| 国产18无套直看片| 精品无人区卡一卡二卡三乱码免费卡| 中文字幕在线亚洲三区| 9999精品免费视频| 欧美成人免费网| 亚洲爱爱综合网| 亚洲动漫第一页| 99精品一区二区三区无码吞精| 尤物精品在线| 免费久久久一本精品久久区| 成人美女视频| 色噜噜狠狠狠综合曰曰曰| 一级成人免费视频| 亚洲免费观看视频| fc2成人免费视频| 国产日韩综合| 日韩免费av一区二区三区| 欧美大陆国产| 欧美激情乱人伦| 色久视频在线播放| 欧美在线综合视频| 精品无码久久久久成人漫画| 成人综合在线观看| 日本成年人网址| 色综合久久网| 国产欧美日韩亚洲| 日本精品在线一区| 久久精品亚洲精品| 日本国产在线观看| 色域天天综合网| 黄色录像免费观看| 99精品在线免费| 三上悠亚av一区二区三区| 中文字幕一区二区三区久久网站| 国产高清一区二区三区| 欧美free嫩15| 欧美高清视频免费观看| 全色精品综合影院| 欧美一区二区精品| 天天干,天天干| 一区二区三区四区不卡在线 | 国产精品久久久久9999赢消| 国产精品国产精品国产专区不卡| 日韩欧美看国产| 国产激情视频一区| www.av网站| 大伊人狠狠躁夜夜躁av一区| 性欧美一区二区| 国产精品一区二区在线观看网站| 一女被多男玩喷潮视频| 日韩在线观看一区| 精品欧美一区二区久久久伦| 欧美伊人亚洲伊人色综合动图| 欧美激情欧美激情在线五月| 成人动漫在线播放| 亚洲第一网站男人都懂| 在线观看国产精品入口男同| 午夜精品久久久久久久蜜桃app| 亚洲精品91美女久久久久久久| 在线观看国产亚洲| 综合自拍亚洲综合图不卡区| 无码人妻aⅴ一区二区三区| 乱一区二区av| 看av免费毛片手机播放 | 亚洲区一区二区三区| 极品国产人妖chinesets亚洲人妖| 成人av色在线观看| 色老太综合网| 2019日本中文字幕| 中文字幕在线三区| 日韩亚洲第一页| 国产在线色视频| 精品在线欧美视频| 熟妇高潮一区二区三区| 日韩欧美国产午夜精品| 国产又粗又黄又爽| 欧美性色欧美a在线播放| 欧美日韩精品区| 亚洲一区二区三区四区中文字幕 | 九色网友自拍视频手机在线| 精品成人私密视频| 国产丰满果冻videossex| 欧美日韩aaa| 在线播放成人av| 在线视频欧美精品| 少妇太紧太爽又黄又硬又爽| 亚洲成国产人片在线观看| 青青草原在线免费观看视频| 亚洲天天做日日做天天谢日日欢| www.99re6| 日韩美女视频一区| 亚洲综合视频网站| 国产精品免费观看视频| 亚洲天堂最新地址| 国产精品网站在线| 可以免费看av的网址| 国产精品区一区二区三区| 亚洲欧美日韩第一页| 国产精品乱码一区二区三区软件| x88av在线| 国产精品婷婷午夜在线观看| 999福利视频| 18成人在线观看| 一区视频免费观看| 亚洲精品国产成人久久av盗摄 | 欧美丝袜一区二区| 国产www在线| 日本久久精品电影| 中文在线观看免费高清| 欧美人妇做爰xxxⅹ性高电影| 在线播放一级片| 日韩欧美成人午夜| 午夜视频在线免费播放| 亚洲日本中文字幕免费在线不卡| 国产中文字幕在线看| 色av中文字幕一区| 手机在线免费av| 51精品国产黑色丝袜高跟鞋| 日韩精选视频| 成人性生交大片免费看小说 | 久久99久久精品欧美| a级大片免费看| 91网站在线观看视频| 欧美激情亚洲色图| 亚洲精品乱码久久久久久黑人| 国产主播在线播放| 色哦色哦哦色天天综合| 国产精品无码白浆高潮| 亚洲最新视频在线播放| 国产精品不卡av| 色诱视频网站一区| 中文字幕观看在线| 91精品国产一区二区三区香蕉| 国产精品欧美亚洲| 欧美精品一区二区三区很污很色的| 亚洲欧美丝袜中文综合| 中文字幕日本精品| 精精国产xxxx视频在线中文版 | 亚洲二区在线播放| 亚洲一区二区视频在线| 成人小视频在线播放| 欧美一区二区三区不卡| 亚洲麻豆一区二区三区| 黄色在线看片| 欧美精品在线播放| 一区一区三区| 97se视频在线观看| 欧美日韩一区二区三区视频播放| 肉大捧一出免费观看网站在线播放 | 国产精品热久久| 精品国产乱码91久久久久久网站| 日本加勒比一区| 这里只有精品视频在线| av影院在线| 国产精品自拍偷拍| 图片婷婷一区| 国产免费内射又粗又爽密桃视频| 日韩av在线播放中文字幕| 岛国大片在线免费观看| 国产欧美日韩中文久久| 日韩欧美中文字幕一区二区| 欧美日韩午夜在线视频| 三级视频网站在线| 欧美激情性做爰免费视频| 国产亚洲人成a在线v网站 | 中文字幕剧情在线观看| 91蜜桃网址入口| 国产又黄又爽又无遮挡| 在线观看www91| 亚洲aaa在线观看| 久久久在线观看| 9999精品| 一级特黄录像免费播放全99| 久久国产精品久久w女人spa| 国产高潮视频在线观看| 亚洲毛片av在线| 国产精品无码久久av| 中文字幕综合一区| 亚洲mmav| 久久本道综合色狠狠五月| 先锋资源久久| 欧美亚洲日本在线观看| 91在线看国产| 99精品在线播放| 欧美成人高清电影在线| www.欧美日本韩国| 91九色蝌蚪国产| 先锋资源久久| 杨幂一区二区国产精品| 亚洲青青青在线视频| 国产又黄又猛又爽| 日韩综合中文字幕| 在线成人免费| 99亚洲精品视频| 国产精一区二区三区| 免费中文字幕在线| 精品少妇一区二区三区免费观看 | 国产精品视频精品| 欧美综合在线视频观看| 亚洲欧美久久久久| 亚洲欧洲国产专区| 99久久精品免费看国产交换| 久久这里有精品| 中文字幕av一区二区三区四区| 久久久久久久久久伊人| 国产传媒日韩欧美成人| 国产亚洲小视频| 亚洲国产成人久久| 综合日韩av| 亚洲国产精品久久久久久女王| 开心九九激情九九欧美日韩精美视频电影| 国产午夜精品福利视频| 欧美日本一道本| 尤物在线网址| 精品蜜桃一区二区三区| 美女久久网站| 波兰性xxxxx极品hd| 日韩精品中午字幕| 老司机深夜福利在线观看| 欧美另类高清视频在线| 麻豆精品国产91久久久久久| 欧美性猛交xxxxx少妇| 精品国产电影一区二区| 韩日成人影院| 中文字幕精品—区二区日日骚| 国产精一区二区三区| 91porny在线| www.日韩.com| 国产精品成人自拍| 99视频免费播放| 亚洲欧美区自拍先锋| 五月天婷婷视频| 国产欧美日韩视频| 亚洲日本黄色| 国产馆在线观看| 欧美精品一区二区三区在线播放 | 久久久久亚洲AV成人无在| 欧美一区二区三区婷婷月色| 国产v日韩v欧美v| 在线视频91| 99re热这里只有精品视频| 伊人22222| 高清欧美性猛交xxxx黑人猛交| 精品日韩一区| 四虎永久免费观看| 欧美自拍偷拍一区| 青青青草视频在线| 午夜精品一区二区在线观看| 国产a级毛片一区| 自拍偷拍福利视频| 97精品国产91久久久久久| 久久资源中文字幕| 蜜桃精品成人影片|