国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

iOS Native與JavaScript交互

移動(dòng)開發(fā)
說到 Native 與 JS 做交互,就不得不提一嘴 HyBird Mobile App。Hybird 的翻譯結(jié)果并不是很文明(擦汗,不知道為啥很多翻譯軟件會(huì)譯為“雜種”,但我更喜歡將它翻譯為“混合、混血”),Hybird App 我對(duì)它的理解為通過 Web 網(wǎng)絡(luò)技術(shù)(如 HTML,CSS 和 JavaScript)與 Native 相結(jié)合的混合移動(dòng)應(yīng)用程序。

說到 Native 與 JS 做交互,就不得不提一嘴 HyBird Mobile App。

Hybird 的翻譯結(jié)果并不是很文明(擦汗,不知道為啥很多翻譯軟件會(huì)譯為“雜種”,但我更喜歡將它翻譯為“混合、混血”),Hybird App 我對(duì)它的理解為通過 Web 網(wǎng)絡(luò)技術(shù)(如 HTML,CSS 和 JavaScript)與 Native 相結(jié)合的混合移動(dòng)應(yīng)用程序。

那么我們來看一下 Hybird 對(duì)比 Native 有哪些優(yōu)劣:

iOS Native與JavaScript交互

因?yàn)?Hybird 的靈活性(更改 Web 頁面內(nèi)的 JS 就可以直接生效不必重新發(fā)版)以及通用性(一份 H5 玩遍公眾號(hào)、Android、iOS)再加上門檻低(前端玩家過來可以無痛上手開擼)的優(yōu)勢(shì),所以在非核心功能模塊使用 Web 通過 Hybird 的方式實(shí)現(xiàn)可能從各方面都會(huì)稍微好一些。而 Native 則可以在核心功能和設(shè)備硬件的調(diào)用上為 JS 提供強(qiáng)有力的支持。

雖然現(xiàn)在很多技術(shù)如 RN 和 Weex 等通過 JS 直接寫 Native 的技術(shù)出現(xiàn),對(duì) Hybird App 沖擊很大。但是由于 Hybird 技術(shù)門檻低(幾乎無學(xué)習(xí)成本)等原因,國(guó)內(nèi)很多公司包括大廠依舊沒有完全拋棄它,畢竟合適的才是***的!

Hybird 的發(fā)展史

H5 發(fā)布

Html5 是在 2014 年 9 月份正式發(fā)布的,這一次的發(fā)布做了一個(gè)***的改變就是“從以前的 XML 子集升級(jí)成為一個(gè)獨(dú)立集合”。

[[206753]]

H5 滲入 Mobile App 開發(fā)

Native APP 開發(fā)中有一個(gè) webview 的組件(Android 中是 webview,iOS 有 UIWebview和 WKWebview),這個(gè)組件可以加載 Html 文件。

在 H5 大行其道之前,webview 加載的 web 頁面單調(diào)(因?yàn)橹荒芗虞d一些靜態(tài)資源)。可自打 H5 火了之后,在很多仿生框架的幫助下,前端玩家們開發(fā)的 H5 頁面在 webview 中的體驗(yàn)不俗使得 H5 開發(fā)慢慢滲透到了 Mobile App 開發(fā)中來。

Hybird 的現(xiàn)狀

雖然目前已經(jīng)出現(xiàn)了 RN 和 Weex 這些 JS 寫 Native 的技術(shù),但是 Hybird 依舊沒有被淘汰。市面上絕大多說應(yīng)用都不同程度的引用了 Web 頁面,Web 頁面中的 JS 與 Native 如何交互依然是每個(gè) iOS 猿必須掌握的技能。

JavaScriptCore

不好意思,在進(jìn)入正題之前,容我再 BB 一下。JavaScriptCore 這個(gè)庫是 Apple 在 iOS 7 之后加入的,它對(duì) iOS Native 與 JS 做交互調(diào)用產(chǎn)生了劃時(shí)代的影響。

JavaScriptCore 大體是由 4 個(gè)類以及 1 個(gè)協(xié)議組成的:

iOS Native與JavaScript交互

  • JSContext 是 JS 執(zhí)行上下文,你可以把它理解為 JS 運(yùn)行的環(huán)境
  • JSValue 是對(duì) JavaScript 值的引用,任何 JS 中的值都可以被包裝為一個(gè) JSValue
  • JSManagedValue 是對(duì) JSValue 的包裝,加入了“conditional retain”
  • JSVirtualMachine 表示 JavaScript 執(zhí)行的獨(dú)立環(huán)境

還有 JSExport 協(xié)議:

實(shí)現(xiàn)將 Objective-C 類及其實(shí)例方法,類方法和屬性導(dǎo)出為 JavaScript 代碼的協(xié)議。

這里的 JSContext,JSValue,JSManagedValue 相對(duì)比較好理解,下面我們把 JSVirtualMachine 單拎出來說明一下:

JSVirtualMachine 的用法和其與 JSContext 的關(guān)系

iOS Native與JavaScript交互

官方文檔的介紹:

JSVirtualMachine 實(shí)例表示用于 JavaScript 執(zhí)行的獨(dú)立環(huán)境。 您使用此類有兩個(gè)主要目的:支持并發(fā) JavaScript 執(zhí)行,并管理 JavaScript 和 Objective-C 或 Swift 之間橋接的對(duì)象的內(nèi)存。

關(guān)于 JSVirtualMachine 的使用,一般情況下我們不用手動(dòng)去創(chuàng)建 JSVirtualMachine。因?yàn)楫?dāng)我們獲取 JSContext 時(shí),獲取到的 JSContext 從屬與一個(gè) JSVirtualMachine。

每個(gè) JavaScript 上下文(JSContext 對(duì)象)都屬于一個(gè) JSVirtualMachine。 每個(gè) JSVirtualMachine 可以包含多個(gè)上下文,允許在上下文之間傳遞值(JSValue 對(duì)象)。 但是,每個(gè) JSVirtualMachine 是不同的 - 您不能將在一個(gè) JSVirtualMachine 中創(chuàng)建的值傳遞到另一個(gè) JSVirtualMachine 中的上下文。

JavaScriptCore API 是線程安全的 - 例如,您可以從任何線程創(chuàng)建 JSValue 對(duì)象或運(yùn)行 JS 腳本 - 但是,嘗試使用相同 JSVirtualMachine 的所有其他線程將被阻塞。 要在多個(gè)線程上同時(shí)運(yùn)行(并發(fā)) JavaScript 腳本,請(qǐng)為每個(gè)線程使用單獨(dú)的 JSVirtualMachine 實(shí)例。

JSValue 與 JavaScript 的轉(zhuǎn)換表

iOS Native與JavaScript交互

iOS 與 JS 交互

對(duì)于 iOS Native 與 JS 做交互我們先從調(diào)用方向上分為兩種情況來看:

  • JS 調(diào)用 iOS Native
  • iOS Native 調(diào)用 JS

iOS Native與JavaScript交互

JS 調(diào)用 iOS Native

其實(shí) JS 調(diào)用 iOS Native 也分為兩種實(shí)現(xiàn)方式:

  • 假 Request 方法
  • JavaScriptCore 方法

假 Request 方法

原理:其實(shí)這種方式就是利用了 webview 的代理方法,在 webview 開始請(qǐng)求的時(shí)候截獲請(qǐng)求,判斷請(qǐng)求是否為約定好的假請(qǐng)求。如果是假請(qǐng)求則表示是 JS 想要按照約定調(diào)用我們的 Native 方法,按照約定去執(zhí)行我們的 Native 代碼就好。

UIWebView

UIWebView 代理用于截獲請(qǐng)求的代理函數(shù),在里面做判斷就好:

 

  1. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { 
  2.     NSURL *url = request.URL; 
  3.     // 與約定好的函數(shù)名作比較 
  4.     if ([[url scheme] isEqualToString:@"your_func_name"]) { 
  5.         // just do it 
  6.     } 

WKWebView

WKWebView 有兩個(gè)代理,一個(gè)是 WKNavigationDelegate,另一個(gè)是 WKUIDelegate。我們需要設(shè)置并實(shí)現(xiàn)它的 WKNavigationDelegate 方法:

 

  1. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 
  2.     NSURL *url = navigationAction.request.URL; 
  3.     // 與約定好的函數(shù)名作比較 
  4.     if ([[url scheme] isEqualToString:@"your_func_name"]) { 
  5.         // just do it 
  6.         decisionHandler(WKNavigationActionPolicyCancel); 
  7.         return
  8.     } 
  9.      
  10.     decisionHandler(WKNavigationActionPolicyAllow); 

Note: decisionHandler 當(dāng)你的應(yīng)用程序決定是允許還是取消導(dǎo)航時(shí),要調(diào)用的塊。 該塊使用單個(gè)參數(shù),它必須是枚舉類型 WKNavigationActionPolicy 的常量之一。如果不調(diào)用 decisionHandler 會(huì)引起 crash。

這里補(bǔ)充一下 JS 段的代碼:

 

  1. function callNative(){ 
  2.     loadURL("your_func_name://xxx"); 

然后拿個(gè) button 標(biāo)簽用一下就好了:

  1. <button type="button" onclick="callNative()">Call Native!</button> 

Call Native!

其實(shí)這里有個(gè)實(shí)際的栗子來的,我之前寫過一篇文章,由于適配原因采取了假 Request 的方式也做到了解決問題。文章鏈接貼在這里 各位想看的可以移步去看一下哈。

JavaScriptCore 方法

iOS 7 有了 JavaScriptCore 專門用來做 iOS Native 與 JS 的交互。我們可以在 webview 完成加載之后獲取 JSContext,然后利用 JSContext 將 JS 中的對(duì)象引用過來用 Native 代碼對(duì)其作出響應(yīng):

 

  1. // 首先引入 JavaScriptCore 庫 
  2. #import<JavaScriptCore/JavaScriptCore.h> 
  3.  
  4. // 然后再 UIWebView 的完成加載的代理方法中 
  5. - (void)webViewDidFinishLoad:(UIWebView *)webView { 
  6.     // 獲取 JS 上下文 
  7.     jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 
  8.     // 做引用,將 JS 內(nèi)的元素引用過來解釋,比如方法可以解釋成 Block,對(duì)象也可以指向 OC 的 Native 對(duì)象哦 
  9.     jsContext[@"iosDelegate"] = self; 
  10.     jsContext[@"yourFuncName"] = ^(id parameter){ 
  11.         // 注意這里的線程默認(rèn)是 web 處理的線程,如果涉及主線程操作需要手動(dòng)轉(zhuǎn)到主線程 
  12.         dispatch_async(dispatch_get_main_queue(), ^{ 
  13.         // your code 
  14.         }); 
  15.     } 

而 JS 這邊代碼更簡(jiǎn)單了,干脆聲明一個(gè)不解釋的函數(shù)(約定好名字的),用于給 Native 做引用:

 

  1. var parameter = xxx;  
  2. yourFuncName(parameter); 

iOS Native 調(diào)用 JS

iOS Native 調(diào)用 JS 的實(shí)現(xiàn)方法也被 JavaScriptCore 劃分開來:

  • webview 直接注入 JS 并執(zhí)行
  • JavaScriptCore 方法

webview 直接注入 JS 并執(zhí)行

  • 在 iOS 平臺(tái),webview 有注入并執(zhí)行 JS 的 API。

UIWebView

UIWebView 有直接注入 JS 的方法:

 

  1. NSString *jsStr = [NSString stringWithFormat:@"showAlert('%@')", @"alert msg"];  
  2. [_webView stringByEvaluatingJavaScriptFromString:jsStr]; 

Note: 這個(gè)方法會(huì)返回運(yùn)行 JS 的結(jié)果( nullable NSString * ),它是一個(gè)同步方法,會(huì)阻塞當(dāng)前線程!盡管此方法不被棄用,但***做法是使用 WKWebView 類的 evaluateJavaScript:completionHandler:method 。

官方文檔:

The stringByEvaluatingJavaScriptFromString: method waits synchronously for JavaScript evaluation to complete. If you load web content whose JavaScript code you have not vetted, invoking this method could hang your app. Best practice is to adopt the WKWebView class and use its evaluateJavaScript:completionHandler: method instead.

WKWebView

不同于 UIWebView,WKWebView 注入并執(zhí)行 JS 的方法不會(huì)阻塞當(dāng)前線程。因?yàn)榭紤]到 webview 加載的 web content 內(nèi) JS 代碼不一定經(jīng)過驗(yàn)證,如果阻塞線程可能會(huì)掛起 App。

 

  1. NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')", @"北京市東城區(qū)南鑼鼓巷納福胡同xx號(hào)"]; 
  2. [_webview evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) { 
  3.     NSLog(@"%@----%@", result, error); 
  4. }]; 

Note: 方法不會(huì)阻塞線程,而且它的回調(diào)代碼塊總是在主線程中運(yùn)行。

官方文檔:

  • Evaluates a JavaScript string.
  • The method sends the result of the script evaluation (or an error) to the completion handler. The completion handler always runs on the main thread.

JavaScriptCore 方法

上面簡(jiǎn)單提到過 JavaScriptCore 庫提供的 JSValue 類,這里再提供一下官方文檔對(duì) JSValue 的介紹翻譯:

JSValue 實(shí)例是對(duì) JavaScript 值的引用。 您可以使用 JSValue 類來轉(zhuǎn)換 JavaScript 和 Objective-C 或 Swift 之間的基本值(如數(shù)字和字符串),以便在本機(jī)代碼和 JavaScript 代碼之間傳遞數(shù)據(jù)。

不過你也看到了我貼在上面的 OC 和 JS 數(shù)據(jù)類型轉(zhuǎn)換表,那里面根本沒有限定為官方文檔所說的基本值。如果你不熟悉 JS 的話,我這里解釋一下為什么 JSValue 也可以指向 JS 中的對(duì)象和函數(shù),因?yàn)?JS 語言不區(qū)分基本值和對(duì)象以及函數(shù),在 JS 中“萬物皆為對(duì)象”。

好了下面直接 show code:

 

  1. // 首先引入 JavaScriptCore 庫 
  2. #import<JavaScriptCore/JavaScriptCore.h> 
  3.  
  4. // 先獲取 JS 上下文 
  5. self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 
  6. // 如果涉及 UI 操作,切回主線程調(diào)用 JS 代碼中的 YourFuncName,通過數(shù)組@[parameter] 入?yún)?nbsp;
  7. dispatch_async(dispatch_get_main_queue(), ^{ 
  8.     JSValue *jsValue = self.jsContext[@"YourFuncName"]; 
  9.     [jsValue callWithArguments:@[parameter]]; 
  10. }); 

上面的代碼調(diào)用了 JS 代碼中 YourFuncName 函數(shù),并且給函數(shù)加了 @[parameter] 作為入?yún)?。為了方便閱讀,這里再補(bǔ)充一下 JS 代碼:

 

  1. function YourFuncName(arguments){ 
  2.     var result = arguments; 
  3.     // do what u want to do 

WKWebView 與 JS 交互的特有方法

[[206755]]

關(guān)于 WKWebView 與 UIWebView 的區(qū)別就不在本文加以詳細(xì)說明了,更多信息還請(qǐng)自行查閱。這里要講的是 WKWebView 在與 JS 的交互時(shí)的特有方法:

  • WKUIDelegate 方法
  • MessageHandler 方法

WKUIDelegate 方法

對(duì)于 WKWebView 上文提到過,除了 WKNavigationDelegate,它還有一個(gè) WKUIDelegate,這個(gè) WKUIDelegate 是做什么用的呢?

WKUIDelegate 協(xié)議包含一些函數(shù)是監(jiān)聽 web JS 想要顯示 alert 或 confirm 時(shí)觸發(fā)的。我們?nèi)绻?WKWebView 中加載一個(gè) web 并且想要 web JS 的 alert 或 confirm 正常彈出,就需要實(shí)現(xiàn)對(duì)應(yīng)的代理方法。

Note: 如果沒有實(shí)現(xiàn)對(duì)應(yīng)的代理方法,則 webview 將會(huì)按照默認(rèn)操作去做出行為。

  • Alert: If you do not implement this method, the web view will behave as if the user selected the OK button.
  • Confirm: If you do not implement this method, the web view will behave as if the user selected the Cancel button.

我們這里就拿 alert 舉例,相信各位讀者可以自己舉一反三。下面是在 WKUIDelegate 監(jiān)聽 web 要顯示 alert 的代理方法用 Native UIAlertController 替代 JS 中的 alert 顯示的栗子 :

 

  1. - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { 
  2.     // 用 Native 的 UIAlertController 彈窗顯示 JS 將要提示的信息 
  3.     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert]; 
  4.     [alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { 
  5.         // 函數(shù)內(nèi)必須調(diào)用 completionHandler 
  6.         completionHandler(); 
  7.     }]]; 
  8.      
  9.     [self presentViewController:alert animated:YES completion:nil]; 

MessageHandler 方法

MessageHandler 是繼 Native 截獲 JS 假請(qǐng)求后另一種 JS 調(diào)用 Native 的方法,該方法利用了 WKWebView 的新特性實(shí)現(xiàn)。對(duì)比截獲假 Request 的方法來說,MessageHandler 傳參數(shù)更加簡(jiǎn)單方便。

MessageHandler 指什么?

WKUserContentController 類有一個(gè)方法:

  1. - (void)addScriptMessageHandler:(id )scriptMessageHandler name:(NSString *)name

該方法用來添加一個(gè)腳本處理器,可以在處理器內(nèi)對(duì) JS 腳本調(diào)用的方法做出處理,從而達(dá)到 JS 調(diào)用 Native 的目的。

那么 WKUserContentController 類和 WKWebView 有毛關(guān)系呢?

在 WKWebView 的初始化函數(shù)中有一個(gè)入?yún)?configuration,它的類型是 WKWebViewConfiguration。WKWebViewConfiguration 中包含一個(gè)屬性 userContentController,這個(gè) userContentController 就是 WKUserContentController 類型的實(shí)例,我們可以用這個(gè) userContentController 來添加不同名稱的腳本處理器。

iOS Native與JavaScript交互

MessageHandler 的坑

那么回到 - (void)addScriptMessageHandler:name: 方法上面,該方法添加一個(gè)腳本消息處理器(***個(gè)入?yún)? scriptMessageHandler),并且給這個(gè)處理器起一個(gè)名字(第二個(gè)入?yún)? name)。不過這個(gè)函數(shù)在使用的時(shí)候有個(gè)坑:scriptMessageHandler 入?yún)?huì)被強(qiáng)引用,那么如果你把當(dāng)前 WKWebView 所在的 UIViewController 作為***個(gè)入?yún)?,這個(gè) viewController 被他自己所持有的 webview.configuration. userContentController 所持有,就會(huì)造成循環(huán)引用。

iOS Native與JavaScript交互

一般我們通過 - (void)removeScriptMessageHandlerForName: 方法刪掉 userContentController 對(duì) viewController 的強(qiáng)引用。所以一般情況下我們的代碼會(huì)在 viewWillAppear 和 viewWillDisappear 成對(duì)兒的添加和刪除 MessageHandler:

 

  1. - (void)viewWillAppear:(BOOL)animated { 
  2.     [super viewWillAppear:animated]; 
  3.     [self.webview.configuration.userContentController addScriptMessageHandler:self name:@"YourFuncName"]; 
  4.  
  5. - (void)viewWillDisappear:(BOOL)animated { 
  6.     [super viewWillDisappear:animated]; 
  7.     [self.webview.configuration.userContentController removeScriptMessageHandlerForName:@"YourFuncName"]; 

WKScriptMessageHandler 協(xié)議

WKScriptMessageHandler 是腳本信息處理器協(xié)議,如果想讓一個(gè)對(duì)象具有腳本信息處理能力(比如上文中 webview 的所屬 viewController 也就是上面代碼的 self)就必須使其遵循該協(xié)議。

WKScriptMessageHandler 內(nèi)部簡(jiǎn)單的一匹,只有一個(gè)方法,我們必須要實(shí)現(xiàn)該方法(@required):

 

  1. // WKScriptMessageHandler 協(xié)議方法,在接收到腳本信息時(shí)觸發(fā) 
  2. - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { 
  3.     // message 有兩個(gè)屬性:name 和 body 
  4.     // message.name 可以用于區(qū)別要做的處理 
  5.     if ([message.name isEqualToString:@"YourFuncName"]) { 
  6.         // message.body 相當(dāng)于 JS 傳遞過來的參數(shù) 
  7.         NSLog(@"JS call native success %@", message.body); 
  8.     } 

老樣子,補(bǔ)充一下 JS 的代碼:

 

  1. // <name> 換 YourFuncName,<messageBody> 換你要的入?yún)⒓纯?nbsp;
  2. window.webkit.messageHandlers.<name>.postMessage(<messageBody>) 

搞定收工!

總結(jié)

  • 這篇文章簡(jiǎn)單的介紹了一下 Hybird Mobile App(其中還包括 Hybird 的發(fā)展簡(jiǎn)史)。
  • 介紹了 JavaScriptCore 的組成,并且把很多文章沒有講清楚的 JSVirtualMachine 與 JSContext 和 JSValue 之間的關(guān)系用圖片的形式表述出來。(JSVirtualMachine 包含 JSContext 包含 JSValue,都是 1 對(duì) n 的關(guān)系,且由于同一個(gè) JSVirtualMachine 下的代碼會(huì)相互阻塞,所以如果想異步執(zhí)行交互需要在不同的線程聲明 JSVirtualMachine 并發(fā)執(zhí)行)
  • 從調(diào)用方向的角度把 JS 與 iOS Native 相互調(diào)用的方式方法分別用代碼講解了一遍。
  • ***補(bǔ)充了 WKWebView 與 JS 交互特有的方法:WKUIDelegate 和 MessageHandler。

如果您覺得我的文章表述錯(cuò)誤請(qǐng)您予以指正,您的指正將會(huì)讓我避免誤導(dǎo)很多人。

責(zé)任編輯:未麗燕 來源: Lision
相關(guān)推薦

2012-04-23 11:00:56

iOS開發(fā)Objective-CJavaScript

2014-07-29 11:16:07

2011-08-04 09:47:33

iOS Objective- JavaScript

2010-08-10 17:01:48

FlexJavaScript

2010-07-30 12:56:02

Flex調(diào)用JavaS

2009-12-07 18:42:55

PHP與Javascr

2009-06-10 21:46:02

JavaScript與

2019-08-19 08:14:52

深度鏈接iOSAndroid

2016-08-12 08:49:46

React NativFacebookNative

2014-09-17 10:57:30

AndroidWebview安全交互

2016-08-15 13:34:37

React NativiOSjs入口

2009-06-30 15:05:52

JSP數(shù)據(jù)JavaScript數(shù)

2023-03-07 16:12:32

2011-09-05 14:53:57

JavaScript

2015-08-17 09:46:15

UIjs

2014-09-16 11:17:36

AndroidService交互方式

2011-06-13 09:04:39

QT Flash 交互

2009-07-01 14:42:30

JSP和XML

2010-07-23 14:51:09

OPhone開發(fā)

2022-05-25 10:47:01

淘寶開發(fā)模式
點(diǎn)贊
收藏

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

国产欧美亚洲日本| 玖玖玖免费嫩草在线影院一区| 色综合色狠狠综合色| 96av在线| 国产精品中文在线| 亚洲大片在线观看| 亚洲欧美小说色综合小说一区| 人九九综合九九宗合| 亚洲性色av| 亚洲男人av电影| 国产九一精品| 人人妻人人澡人人爽欧美一区| 国产精品二三区| av激情在线| 国产精品吴梦梦| 国产亚洲欧美日韩日本| 日本资源在线| 国产精品日韩欧美一区二区| 洋洋av久久久久久久一区| 国产精品香蕉| 亚洲一区三区视频在线观看| 欧美大片网站| 亚洲视频在线免费观看| 亚洲高清免费视频| 求av网址在线观看| 欧美高清激情视频| 天堂аⅴ在线最新版在线| 日韩一区二区在线观看| 欧美精品一区二区三区精品| 亚洲精品天堂成人片av在线播放| 日韩欧美一区二区三区| 国内欧美日韩| 中文字幕av久久| 91久久精品一区二区三区| 亚洲一区二区三区免费| 在线丝袜欧美日韩制服| 色94色欧美sute亚洲线路一ni| 国内精品免费| 天天看片激情网站| 成人在线精品视频| 天堂社区在线视频| 欧美日本一区二区三区四区| 成人性生交大片免费看96| 亚洲一区二区三区精品在线观看| 日本高清不卡一区| 国产精品久久久久久| 欧美国产视频一区二区| 2019国产精品| 国产精品第一国产精品| 自拍另类欧美| 亚洲偷欧美偷国内偷| 欧美bbbbb| 久草在线资源福利站| 影音先锋男人的网站| 亚洲美女性视频| 成人黄页毛片网站| 日韩三区免费| gogo久久| 好吊色欧美一区二区三区视频| 国产最新精品免费| bl视频在线免费观看| 黄色av网站在线看| 大伊香蕉精品视频在线| 中文字幕在线播放不卡一区| 日韩在线欧美在线国产在线| 欧美成人日韩| 天堂资源中文在线| 日韩精品免费看| 97久久超碰精品国产| 日韩大片在线免费观看| 传媒av在线| 日本一区高清不卡| 久久精品视频va| 亚洲人成人一区二区在线观看 | 97久久超碰国产精品| 久久久久久毛片免费看 | 久久久精品tv| 欧美日韩三区| 亚洲成人不卡| 黄色直播在线| 精品一区二区三区毛片| 国产剧情久久久久久| 国外成人在线直播| 精品日韩在线观看| 国产精品video| 香蕉av一区二区| 导航福利在线| 日本一区二区三区视频在线播放| 欧美日韩精品在线视频| 欧美综合国产| 国产一区二区三区四区五区传媒| 欧美草逼视频| 日本激情视频网| 老司机午夜网站| 91日韩在线播放| 97国产真实伦对白精彩视频8| 岛国av在线不卡| 91网址在线看| 卡一卡二国产精品| 在线免费观看日本欧美爱情大片| 一区二区免费| 亚洲精品大全| 婷婷六月国产精品久久不卡| 亚洲精品666| 成人福利免费网站| 久久久久久www| 一区高清视频| 亚洲精品免费在线视频| 18久久久久久| 九色91av视频| 九九久久精品一区| 日韩精品视频在线播放| 欧美在线free| 精品视频123区在线观看| 亚洲一区在线观看免费观看电影高清| 国产婷婷色一区二区三区四区| 韩国av一区二区| 国产成人自拍高清视频在线免费播放| 亚洲一区日本| 免费看欧美女人艹b| 男男视频亚洲欧美| 国产欧美午夜| 人人狠狠综合久久亚洲| 九一九一国产精品| 狠狠久久亚洲欧美| 99在线精品观看| 中文字幕一区二区三区精华液| 亚洲午夜久久久久久久久电影院| 欧美性猛交xxxx乱大交| 欧美久久一区二区| 日韩精品视频免费| 一区二区欧美亚洲| 欧美福利小视频| 青青草原成人在线视频| 国产日韩中文字幕在线| 欧美日韩一区在线视频| 手机在线视频你懂的| 妺妺窝人体色www在线观看| 国产宾馆自拍| 成人免费看片| 97色成人综合网站| 综合五月婷婷| 国产在线播放一区三区四| 久久久久久**毛片大全| 欧美在线视频你懂得| 亚洲区中文字幕| 欧美一区二区三区……| 图片区小说区区亚洲五月| 欧美xxxxx在线视频| 你懂的视频在线| 一区二区三区欧洲区| 亚洲性视频h| 欧美国产日韩亚洲一区| 在线这里只有精品| 57pao成人永久免费视频| 久久国产精品免费一区| 992kp快乐看片永久免费网址| 香蕉视频在线看| 亚州精品视频| 国产最新精品精品你懂的| 午夜久久久久久久久| 欧美精品18videos性欧美| 在线免费观看一区二区三区| 97超碰蝌蚪网人人做人人爽| 喷白浆一区二区| 欧美视频在线看| 久久99久国产精品黄毛片入口| 久久偷窥视频| 精品成人一区二区三区免费视频| 粉嫩av国产一区二区三区| 一区二区三区四区五区精品视频 | 日本道免费精品一区二区三区| 欧美极品在线播放| 亚洲黄色av网址| 久久精品亚洲成在人线av网址| 91丨porny丨中文| 波霸ol色综合久久| av日韩在线看| 国产精品久久久久久吹潮| 99re这里只有精品首页| 久精品免费视频| www.涩涩涩| 精品国产a一区二区三区v免费| 一区二区三区精品久久久| 午夜免费在线观看精品视频| 在线观看免费污视频| 亚洲免费福利一区| 精品av在线播放| 久久精品综合一区| 黄色激情在线播放| 九一在线视频| 成人三级网址| 精品综合久久88少妇激情| 少妇一区二区视频| 你懂的视频一区二区| 久久成人免费电影| 欧美香蕉大胸在线视频观看 | 国产麻豆精品95视频| 国产精品三级在线观看| 欧美精品一区男女天堂|