从Hybrid到React-Native: JS在移动端的南征北战史

注:因为不了解Dart,所以本文不对flutter相关内容进行阐述, 实在抱歉

其实写这篇文章的时候,我就知道,肯定有人问我:为什么不写flutter?抱歉了,flutter的大名我当然知道,可我只是一个写JS的,同时了解一些Java的知识,而flutter采用的编程语言,我暂时没有碰过,所以自然不敢妄加猜度,还请谅解

Hybrid

Hybird是一种混合开发应用,可以实现JS和Java代码的互通,单纯使用ios/android原生实现,开发进度和成本受不了,而单纯使用h5/js开发,页面体验更加受不了。Hybird的目的是实现H5和Naive两者之间的权衡

Hybird的实现方式

Hybrid是基于原生webview控件实现的,它主要要解决的问题有两个:

  • 原生端怎么调用JS代码
  • JS代码怎么调用原生端

这个问题进一步扩展,又细分为以下4个问题:

  • Q1: JS怎么调用Android代码
  • Q2: Android代码怎么调用JS
  • Q3: JS怎么调用IOS代码
  • Q4: IOS代码怎么调用JS

Q1: JS怎么调用Android代码

我们先讲下JS是怎么调Android代码的

主要有3种

  1. JSInterface
  2. JSBridge
  3. UrlRouter

1)JSInterface

从我们前端的角度看啊,是这样子滴~ :在Android中啊,有个叫做WebView的控件,这个控件的作用是可以在里面放一个网页然后运行它!我们前端就暂时把它理解成一个安卓APP里嵌入的微型浏览器吧,哈哈。然后呢,这个WebView控件对象还可以调用一个方法。

一个叫webView.addJavascriptInterface(接口对象,接口名)的方法,调用后,webView控件里面的HTML页面里的JS代码,就可以调用刚才addJavascriptInterface方法里的接口对象的原生方法了! 于是就这样,我们可以从JS间接调用原生Android代码,从此桥梁建立

例如,比如说我们下面定一个JSInterface的类,里面的showToast方法可以弹出一个原生的Toast

Android的原生代码

webView.addJavascriptInterface(new JsInterface(), "control”);
// …
public class JsInterface {
        @JavascriptInterface
        public void showToast(String toast) {
            Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
            log("show toast success");
        }

}

JS代码

// WebView中的JS代码,注意control就是上面addJavascriptInterface定义的命名空间
function showToast(toast) {
  javascript:control.showToast(toast);
}

参考资料

好好和h5沟通!几种常见的hybrid通信方式

2)JSbridge

从我们前端的角度看啊,其实是这样子滴~:就是在Android中啊,有这么一个WebChromeClient的组件,它就是上面讲到的WebView控件的一个子类。没错,它也可以在里面放一个网页去运行它,而且它牛啤的地方在于:你这个内部网页里的JS干的三件事可以被外层WebChromeClient给监听到:分别是前端的alert方法,confirm方法和prompt方法。只要你动了这三个方法,它们传递的数据就会被外部的WebChromeClient拦截和获取,这就为JS调Android的代码提供了一种方便的渠道。哎呀,三个方法这么多选哪个呢? 一般情况下,我们会选prompt方法,因为alert方法JS相对用的比较频繁,存在起冲突的可能

3)UrlRouter

这个东东还是和上面是一样的,Android的WebChromeClient控件这个类,它有个shouldOverrideUrlLoading这个方法,这个方法可以把控件内部网页的JS的Url请求给拦截了,当然了,你写在Url中的数据也同时被一并获取了。

总结:说白了JSInterface,JSBridge和UrlRouter主要的作用就是提供JS调原生代码的方式,搭一座桥梁

Q2: Android怎么调JS代码?

1)web view.loadUrl

有了上面的经验你肯定知道,这事还是webview这位老哥来做的,它可以通过调用webview.loadUrl方法加载一个HTML页面,这样HTML中的JS脚本不就被调用了吗?

webView.loadUrl(“...//my.html”);

2)webView.evaluateJavascript

上面的loadUrl有一个问题,它会导致页面刷新,而且通过加载文件的方式执行JS代码总不是我们认为最优雅的方式,我们可能期望的是执行一段指定的代码,而非一个文件,webView.evaluateJavascript就是做这件事情的,以下的代码可以执行一段JS代码

webView.evaluateJavascript(“JS代码”,Callback对象)

哦,对了,不好意思,上面讲的是Android的,下面讲下IOS怎么做

Q3: IOS代码怎么调用JS

1.可通过webview.stringByEvaluatingJavaScriptFromString方法调用JS方法,但前提是该JS方法在顶层Window对象上

webview.stringByEvaluatingJavaScriptFromString("方法名(参数)”)

Q4: JS怎么调用IOS代码

可通过 shouldStartLoadWithRequest方法进行拦截JS请求,从而感知JS的调用发起,并进行相应处理,以达到JS调用ios的效果

Hybrid也曾在移动端连接H5的童话世界中风靡一时,但由于对webview以及H5的过度依赖,导致它的体验性问题一直让人困扰,所以自从React-Native横空出世后,后者便蚕食了前者的半壁江山。

React-Native

RN的作用

  1. 跨平台:可以为IOS/Android,甚至Windows Phone开发原生应用
  2. 相对良好的UI体验,平衡开发成本和用户体验后相对合理的选择

RN的本质

  1. 不是WebView,和Cordova等Hybrid方案划清界限
  2. 不将JavaScript预编译为Native代码,和Xamarin等方案划清界限。Xammarin的方案是AOT的,运行前就编译为原生代码,RN则采用JIT+解释器的方案(IOS另当别论)
  3. RN是虚拟机类的方案,依靠运行时系统JavaScriptCore运行

RN的4个线程

  1. UI线程:也成为主线程,负责本机的Android/iOS的UI呈现,在android中它负责android测量/布局/绘制
  2. JS线程:执行JS/React代码,进行API调用,处理触摸事件等,对视图的更新被进行批处理,并在事件循环结束时发送给UI线程
  3. Shadow线程:处理虚拟DOM布局变更的线程
  4. 本机模块线程: 如android/ios系统自带的原生API

RN的3部分

  1. Native端(IOS/android)
  2. JavaScript端
  3. Bridge:上面介绍的多个线程之间相互通信,以及JS和Native端通信的方式的统称

线程协调过程示例

以下面一段RN代码的执行为例,它在JS线程中执行

<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
  <View style={{width: 100, height: 100, backgroundColor: "red"}}></View>
</View>
  1. 注意原生端有自己的布局实现,所以上面的flex属性和CSS是没有任何关系的。
  2. 为了实现布局,同时又不阻塞JS线程,布局计算将转移到Shadow线程中进行。
  3. Shadow线程进行计算,并最终将计算结果得到的布局参数传递给主线程(UI线程),实现UI的构建

RN中的Bridge做了什么? && RN线程如何交互?

  • 异步:线程之间,例如JS线程和UI线程,以异步的方式进行通信,这样它们就不会互相阻塞了
  • 批处理: 以优化的方式, 把消息从一个线程传递到另外一个线程
  • 序列化: 两个线程不会操作或者共享同一块数据,它们之间会通过序列化和反序列化的方式交换消息

RN线程异步带来的某些问题 && 未来的解决方案

RN中的JS线程和UI线程之间是没有同步的方式的,这可能造成一些问题,但RN未来的Fabric也许能提供这一功能

RN的Web化:react-native-web

react-native-web 组件的内部,会把 React Native 的 API 映射成了浏览器支持的 API。将RN的代码转化成浏览器能支持的代码

RN-web和普通的React的区别?

RN-web尽量做到不侵入RN代码,不影响RN代码的逻辑,争取能够在基本不动RN项目代码的情况下,将其H5化,RN-web项目的基本逻辑还是RN,不是React

RN-WEB的作用

实现IOS/Android/Web的三端构建

参考文章

原文地址:https://www.cnblogs.com/penghuwan/p/11538146.html

时间: 2024-08-30 17:29:42

从Hybrid到React-Native: JS在移动端的南征北战史的相关文章

Hybrid APP基础篇(二)-&gt;Native、Hybrid、React Native、Web App方案的分析比较

说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid App React Native App 分析 各大开发模式直观对比 如何选择开发模式 另类的app方案 微网页 微信小程序 其它 前言 参考来源 前人栽树,后台乘凉,本文参考了以下来源 对当前主流hybrid app.web app与native app工具的初步比较与分析 H5.React Nati

Native、Web App、Hybrid、React Native(简称RN)、Weex 间的异同点。

App常用开发模式简介 此处App为应用application,并非我们通常讲的手机App. 常用的几种APP开发模式-脑图 Native App 传统的原生App开发模式,有iOS和aOS两大系统,需要各自语言开发各自App. 优点:性能和体验都是最好的. 缺点:开发和发布成本高. 举个栗子:网易管家App (https://id.163.com/gj/) 应用技术:Swift,OC,Java. WebApp 移动端的网站,常被称为H5应用,说白了就是特定运行在移动端浏览器上的网站应用.一般泛

【REACT NATIVE 系列教程之十二】REACT NATIVE(JS/ES)与IOS(OBJECT-C)交互通信

一用到跨平台的引擎必然要有引擎与各平台原生进行交互通信的需要.那么Himi先讲解React Native与iOS之间的通信交互. 本篇主要分为两部分讲解:(关于其中讲解的OC语法等不介绍,不懂的请自行学习) 1. React Native 访问iOS 2. iOS访问React Native     一:React Native 访问iOS 1. 我们想要JS调用OC函数,就要实现一个"RCTBridgeModule"协议的Objective-C类 所以首先我们先创建一个oc新类,  

react native js 与 native 的通信与交互方式

JS 的启动过程 React Native 的 iOS 端代码是直接从 Xcode IDE 里启动的.在启动时,首先要对代码进行编译,不出意外,在编译后会弹出一个命令行窗口,这个窗口就是通过 Node.js 启动的 development server . 问题是这个命令行是怎么启动起来的呢?实际上,Xcode 在 Build Phase 的最后一个阶段对此做了配置,其实就是增加了一个 sh 脚本,让小葱的在编译会自动去执行这个脚本,打开 npm,相当于你直接手动命令行切到 react-nati

基于React Native的跨三端应用架构实践

作者|陈子涵 编辑|覃云 “一次编写, 到处运行”(Write once, run anywhere ) 是很多前端团队孜孜以求的目标.实现这个目标,不但能以最快的速度,将应用推广到各个渠道,而且还能节省大量人力物力. React Native 的推出,为跨平台的开发带来了新的曙光. 虽然 Facebook 官方 blog 的说法 React Native 支持“Learn once, write anywhere.”. 但经过开源社区的不断努力,React Native 已经可以达到“一次编写

ReactJs和React Native的那些事

介绍 1,React Js的目的 是为了使前端的V层更具组件化,能更好的复用,它能够使用简单的html标签创建更多的自定义组件标签,内部绑定事件,同时可以让你从操作dom中解脱出来,只需要操作数据就会改变相应的dom. 2,React Native的目的 是希望我们能够使用前端的技术栈就可以创建出能够在不同平台运行的一个框架.可以创建出在移动端运行的app,但是性能可能比原声app差一点. 3,ReactJs和React Native的原理是相同的,都是由js实现的虚拟dom来驱动界面view层

ReactJs和React Native的联系和差异

1,React Js的目的 是为了使前端的V层更具组件化,能更好的复用,它能够使用简单的html标签创建更多的自定义组件标签,内部绑定事件,同时可以让你从操作dom中解脱出来,只需要操作数据就会改变相应的dom. 2,React Native的目的 是希望我们能够使用前端的技术栈就可以创建出能够在不同平台运行的一个框架.可以创建出在移动端运行的app,但是性能可能比原声app差一点. 3,ReactJs和React Native的原理是相同的,都是由js实现的虚拟dom来驱动界面view层渲染.

React Native专题-江清清

本React Native讲解专题:主要讲解了React Native开发,由基础环境搭建配置入门,基础,进阶相关讲解. 刚创建的React Native交流8群:533435865  欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送! 关于React Native各种疑难杂症,问题深坑总结方案请点击查看: Mac和Windows安装搭建React Native环境教程如下: Mac OS X版本:Mac OS X安装R

React Native Android 应用层实战沦陷记

[工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 一眨眼又一年快要过去了,原计划今年的最后一个小目标(React Native)看样子要留尾巴到明年了,React Native 想说爱你不容易.怎么评价你呢?应用层 JSX 编写还是很友好的,尼玛框架接入的各种锅却让人痛哭不已,万事开头难,对于 React Native 的接入可以说大量工作可能都需要投入到框架接入中(各种灰度实验的兼容性.各种锅),一旦接入稳定以