在9012的最后一篇写到了在rn中安卓的webview的通讯原理,而做为0202年的第一篇,继续讨论上年rn中webview通讯剩下的部分。react
对于webview,了解过的人都知道在ios端会存在两种类型的webview(UIWebview和WKWebview),而他们之间的区别主要以下:ios
在ios中,应用层会设置rn中webview的某个属性,而weview会经过webview.iso.js进行处理,若是该属性是原生底层直接拥有的,那么就直接往下传递,若是该属性不是底层所拥有的,则须要经过在webview.ios.js层处理成底层组件所拥有的属性,而后再往下传递下去,由RCTWebview或者RCTWKWebview进行处理。web
例如:
source属性:webview层设置了source -----> webview.ios.js往下传递 ------> RCTWebviewManager.m能接受到该属性,而后继续往下传递 -----> RCTWebview进行处理该属性;segmentfault
onLoadStart属性:webview层设置了onLoadStart ----> webview.ios.js对该属性进行处理,包装成_onLoadingStart,而后传给RCTWebviewManager ----> RCTWebviewManager.m能接受到该属性,而后继续往下传递 -----> RCTWebview进行处理该属性;浏览器
语法形式:缓存
- (void)injectJavaScript:(NSString *)script { [_webView stringByEvaluatingJavaScriptFromString:script]; }
当js层传递js字符串给ios的时候,ios就会用stringEvaluatingJavascriptFromString这个方法执行这个script。app
对于uiwebview来讲,通常有三个生命周期他们分别是:post
在webview之中通讯最为重要,经过postMessage向rn层传递信息,rn层只须要message就行,相反也行。该实现的逻辑是在资源加载完成的时候执行的,就是在webviewDidFinishLoad性能
内嵌页面向rn传递信息和接受信息:ui
window.postMessage(data); document.addEventListener('message', (event) => {});
rn层向内嵌页面传递信息:
<Webview onMessage={event => {}} ref={(_ref) => {this.webview = _ref}} ... /> this.webview.postMessage(data)
细心的朋友此处应该能够发现出这里的postMessage和平时咱们调用的不太同样:
通常状况下:window.postMessage(data, origin);
内嵌在webview之中:window.postMessage(data);
缘由是由于在uiwebview之中从新定义了window.postMessage,原来的postmessage已经被赋予到originMessage之中,因此若是在内嵌页面中出现了postmessage(data),放在浏览器会报错,放在rn的webview就会没事。
当页面资源加载完成以后,就会触发webviewDidFinishLoad这个生命周期,在这个生命周期内,会作几件事情:
其中从新定义postmessage的js代码:
大概的意思就是将内嵌页面调用postmessage的信息存在messagequeue之中(以字符串形式放进去),而后经过定义window.location的值来传递信息给原生成,其中window.location的格式是:
'%@://%@?' + encodeURIComponent(messageQueue.shift());" ,当中的两个%@会被RCTJSNavigationScheme和kPostMessageHost代替从而造成新的url地址(不是经常使用的http协议的地址,是指定的特殊协议)
例如:'react-js-navigation://postMessage?' + encodeURIComponent('{"A":1}') ===> "react-js-navigation://postMessage?%7B%22A%22%3A1%7D";因为内嵌页面没有window,因此只能用document来监听webview传来的信息。
postmessage的信息如何传递给原生层:每当webview之中出现url的请求,都会触发shouldStartLoadWithRequest,此时就会由
大概就是判断url的host是否为kPostMessageHost,若是是则认为是postmessage传来的,而后执行_onMessage方法,而这个方法事由上层js定义的:
webview如何将信息传递给内嵌页面:
大概就是经过document.dispatchEvent发起一个事件,而后在内嵌页面之中由document进行监听;
下面就是整一块uiwebview的通讯流程:
因此若是要js层调用原生层能力,能够经过协议请求,而后在原生对该协议进行拦截处理,从而判断是否调用原生能力。
以上就是对uiwebview的一个比较浅的概述,下一篇会继续介绍一下rn中wkwebview的通讯原理。