react-native中IOS的webview和js层通信 - UIWebview

前言

在9012的最后一篇写到了在rn中安卓的webview的通信原理,而作为0202年的第一篇,继续讨论上年rn中webview通信剩下的部分。

背景:

对于webview,了解过的人都知道在ios端会存在两种类型的webview(UIWebview和WKWebview),而他们之间的区别主要如下:

  • 时间上的差异:UIwebview是在ios2之后才有,Wkwebview是在ios8之后才有;
  • UIwebview占用的内存较大,而WKwebview侧是内存占有不多,因此性能会比前者好;
  • WKwebview拥有高达60FPS滚动刷新率(滚动时每秒可达到60次渲染,一般最多64次)及内置手势;
  • WKwebview比UIwebview拥有更多H5的特性;
  • WKwebview提供了加载网页的进度属性;
  • WKwebview在app和web通信方面比UIwebview要好;
  • WKWebView没有做缓存处理,所以对网页需要缓存的加载性能要求没那么高的还是可以考虑UIWebView.

RN中IOS的webview结构:

大致流程:

在ios中,应用层会设置rn中webview的某个属性,而weview会通过webview.iso.js进行处理,如果该属性是原生底层直接拥有的,那么就直接往下传递,如果该属性不是底层所拥有的,则需要通过在webview.ios.js层处理成底层组件所拥有的属性,然后再往下传递下去,由RCTWebview或者RCTWKWebview进行处理。

例如:
source属性:webview层设置了source -----> webview.ios.js往下传递 ------> RCTWebviewManager.m能接受到该属性,然后继续往下传递 -----> RCTWebview进行处理该属性;

onLoadStart属性:webview层设置了onLoadStart ----> webview.ios.js对该属性进行处理,包装成_onLoadingStart,然后传给RCTWebviewManager ----> RCTWebviewManager.m能接受到该属性,然后继续往下传递 -----> RCTWebview进行处理该属性;

大概的流程图:

image.png

UIWebview的相关知识:

ios和js的交互
  • stringEvaluatingJavascriptFromString:该方法时可以让ios层执行js代码;

语法形式:

- (void)injectJavaScript:(NSString *)script
{
  [_webView stringByEvaluatingJavaScriptFromString:script];
}

当js层传递js字符串给ios的时候,ios就会用stringEvaluatingJavascriptFromString这个方法执行这个script。

  • shouldStartLoadWithRequest: 该方法是用来对webview中的url进行拦截,然后判断是否打开这个url链接,需要返回一个boolean值。当webview中存在一个url链接,就会触发这个方法,然后对url进行判断,如果是返回boolean,则可以打开url的链接,否则不行。

image.png

生命周期

对于uiwebview来说,一般有三个生命周期他们分别是:

  • shouldStartLoadWithRequest:页面在准备加载资源;
  • webViewDidFinishLoad:页面资源完成加载完毕;
  • didFailLoadWithError:资源加载失败;

rn中UIWebview和js之间的通信机制:

在webview之中通信最为重要,通过postMessage向rn层传递信息,rn层只需要message就行,相反也行。该实现的逻辑是在资源加载完成的时候执行的,就是在webviewDidFinishLoad
image.png

内嵌页面向rn传递信息和接受信息:

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这个生命周期,在这个生命周期内,会做几件事情:

image.png

其中重新定义postmessage的js代码:

image.png

大概的意思就是将内嵌页面调用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,此时就会由

image.png

大概就是判断url的host是否为kPostMessageHost,如果是则认为是postmessage传来的,然后执行_onMessage方法,而这个方法事由上层js定义的:
image.png

webview如何将信息传递给内嵌页面:
image.png

大概就是通过document.dispatchEvent发起一个事件,然后在内嵌页面之中由document进行监听;

下面就是整一块uiwebview的通信流程:
image.png

所以如果要js层调用原生层能力,可以通过协议请求,然后在原生对该协议进行拦截处理,从而判断是否调用原生能力。

以上就是对uiwebview的一个比较浅的概述,下一篇会继续介绍一下rn中wkwebview的通信原理。

Image placeholder
CoderJJMa
未设置
  35人点赞

没有讨论,发表一下自己的看法吧

推荐文章
一小时快速搭建基于阿里云容器服务-Kubernetes的Web应用

本文面向的读者如果您是一个Kubernetes的初学者,本文可以帮助你快速在云上搭建一个可实际使用的集群环境,并发布自己的第一个应用。你无须提前准备任何的硬件资源或者下载任何的软件包。 如果您已经有一

jquery和js的区别是什么?

jquery和js的区别是什么?一、首先来看一下jQuery和js的概念jquery是一个快速、简洁的JavaScript库,极大的简化了javascript编程。js是一种脚本语言,常用于网页客户端

react中的webpack是什么?

Webpack是一个开源的前端打包工具。Webpack提供了前端开发缺乏的模块化开发方式,将各种静态资源视为模块,并从它生成优化过的代码。Webpack可以从终端、或是更改webpack.config

App内嵌webview踩坑

为移动端h5页面遇到的问题做些记录一、样式部分1.1基本样式object-fit:fill;//video铺满父元素 -webkit-appearance:none;//消除iOS输入框的内阴影1.2

JSON.parse和JSON.stringify的巧用

JSON.parse和JSON.stringify是对json数据的转换,在js中使用的频率还是非常高的,比如localStorage,cookie中对复合型数据的存储,与服务器进行数据交互的格式转换

JSON.parse和JSON.stringify的巧用

JSON.stringify()是将一个JavaScript值(对象或者数组)转换为一个json字符串,如果指定了replacer是一个函数,则可以选择性地替换值,或者如果指定了replacer是一个

分享一个可视化开发vue框架下的各类ui的web在线表单设计布局器

新手发帖,第一次不小心刷新了一下就没了本人刚入门vue,偶然间发现这款布局器挺好的,可视化开发element所以分享给大家网站地址:http://lowcode.magicalcoder.c...嵌入

react和jquery的区别是什么?

首先我们要注意的是,虽然我们这里把React和JQuery拿到一个台面上来说,但是这两者是有本质区别的。React是一个UI库,但是JQuery更多的知识一个工具库或者说是插件库,我们之所以把这两者谈

js和jquery的区别是什么?

JavaScript和jQuery的区别:一、本质上的区别:js是网页脚本语言,而jQuery是基于js语言封装出来的一个前端框架。也就是说js是一种语言,而jQuery是基于该语言的一种框架。二、用

vuejs和jquery的区别是什么?

vuejs和jquery的区别1、jQuery首先要获取到dom对象,然后对dom对象进行进行值的修改等操作2、Vue是首先把值和js对象进行绑定,然后修改js对象的值,Vue框架就会自动把dom的值

jquery和js之间有什么区别?

js是一种脚本语言,常用于网页客户端编程,使网页在客户端浏览器中,实现更多地动态功能,表现出更加丰富的视觉效果。jQuery是一个简洁而快速的JavaScript库,可用于简化事件处理,HTML文档遍

html和jsp的区别及优缺点

html和jsp的区别:●最简单的区别就是,HTML能直接打开,jsp只能发布到Tomact等服务器上才能打开●定义上HTML页面是静态页面可以直接运行,JSP页面是动态页它运行时需要转换成servl

css和js后加问号和数字有什么用?

css和js后加问号和数字有什么用?当浏览器请求一个网站的时候,会加载各种各样的资源,比如:HTML文档、图片、CSS和JS等文件。对于一些不经常变的内容,浏览器会将他们保存在本地的文件中,下次访问相

axios怎么引入到vue中?

Axios是一个基于promise的HTTP库,可以用在浏览器和node.js中。在vue项目之中使用axios是一个非常明智的选择,因为vue官方已经宣称不再维护vue-resource,并且推荐使

Kubernetes1.14 版发布,增强了云原生平台的Windows节点支持

Kubernetes1.14GA版本,是开源云原生平台Kubernetes在2019年的一次重大更新。自3月25日开始,这一版本正式推出,供开发者全面使用。  Kubernetes,由云原生计算基金会

win10美化,让你的win10独一无二,与众不同!

1.原则美化之前,得先有一个目标对不对,笔者是一个喜欢简单的人,因此美化本着三大原则:简单,干净,整洁.呃....好像很抽象的样子,上图吧.反正没图没真相.怎么样,还可以吧,没有任何多余的东西.再来一

vue.js的localhost无法打开

课程推荐:web全栈开发就业班--拿到offer再缴学费--融职教育 vue项目不能使用localhost访问 问题 vue项目不能使用localhost访问,但是使用本机的ip加端口号是可以访问的

聊聊chronos的DeleteBgWorker

序本文主要研究一下chronos的DeleteBgWorkerDeleteBgWorkerDDMQ/carrera-chronos/src/main/java/com/xiaojukeji/chron

webpack中css的url报错?

webpack中css的url报错?css-loader://打包样式中背景图 { test:/\.(png|jpg)$/, loader:"url-loader?limit=8192&name=im

leveldb源代码分析系列1.1:memtable中comparator的实现

leveldb中memtable封装了一个skiplist用来存储真正的数据,跳跃列表的实现一定需要定义存储项的序关系,而在leveldb中这个序关系通过comparator相关类来实现。leveld

dreamweaver和css的区别是什么?

DreamweaverAdobeDreamweaver,简称“DW”,中文名称"梦想编织者",是美国MACROMEDIA公司开发的集网页制作和管理网站于一身的所见即所得网页编辑器。DW是第一套针对专业

echarts怎么引入到vue中?

准备工作:首先我们初始化一个vue项目,执行vueinitwebpackechart。接着我们进入初始化的项目下,安装echarts,npminstallecharts-S //或 cnpminsta

node中文什么意思?

起初,RyanDahl称他的项目为web.js,就是一个Web服务器,但是项目的发展超过了他最初单纯开发一个Web服务器的想法,变成了构建网络应用的一个基础框架,这样可以在它的基础上构建更多的东西,诸

vue中如何关闭eslint检测?

vue中如何关闭eslint检测?有了eslint的校验,可以来规范开发人员的代码,是挺好的。但是有些像缩进、空格、空白行之类的规范,在开发过程中一直报错,未免太过于苛刻了。所以,下面来介绍下怎么在v

ajax怎么在vue中使用?

ajax怎么在vue中使用?axios是一个基于Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护本文为大家介绍vue使用a