整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript庫hxsfx.ajax之解決動態加載HTML

          最近寫博客真的是太痛苦了,倒不是寫博客本身,而是寫完之后往多個平臺發布的過程,一不注意就是十多分鐘往上的時間消耗。

          為了解決這個問題,之前立項的“解決自媒體一鍵多平臺發布”項目必須得立刻著手完善了,爭取早日讓自己從發布這件事情上解脫出來專心寫文章。

          【hxsfx的JavaScript庫】這個系列基本上是為“一鍵多平臺發布”項目打基礎用的。之所以把各個功能模塊拆分出來,是為了盡量讓小伙伴能夠復制即用(在兼容性方面,因為個人能力的原因,幾乎只會兼容Chrome瀏覽器)。


          hxsfx.ajax庫

          (一)介紹

          AJAX 是異步的 JavaScript 和 XML(Asynchronous JavaScript And XML),開發hxsfx.ajax庫的主要目的就是希望通過異步加載HTML,從而盡量避免直接在js中寫HTML來刷新頁面內容。

          hxsfx.ajax這個庫與jquery的ajax功能基本一致,不過短時間內應該是寫不到人家那么完善的。哈哈~

          各位小伙伴別問,為什么不用jquery的ajax而要自己再寫一個呢?

          問就是,博主喜歡造輪子。開玩笑了~

          其實原因是為了減少三方庫的依賴,達到對項目的全面掌控。

          項目地址:https://github.com/hxsfx/hxsfx_web_tools

          (二)代碼

          要自己開發一個ajax庫,需要借助Web API接口中的XMLHttpRequest(XHR)對象。

          XMLHttpRequest(XHR)對象用于與服務器交互。通過 XMLHttpRequest 可以在不刷新頁面的情況下請求特定 URL,獲取數據。這允許網頁在不影響用戶操作的情況下,更新頁面的局部內容。

          1、在window對象上新建一個hxsfx對象,本系列的所有庫基本都會在hxsfx對象之中:

          //hxsfx.js
          (function () {
              window.hxsfx = {};
          })();

          2、在hxsfx對象的基礎上新建一個ajax對象:

          //ajax.js
          (function () {
              window.hxsfx.ajax = {
              };
          })();

          3、在ajax對象中新建loadHTML方法,設置兩個參數,分別是ele準備加載HTML的容器元素和url加載HTML的地址:

          //ajax.js
          (function () {
              window.hxsfx.ajax = {
                  loadHTML: function (ele, url) {
                  }
              };
          })();

          4、在loadHTML方法中新建XMLHttpRequest對象:

          //ajax.js
          (function () {
              window.hxsfx.ajax = {
                  loadHTML: function (ele, url) {
                      const httpRequest = new XMLHttpRequest();
                      httpRequest.open('GET', url, true);
                      httpRequest.onreadystatechange = function () {
                          //為了讓代碼更健壯,使用try...catch來捕獲返回狀態判斷和處理HTML代碼的異常
                          try {
                              if (httpRequest.readyState === XMLHttpRequest.DONE) {
                                  if (httpRequest.status === 200) {
                                        //在這處理返回的HTML
                                      }
                                  }
                                  else {
                                      console.log("【ajax.get(" + url + ")請求出錯】");
                                  }
                              }
                          }
                          catch (ex) {
                              console.log("【ajax.get(" + url + ")異常】" + ex.message);
                          }
                      };
                      httpRequest.send();
                  }
              };
          })();

          5、為了解決加載HTML緩存的問題,將loadHTML方法中傳入的URL參數后面加上一個時間戳:

          //ajax.js
          //時間戳用來解決加載頁面緩存的問題
          var urlTimeStamp = "timeStamp=" + new Date().getTime();
          url += ((url.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;

          6、【重點】在這處理返回的HTML時,如果直接將HTML加載到容器中,會出現HTML中Javascript代碼不執行的問題。解決這個問題,需要將加載的script標簽替換為script元素:

          //ajax.js
          ele.innerHTML = httpRequest.responseText;
          var scriptElements = ele.getElementsByTagName("script");
          for (var i = 0; i < scriptElements.length; i++) {
              var scriptElement = document.createElement("script");
              scriptElement.setAttribute("type", "text/javascript");
              var src = scriptElements[i].getAttribute("src");
              if (src) {
                  //因為加載的src路徑是之前相對加載HTML頁面的,需要修改為當前頁面的引用路徑
                  src = url.substring(0, url.lastIndexOf('/') + 1)  + src;
                  src += ((src.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
                  scriptElement.setAttribute("src", src);
              }
              var scriptContent = scriptElements[i].innerHTML;
              if (scriptContent) {
                  scriptElement.innerHTML = scriptContent;
              }
              //用生成的script元素去替換html中的script標簽,以此來激活script代碼
              ele.replaceChild(scriptElement, scriptElements[i]);
          }

          7、最后ajax.js完整代碼:

          //ajax.js
          (function () {
              window.hxsfx.ajax = {
                  loadHTML: function (ele, url) {
                      //時間戳用來解決加載頁面緩存的問題
                      var urlTimeStamp = "timeStamp=" + new Date().getTime();
                      url += ((url.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
                      const httpRequest = new XMLHttpRequest();
                      httpRequest.open('GET', url, true);
                      httpRequest.onreadystatechange = function () {
                          //為了讓代碼更健壯,使用try...catch來捕獲返回狀態判斷和處理HTML代碼的異常
                          try {
                              if (httpRequest.readyState === XMLHttpRequest.DONE) {
                                  if (httpRequest.status === 200) {
                                      ele.innerHTML = httpRequest.responseText;
                                      var scriptElements = ele.getElementsByTagName("script");
                                      for (var i = 0; i < scriptElements.length; i++) {
                                          var scriptElement = document.createElement("script");
                                          scriptElement.setAttribute("type", "text/javascript");
                                          var src = scriptElements[i].getAttribute("src");
                                          if (src) {
                                              //因為加載的src路徑是之前相對加載HTML頁面的,需要修改為當前頁
                                              src = url.substring(0, url.lastIndexOf('/') + 1) + src;
                                              src += ((src.indexOf('?') >= 0) ? "&" : "?") + urlTimeStamp;
                                              scriptElement.setAttribute("src", src);
                                          }
                                          var scriptContent = scriptElements[i].innerHTML;
                                          if (scriptContent) {
                                              scriptElement.innerHTML = scriptContent;
                                          }
                                          //用生成的script元素去替換html中的script標簽,以此來激活script代
                                          ele.replaceChild(scriptElement, scriptElements[i]);
                                      }
                                      }
                                  }
                                  else {
                                      console.log("【ajax.get(" + url + ")請求出錯】");
                                  }
                              }
                          }
                          catch (ex) {
                              console.log("【ajax.get(" + url + ")異常】" + ex.message);
                          }
                      };
                      httpRequest.send();
                  }
              };
          })();

          (三)調用文檔

          1、將hxsfx.js和ajax.js放入Scripts文件夾中的hxsfx文件夾

          2、在Scripts文件夾同級目錄新建index.html頁面

          <!DOCTYPE html>
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
              <title>js庫測試</title>
              <script src="Scripts/hxsfx/hxsfx.js"></script>
              <script src="Scripts/hxsfx/ajax.js"></script>
              <script>
                  window.onload = function () {
                          //調用ajax中的loadHTML方法
                      window.hxsfx.ajax.loadHTML(document.getElementById("ContentContainer"), "Views/test/testPage.html");
                  };
              </script>
          </head>
          <body>
              <div id="ContentContainer"></div>
          </body>
          </html>

          3、在Scripts文件夾同級目錄,首先新建Views文件夾,接著其中新建test文件夾,最后在test文件夾中新建testPage.html

          <style>
              div#TestPageContainer {
                  height: 300px;
                  width: 300px;
                  background-color: #F0F0F0;
              }
          </style>
          <script src="../../Scripts/hxsfx/test/test.js"></script>
          <script>
              function updateBackgroundColor() {
                  try {
                      var backgroundColor = '#' + (Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0'));
                      document.getElementById("TestPageContainer").style.backgroundColor = backgroundColor;
                  }
                  catch (ex) {
                      console.log(ex.message);
                  }
              }
          </script>
          <div id="TestPageContainer">
              <button onclick="updateBackgroundColor()">更改背景色</button>
              <button onclick="modifyPFontColor()">更改下面一句話的字體顏色</button>
              <p id="P">這兒是一句話。</p>
          </div>


          最后

          以上內容只是hxsfx.ajax庫的開始,后續的內容更新小伙伴可以通過訪問Github項目地址進行獲取。

          ndroid高階開發專欄

          Java高級開發進階專欄

          TCP連接的三次握手和四次揮手

          一文搞懂DNS域名解析的詳細流程

          高并發與負載均衡:Nginx的反向代理和負載均衡

          一文搞懂TCP/IP協議及Web基礎知識

          一文搞懂HTTP協議的核心知識點

          一文掌握 HTTP協議報文 包含的信息類型

          一文搞懂HTTP協議 返回結果的HTTP狀態碼

          一文搞懂 HTTP協議的報文首部


          作為網絡專欄的開篇導文,本文概況介紹下經典案例:從輸入一個網址到瀏覽器顯示頁面的全過程。

          步驟概要介紹如下:

          • 1、輸入網址
          • 2、DNS解析獲取域名對應的IP地址
          • 3、建立TCP連接
          • 4、web瀏覽器向web服務器發送HTTP請求
          • 5、服務器的永久重定向響應
          • 6、瀏覽器跟蹤重定向地址
          • 7、web服務器做出應答
          • 8、瀏覽器顯示 HTML
          • 9、瀏覽器發送請求獲取其他嵌入在 HTML 中的資源
          • 10、web服務器關閉TCP連接

          1、輸入網址

          當在瀏覽器中輸入網址時,瀏覽器其實就已在智能匹配 url 了,他會從歷史記錄,書簽等地方,找到已經輸入的字符串可能對應的 url,然后給出智能提示,讓你可以補全url地址。

          對于 google的chrome 的瀏覽器,他甚至會直接從緩存中把網頁展示出來,就是說,你還沒有按下 enter,頁面就出來了。


          2、DNS解析獲取域名對應的IP地址

          請求一旦發起,瀏覽器首先要做的事情就是解析這個域名。

          • 1、一般來說,瀏覽器會首先查看本地硬盤的 hosts 文件,看看其中有沒有和這個域名對應的規則,如果有的話就直接使用 hosts 文件里面的 ip 地址。
          • 2、如果在本地的 hosts 文件沒有能夠找到對應的 ip 地址,瀏覽器會發出一個 DNS請求到本地DNS服務器 。本地DNS服務器一般都是你的網絡接入服務器商提供,比如中國電信,中國移動。
          • 3、查詢你輸入的網址的DNS請求到達本地DNS服務器之后,本地DNS服務器會首先查詢它的緩存記錄,如果緩存中有此條記錄,就可以直接返回結果,此過程是遞歸的方式進行查詢。如果沒有,本地DNS服務器還要向DNS根服務器進行查詢。
          • 4、根DNS服務器沒有記錄具體的域名和IP地址的對應關系,而是告訴本地DNS服務器,你可以到域服務器上去繼續查詢,并給出域服務器的地址。這種過程是迭代的過程。
          • 5、本地DNS服務器繼續向域服務器發出請求,在這個例子中,請求的對象是.com域服務器。.com域服務器收到請求之后,也不會直接返回域名和IP地址的對應關系,而是告訴本地DNS服務器,你的域名的解析服務器的地址。
          • 6、最后,本地DNS服務器向域名的解析服務器發出請求,這時就能收到一個域名和IP地址對應關系,本地DNS服務器不僅要把IP地址返回給用戶電腦,還要把這個對應關系保存在緩存中,以備下次別的用戶查詢時,可以直接返回結果,加快網絡訪問。


          3、建立TCP連接

          在HTTP工作開始之前,web瀏覽器首先要通過網絡與web服務器建立連接,該連接是通過TCP來完成的。

          PS1:為什么要先建立TCP呢?

          因為HTTP是比TCP更高層次的應用層協議,根據規則,只有低層協議建立之后才能進行更高層次協議的連接,因此要先建立TCP連接,一般TCP連接的端口號是80

          PS2:擴展知識點:

          TCP連接的三次握手和斷開的四次揮手 參照站內文章:TCP 三次握手和四次揮手


          4、web瀏覽器向web服務器發送HTTP請求

          建立了TCP連接之后,web瀏覽器就會向web服務器發起一個http請求。

          一個典型的 http request header 一般需要包括請求的方法,例如 GET 或者 POST 等,不常用的還有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的瀏覽器只能發起 GET 或者 POST 請求。

          客戶端向服務器發起http請求的時候,會有一些請求信息,請求信息包含三個部分:

          • 請求方法URI協議/版本
          • 請求頭(Request Header)
          • 請求正文:

          下面是一個完整的HTTP請求例子:

          GET/sample.jspHTTP/1.1
          Accept:image/gif.image/jpeg,*/*
          Accept-Language:zh-cn
          Connection:Keep-Alive
          Host:localhost
          User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
          Accept-Encoding:gzip,deflate
          
          username=jinqiao&password=1234

          4.1、請求行

          請求的第一行是“方法URL議/版本”:GET/sample.jsp HTTP/1.1

          4.2、請求頭(Request Header)

          請求頭包含許多有關的客戶端環境和請求正文的有用信息。例如,請求頭可以聲明瀏覽器所用的語言,請求正文的長度等。

          Accept:image/gif.image/jpeg.*/*
          Accept-Language:zh-cn
          Connection:Keep-Alive
          Host:localhost
          User-Agent:Mozila/4.0(compatible:MSIE5.01:Windows NT5.0)
          Accept-Encoding:gzip,deflate.
          

          4.3、請求正文

          請求頭和請求正文之間是一個空行,這個行非常重要,它表示請求頭已經結束,接下來的是請求正文。請求正文中可以包含客戶提交的查詢字符串信息:

          username=jinqiao&password=1234

          5、服務器的永久重定向響應

          服務器給瀏覽器響應一個301永久重定向響應,這樣瀏覽器就會訪問“http://www.google.com/” 而非“http://google.com/”。

          為什么服務器一定要重定向而不是直接發送用戶想看的網頁內容呢?其中一個原因跟搜索引擎排名有關。如果一個頁面有兩個地址,就像http://www.yy.com/和http://yy.com/,搜索引擎會認為它們是兩個網站,結果造成每個搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有就是用不同的地址會造成緩存友好性變差,當一個頁面有好幾個名字時,它可能會在緩存里出現好幾次。

          重定向原因:

          • 1、網站調整(如改變網頁目錄結構);
          • 2、網頁被移到一個新地址;
          • 3、網頁擴展名改變(如應用需要把.php改成.Html或.shtml)。

          這種情況下,如果不做重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶得到一個404頁面錯誤信息,訪問流量白白喪失;再者某些注冊了多個域名的網站,也需要通過重定向讓訪問這些域名的用戶自動跳轉到主站點等。


          6、瀏覽器跟蹤重定向地址

          現在瀏覽器知道了 "http://www.google.com/"才是要訪問的正確地址,所以它會發送另一個http請求。這里沒有啥好說的


          7、web服務器做出應答

          經過前面的步驟,服務器收到了我們的請求,也處理我們的請求,到這一步,它會把它的處理結果返回,也就是返回一個HTPP響應。

          HTTP響應與HTTP請求相似,HTTP響應也由3個部分構成,分別是:

          • 狀態行
          • 響應頭(Response Header)
          • 響應正文
          HTTP/1.1 200 OK
          Date: Sat, 31 Dec 2005 23:59:59 GMT
          Content-Type: text/html;charset=ISO-8859-1
          Content-Length: 122
          
          <html>
          <head>
          <title>http</title>
          </head>
          <body>
          <!-- body goes here -->
          </body>
          </html>

          7.1、狀態行:

          狀態行由協議版本、數字形式的狀態代碼、及相應的狀態描述,各元素之間以空格分隔。

          格式: HTTP-Version Status-Code Reason-Phrase CRLF

          例如: HTTP/1.1 200 OK \r\n

          -- 協議版本:是用http1.0還是其他版本

          -- 狀態描述:狀態描述給出了關于狀態代碼的簡短的文字描述。比如狀態代碼為200時的描述為 ok

          -- 狀態代碼:狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。

          狀態代碼具體協議定義如下:

          1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。
          100 Continue
          101 Switching Protocols
          
          2xx:成功狀態碼,表示服務器已成功接收到請求并進行處理。
          200 OK 表示客戶端請求成功
          204 No Content 成功,但不返回任何實體的主體部分
          206 Partial Content 成功執行了一個范圍(Range)請求
          
          3xx:重定向狀態碼,表示服務器要求客戶端重定向。
          301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL
          302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源
          303 See Other 請求的資源存在著另一個URI,客戶端應使用GET方法定向獲取請求的資源
          304 Not Modified 服務器內容沒有更新,可以直接讀取瀏覽器緩存
          307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換為GET,但實際使用時并不一定,307則更多瀏覽器可能會遵循這一標準,但也依賴于瀏覽器具體實現
          
          4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。
          400 Bad Request 表示客戶端請求有語法錯誤,不能被服務器所理解
          401 Unauthonzed 表示請求未經授權,該狀態代碼必須與 WWW-Authenticate 報頭域一起使用
          403 Forbidden 表示服務器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因
          404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL
          
          5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。
          500 Internel Server Error 表示服務器發生不可預期的錯誤,導致無法完成客戶端的請求
          503 Service Unavailable 表示服務器當前不能夠處理客戶端的請求,在一段時間之后,服務器可能會恢復正常

          7.2、響應頭:

          響應頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號":"分隔。

          Date: Sat, 31 Dec 2005 23:59:59 GMT
          Content-Type: text/html;charset=ISO-8859-1
          Content-Length: 122

          典型的響應頭字段:

          7.3、響應正文

          包含著我們需要的一些具體信息,比如cookie,html,image,后端返回的請求數據等等。這里需要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格為止。


          8、瀏覽器顯示 HTML

          在瀏覽器沒有完整接受全部HTML文檔時,它就已經開始顯示這個頁面了,瀏覽器是如何把頁面呈現在屏幕上的呢?

          不同瀏覽器可能解析的過程不太一樣,這里我們只介紹webkit的渲染過程。下圖對應的就是WebKit渲染的過程,這個過程包括:

          解析html以構建dom樹 -> 構建render樹 -> 布局render樹 -> 繪制render樹:


          9、瀏覽器發送請求獲取嵌入在 HTML 中的資源(如圖片、音頻、視頻、CSS、JS等等)

          其實這個步驟可以并列在步驟8中,在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內容的標簽。這時,瀏覽器會發送一個獲取請求來重新獲得這些文件。比如我要獲取外圖片,CSS,JS文件等,類似于下面的鏈接:

          圖片:http://static.ak.fbcdn.net/rsrc.php/z12E0/hash/8q2anwu7.gif

          CSS式樣表:http://static.ak.fbcdn.net/rsrc.php/z448Z/hash/2plh8s4n.css

          JavaScript 文件:http://static.ak.fbcdn.net/rsrc.php/zEMOA/hash/c8yzb6ub.js

          這些地址都要經歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查找這些域名,發送請求,重定向等等...

          不像動態頁面,靜態文件會允許瀏覽器對其進行緩存。有的文件可能會不需要與服務器通訊,而從緩存中直接讀取,或者可以放到CDN中


          10、web服務器關閉TCP連接

          一般情況下,一旦web服務器向瀏覽器發送了請求數據后,它就要關閉TCP連接,然后如果瀏覽器或者服務器在其頭信息加入這行代碼:

          connection:keep-alive

          這樣TCP連接將依然保持打開狀態,瀏覽器可以繼續通過相同的連接發送請求,保持連接,節省了為每個請求建立新連接所需要的的事件,同時節省了寬帶

          實際上,在HTTP 1.1 版本的新特性中有一點是:默認持久連接節省通信量,只要客戶端、服務端任意一端沒有明確斷開TCP連接,可以發送多次HTTP請求。



          版權說明:摘錄到部分網絡資源,如存在版權問題,請私信聯系處理,謝謝!


          關注頭條號“編程家園”,后續陸續會有更多技術領域(包括并不限于Android進階、Java進階、Kotlin、網絡、Flutter、Python等),以及架構、職業規劃、職業思考等方面資料的免費分享,期待您的關注!

          . HTML解析

          • 當瀏覽器開始加載HTML文檔時,它會從上到下解析HTML文件。在解析過程中,瀏覽器會構建DOM(文檔對象模型)樹。

          2. 遇到外部鏈接(CSS、JavaScript)

          • 當解析器遇到外部CSS鏈接(<link>標簽)時,它通常會停止DOM構建,等待CSS文件下載并解析完成,因為CSS可能影響后續DOM元素的渲染。
          • 當解析器遇到傳統的JavaScript腳本(<script>標簽)時,它也會停止DOM構建,等待腳本下載和執行完成,因為腳本可能會修改DOM。

          3. defer async

          • defer屬性:用于<script>標簽,指示瀏覽器應該在繼續構建DOM的同時異步下載腳本,但延遲執行直到整個文檔解析完成。所有帶defer的腳本將在DOMContentLoaded事件之前按順序執行。
          • async屬性:也用于<script>標簽,指示瀏覽器異步下載腳本,并在腳本下載完成后立即執行,而不用等待HTML文檔解析完成。async腳本的執行順序不能保證。

          4. DOMContentLoaded事件

          • 當HTML文檔被完全加載和解析時,不包括樣式表、圖片和iframe的加載,DOMContentLoaded事件將被觸發。
          • 如果腳本有defer屬性,它們將在DOMContentLoaded事件之前按順序執行。

          5. 其他資源的加載

          • 在DOMContentLoaded事件之后,瀏覽器會繼續加載頁面上的其他資源(如圖片、樣式表、iframe等)。

          6. onload事件

          • 當文檔及其所有依賴資源(如樣式表和圖片)完全加載后,window對象的onload事件將被觸發。
          • 這標志著整個頁面的加載過程結束。

          7. JavaScript執行

          • 在整個文檔解析過程中,JavaScript(無論是內聯的還是通過<script>標簽引入的)可以被執行,具體取決于它的位置和是否使用了defer或async屬性。
          • 使用defer的腳本會在文檔解析結束后按順序執行,而async腳本則會在它們加載完成后盡快執行。

          注意

          • 使用async和defer可以提高頁面加載性能,因為它們允許HTML解析和腳本下載并行進行。
          • JavaScript腳本的放置位置(在<head>或<body>)也會影響加載和執行的時機。通常推薦將腳本放在<body>標簽的底部,以提高頁面加載性能。

          主站蜘蛛池模板: 日本无卡码免费一区二区三区| 中文字幕人妻AV一区二区| 精品国产高清自在线一区二区三区| 久久久久人妻一区精品性色av| 国产精品成人一区二区三区| 午夜天堂一区人妻| 国产欧美一区二区精品仙草咪| 国产精品香蕉一区二区三区| 亚洲丰满熟女一区二区哦| 日本一区中文字幕日本一二三区视频| 人妻无码一区二区三区AV| 国产精品va一区二区三区| 红杏亚洲影院一区二区三区| 精品无码人妻一区二区三区品| 精品亚洲av无码一区二区柚蜜| 亚洲AV色香蕉一区二区| 日韩精品一区二区午夜成人版 | 亚洲AV日韩精品一区二区三区| 福利一区二区三区视频在线观看 | 色综合久久一区二区三区| 中文字幕乱码人妻一区二区三区 | 亚洲综合一区二区| 亚洲国产精品一区二区第一页 | 久久亚洲日韩精品一区二区三区 | 精品国产福利一区二区| 一区二区三区中文| 日本精品高清一区二区| 亚洲综合一区二区精品久久| 一本大道在线无码一区| 国产成人高清亚洲一区久久| www一区二区三区| 国产精品一区二区无线| 久久久无码精品国产一区| 无码人妻视频一区二区三区| 99国产精品欧美一区二区三区 | 亚洲sm另类一区二区三区| 日韩精品一区二区三区老鸦窝| 日韩视频在线观看一区二区| 日本欧洲视频一区| 日韩免费无码一区二区三区| 无码人妻精品一区二区蜜桃AV|