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

iOS Native與JavaScript交互

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

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

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

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

iOS Native與JavaScript交互

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

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

Hybird 的發(fā)展史

H5 發(fā)布

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

[[206753]]

H5 滲入 Mobile App 開(kāi)發(fā)

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

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

Hybird 的現(xiàn)狀

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

JavaScriptCore

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

JavaScriptCore 大體是由 4 個(gè)類(lèi)以及 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 類(lèi)及其實(shí)例方法,類(lèi)方法和屬性導(dǎo)出為 JavaScript 代碼的協(xié)議。

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

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

iOS Native與JavaScript交互

官方文檔的介紹:

JSVirtualMachine 實(shí)例表示用于 JavaScript 執(zhí)行的獨(dú)立環(huán)境。 您使用此類(lèi)有兩個(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 是線(xiàn)程安全的 - 例如,您可以從任何線(xiàn)程創(chuàng)建 JSValue 對(duì)象或運(yùn)行 JS 腳本 - 但是,嘗試使用相同 JSVirtualMachine 的所有其他線(xiàn)程將被阻塞。 要在多個(gè)線(xiàn)程上同時(shí)運(yùn)行(并發(fā)) JavaScript 腳本,請(qǐng)為每個(gè)線(xiàn)程使用單獨(dú)的 JSVirtualMachine 實(shí)例。

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

iOS Native與JavaScript交互

iOS 與 JS 交互

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

  • 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 開(kāi)始請(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ù),它必須是枚舉類(lèi)型 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í)際的栗子來(lái)的,我之前寫(xiě)過(guò)一篇文章,由于適配原因采取了假 Request 的方式也做到了解決問(wèn)題。文章鏈接貼在這里 各位想看的可以移步去看一下哈。

JavaScriptCore 方法

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

 

  1. // 首先引入 JavaScriptCore 庫(kù) 
  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)的元素引用過(guò)來(lái)解釋?zhuān)热绶椒梢越忉尦?nbsp;Block,對(duì)象也可以指向 OC 的 Native 對(duì)象哦 
  9.     jsContext[@"iosDelegate"] = self; 
  10.     jsContext[@"yourFuncName"] = ^(id parameter){ 
  11.         // 注意這里的線(xiàn)程默認(rèn)是 web 處理的線(xiàn)程,如果涉及主線(xiàn)程操作需要手動(dòng)轉(zhuǎn)到主線(xià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 劃分開(kāi)來(lái):

  • 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)前線(xiàn)程!盡管此方法不被棄用,但***做法是使用 WKWebView 類(lèi)的 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)前線(xiàn)程。因?yàn)榭紤]到 webview 加載的 web content 內(nèi) JS 代碼不一定經(jīng)過(guò)驗(yàn)證,如果阻塞線(xià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ì)阻塞線(xiàn)程,而且它的回調(diào)代碼塊總是在主線(xiàn)程中運(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)單提到過(guò) JavaScriptCore 庫(kù)提供的 JSValue 類(lèi),這里再提供一下官方文檔對(duì) JSValue 的介紹翻譯:

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

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

好了下面直接 show code:

 

  1. // 首先引入 JavaScriptCore 庫(kù) 
  2. #import<JavaScriptCore/JavaScriptCore.h> 
  3.  
  4. // 先獲取 JS 上下文 
  5. self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 
  6. // 如果涉及 UI 操作,切回主線(xiàn)程調(diào)用 JS 代碼中的 YourFuncName,通過(guò)數(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)ⅰ榱朔奖汩喿x,這里再補(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ì)說(shuō)明了,更多信息還請(qǐng)自行查閱。這里要講的是 WKWebView 在與 JS 的交互時(shí)的特有方法:

  • WKUIDelegate 方法
  • MessageHandler 方法

WKUIDelegate 方法

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

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

Note: 如果沒(méi)有實(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)聽(tīng) 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 的方法來(lái)說(shuō),MessageHandler 傳參數(shù)更加簡(jiǎn)單方便。

MessageHandler 指什么?

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

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

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

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

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

iOS Native與JavaScript交互

MessageHandler 的坑

那么回到 - (void)addScriptMessageHandler:name: 方法上面,該方法添加一個(gè)腳本消息處理器(***個(gè)入?yún)? scriptMessageHandler),并且給這個(gè)處理器起一個(gè)名字(第二個(gè)入?yún)? name)。不過(guò)這個(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交互

一般我們通過(guò) - (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 傳遞過(guò)來(lái)的參數(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 的組成,并且把很多文章沒(méi)有講清楚的 JSVirtualMachine 與 JSContext 和 JSValue 之間的關(guān)系用圖片的形式表述出來(lái)。(JSVirtualMachine 包含 JSContext 包含 JSValue,都是 1 對(duì) n 的關(guān)系,且由于同一個(gè) JSVirtualMachine 下的代碼會(huì)相互阻塞,所以如果想異步執(zhí)行交互需要在不同的線(xiàn)程聲明 JSVirtualMachine 并發(fā)執(zhí)行)
  • 從調(diào)用方向的角度把 JS 與 iOS Native 相互調(diào)用的方式方法分別用代碼講解了一遍。
  • ***補(bǔ)充了 WKWebView 與 JS 交互特有的方法:WKUIDelegate 和 MessageHandler。

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

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

2014-07-29 11:16:07

2012-04-23 11:00:56

iOS開(kāi)發(fā)Objective-CJavaScript

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

2016-08-15 13:34:37

React NativiOSjs入口

2014-09-17 10:57:30

AndroidWebview安全交互

2011-09-05 14:53:57

JavaScript

2009-06-30 15:05:52

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

2023-03-07 16:12:32

2015-08-17 09:46:15

UIjs

2014-09-16 11:17:36

AndroidService交互方式

2009-07-01 14:42:30

JSP和XML

2011-06-13 09:04:39

QT Flash 交互

2010-07-23 14:51:09

OPhone開(kāi)發(fā)

2022-05-16 11:17:01

應(yīng)用開(kāi)發(fā)JSJAVA
點(diǎn)贊
收藏

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

91精品国产91久久久久| 成人av影音| 国产蜜臀av在线一区二区三区| 国产精品日韩欧美综合| 日韩欧美国产成人精品免费| 精品午夜av| 欧美日韩另类在线| 永久域名在线精品| 天堂网在线资源| 日av在线不卡| 国外成人在线视频| 国产精品麻豆一区| 国产一级成人av| 欧美日韩日日夜夜| 无罩大乳的熟妇正在播放| 日韩黄色影院| 福利一区在线观看| 国产精品第一页在线| 久久老司机精品视频| 精品国产一级毛片| 亚洲国产精品专区久久| 天天影视色综合| 中文一区一区三区高中清不卡免费| 中文字幕日韩一区二区| 蜜桃传媒视频麻豆第一区免费观看 | 性生活黄色大片| 91久久亚洲| 日韩中文在线不卡| 一区二区三区四区免费| 9l视频自拍九色9l视频成人| 精品婷婷伊人一区三区三| 成人黄色av片| 女子免费在线观看视频www| 亚洲国产成人自拍| 欧美日韩精品不卡| 欧美自拍偷拍一区二区| 国产一区二区精品久久91| 国产精品主播视频| 一级黄色av片| 久久人人97超碰国产公开结果| 欧美激情一区二区三区久久久| 神马久久精品综合| 日韩精品诱惑一区?区三区| 亚洲欧美一区二区三区情侣bbw| 亚洲一区二区在线免费| 伊人www22综合色| 欧美成人精精品一区二区频| 午夜av中文字幕| 亚洲一区二区三区久久久| 欧美中文一区二区三区| 美女黄色片视频| **在线精品| 色乱码一区二区三区88| 成年人黄色片视频| 国产黄色一区二区| 日韩av电影天堂| 日韩免费观看网站| www.国产毛片| 石原莉奈在线亚洲二区| 国产z一区二区三区| 麻豆成人免费视频| 日韩综合在线视频| 国产精品亚洲激情| 国产精品一级视频| 国产不卡在线播放| 好吊色欧美一区二区三区视频| 日韩在线视频观看免费| 91免费观看视频| 久久人人九九| 成人性生交大片免费看午夜| 中文字幕 久热精品 视频在线| 亚洲v国产v在线观看| 欧美被日视频| 亚洲愉拍自拍另类高清精品| 婷婷无套内射影院| 欧美舌奴丨vk视频| 在线电影一区二区三区| 99免费观看视频| 亚洲动漫在线观看| 中文字幕亚洲自拍| 免费一级a毛片夜夜看| 国产精品一区亚洲| 国产精品视频精品视频| 亚洲av无码乱码国产精品久久| av电影在线观看完整版一区二区| 欧美日韩精品免费观看| 免费在线午夜视频| 亚洲成人激情自拍| 天天操天天摸天天爽| 动漫一区二区三区| 精品亚洲aⅴ在线观看| 中文字幕有码在线播放| 欧美日韩亚洲一区| 国产成人精品午夜| 国产夫妻自拍av| 久久久噜噜噜久噜久久综合| 天天爱天天做天天操| а√在线中文在线新版| 欧美日韩中文国产| 五十路六十路七十路熟婆| 成人羞羞网站入口| 久久久久久成人| 中文字幕在线视频免费| 成人午夜视频在线| 亚洲美女网站18| sm在线播放| 欧美精品v国产精品v日韩精品| 99久久久无码国产精品性波多 | 日本久久高清视频| 免费v片在线观看| 在线综合亚洲欧美在线视频| 88av在线播放| 亚洲网色网站| 国产精品扒开腿做爽爽爽视频| 精品久久久中文字幕人妻| 久久精品免视看| 欧美成人高潮一二区在线看| 日韩欧乱色一区二区三区在线| 日韩成人久久久| 青草草在线视频| 久久成人18免费观看| 欧美日韩亚洲在线| hd国产人妖ts另类视频| 欧美一区二区在线看| 中文字幕第24页| 久久大逼视频| 精品国产乱码久久久久久108| 中文字幕在线观看网站| 欧美色图天堂网| japanese中文字幕| 午夜亚洲一区| 另类视频在线观看+1080p| 蜜臀av国内免费精品久久久夜夜| 3d成人h动漫网站入口| 一级黄色毛毛片| 日日骚欧美日韩| 欧美日韩精品免费看| 日韩大片免费观看| 日韩av网站大全| 国产午夜福利片| 国产91高潮流白浆在线麻豆 | 欧产日产国产精品视频 | xxx中文字幕| 99精品在线观看| 成人激情春色网| 九色porny丨首页在线| 欧美日韩黄视频| 黄大色黄女片18免费| 丝袜美腿亚洲一区| 欧美久久久久久| 欧亚一区二区| 中文字幕欧美国内| 97caocao| 日韩一区在线免费观看| 欧美日韩中文不卡| 天天插综合网| 亚洲free性xxxx护士hd| 成人在线播放| 精品成人免费观看| 国产成人亚洲欧洲在线| 99re热视频这里只精品| 日日摸日日碰夜夜爽av| 视频国产一区| 国产精品视频久久| 91精品国产综合久久久久久豆腐| 欧美猛男超大videosgay| 国产精品丝袜一区二区| 国产超碰在线一区| 大陆极品少妇内射aaaaa| 在线日韩网站| 国产精品视频网| av激情在线| 精品成人一区二区| 岛国av中文字幕| 中文字幕av不卡| 老女人性生活视频| 国产欧美日本| 亚洲高清123| 国产一区二区三区免费观看在线| 欧美激情按摩在线| 久草在现在线| 91精品国产综合久久久久久漫画| 久久久久久久久久久久久久免费看 | 亚洲美女精品视频| 亚洲欧美日韩国产一区二区| 亚洲精品在线免费| 白白在线精品| 国产精品激情av在线播放 | 一区二区在线免费观看| 成人手机在线免费视频| 久久精品av麻豆的观看方式| 波多野结衣av一区二区全免费观看| 99香蕉久久| 国产精品免费小视频| 污视频网站在线免费| 亚洲精品一二区| 国产三级在线观看视频| 日韩欧美国产高清91| caoporn91| 久久久久久久网| 欧美一级大片免费看| 久久资源在线| 17c丨国产丨精品视频| 精品国产午夜| 国产自产精品| 麻豆一区在线| 国产精品一区二区三区久久 | 色综合久久久久| 超碰手机在线观看| 国产色婷婷亚洲99精品小说| 一二三区视频在线观看| 日本怡春院一区二区| 成人性生活视频免费看| 一级欧洲+日本+国产| 欧美一区亚洲二区| 久久黄色影视| 亚洲bt欧美bt日本bt| 国产精品99| 国产盗摄xxxx视频xxx69| 成人免费高清观看| 久久精品国产久精国产一老狼| 欧洲视频在线免费观看| 精品国产百合女同互慰| 国产美女明星三级做爰| 欧美日韩精品一区二区天天拍小说| 日韩精品手机在线| 亚洲国产视频直播| 欧美日韩国产精品综合| 亚洲图片你懂的| 99成人在线观看| 亚洲国产精品二十页| 日韩精品卡通动漫网站| eeuss影院一区二区三区| 麻豆av免费看| 国产高清久久久| 久久久久久久久久毛片| 捆绑调教美女网站视频一区| 成年人黄色片视频| 老司机精品导航| 精品一卡二卡三卡| 免费在线日韩av| 黄色动漫在线免费看| 亚洲深夜福利| 国产超级av在线| 久久久噜噜噜| 搡女人真爽免费午夜网站| 久久亚洲电影| 九色91popny| 免费在线观看视频一区| 欧美午夜性生活| 蜜桃av一区二区在线观看 | 成人一区在线观看| 2018国产精品| 成人97人人超碰人人99| 国产精品无码在线| 97久久精品人人做人人爽| 少妇饥渴放荡91麻豆| 91玉足脚交白嫩脚丫在线播放| a级一a一级在线观看| 91麻豆蜜桃一区二区三区| jlzzjizz在线播放观看| 久久久久久一二三区| 欧美黄色激情视频| 国产精品免费aⅴ片在线观看| 蜜桃视频最新网址| 亚洲免费视频成人| 国产午夜视频在线| 日韩欧美黄色动漫| 一二三区在线播放| 日韩欧美国产一区二区三区| 蜜臀久久99精品久久久| 日韩精品在线免费观看视频| 黄色大片在线免费观看| 日韩一级黄色av| 青春草在线视频| 欧洲亚洲免费在线| 国产欧美在线观看免费| 亚洲影院色无极综合| 久久影视三级福利片| 亚洲不卡中文字幕| 亚洲mv大片欧洲mv大片| 日韩精品―中文字幕| 奇米影视一区二区三区| 性生活在线视频| 久久这里只有精品6| 四虎影视1304t| 亚洲国产日韩av| 欧美一区二区三区久久久| 欧美一级在线免费| 免费在线国产| 成年人精品视频| 欧美大片免费高清观看| 91精品啪aⅴ在线观看国产| 免费观看成人www动漫视频| 欧美日韩国产一二| 欧美另类亚洲| 亚洲一二三区av| 成人午夜精品在线| 99久久精品久久亚洲精品| 亚洲国产精品久久艾草纯爱| 伊人免费在线观看| 亚洲国产精品成人av| 黄色成人在线观看| 日韩av不卡电影| 白嫩白嫩国产精品| 国产大尺度在线观看| 国产精品毛片| 中国男女全黄大片| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ原创 | 国产精品久久久久久av福利软件| 136导航精品福利| 亚洲午夜精品久久| 米奇777在线欧美播放| 中文字幕无码毛片免费看| 中文字幕二三区不卡| 欧美三级一区二区三区| 日韩欧美黄色影院| 蜜桃视频网站在线| 国产成人在线精品| 欧美交a欧美精品喷水| 日韩中文在线字幕| 麻豆精品久久久| 91成人破解版| 疯狂蹂躏欧美一区二区精品| 亚洲精品字幕在线观看| 久久视频精品在线| 韩国精品视频在线观看| 欧美色图亚洲自拍| 亚洲欧美春色| 中文字幕日韩三级片| 亚洲第一成人在线| 成人av无码一区二区三区| 欧美精品在线观看91| **日韩最新| 欧美aaa在线观看| 蜜桃av一区二区三区| 成人黄色短视频| 欧美性极品少妇| av在线中文| 国产精品久久久久久搜索| 狠狠做六月爱婷婷综合aⅴ| 久久美女福利视频| 久久网站热最新地址| 国产三级精品三级在线观看| 日韩av在线高清| 午夜影院在线观看国产主播| 久久一区二区精品| 久久精品人人| 欧美性受xxxx黑人| 欧美日韩午夜精品| 巨大荫蒂视频欧美另类大| 91免费观看网站| 神马影院午夜我不卡| 日韩精品乱码免费| 亚洲一级理论片| 欧美一区二区视频观看视频 | 婷婷久久一区| 色欲无码人妻久久精品| 一区二区三区在线免费| 亚洲成人一级片| 77777少妇光屁股久久一区| 岳的好大精品一区二区三区| 久久婷五月综合| 亚洲色图欧洲色图| 可以免费看毛片的网站| 欧美中文字幕在线视频| 欧美丝袜激情| 婷婷中文字幕在线观看| 亚洲国产毛片aaaaa无费看| 日韩欧美在线观看一区二区| 国产精品国产三级国产aⅴ浪潮 | av不卡一区| 国产99久久九九精品无码| 日本一区二区三级电影在线观看| 97成人在线观看| 久久久久久久久亚洲| 婷婷综合一区| 不卡的在线视频| 亚洲成a人片综合在线| 欧美777四色影视在线| 国产日产久久高清欧美一区| 国产精品www994| av在线网站观看| 777亚洲妇女| 一区二区乱码| 浴室偷拍美女洗澡456在线| 99热99精品| 国产麻豆91视频| 欧美性做爰毛片| 亚洲午夜精品一区 二区 三区| 精品夜夜澡人妻无码av| 9191久久久久久久久久久| 成人免费网站观看| 一区二区三区四区欧美| 91在线看国产| 国产又黄又粗又硬| 青青在线视频一区二区三区 | 国产精品va无码一区二区| 国产精品久久久久一区二区三区共| 天堂在线资源库|