React Native 三端同构实践

article/2025/10/15 11:29:00

⚠️ 博客中涉及的代码内容可查看 Github: react-native-isomorphism

React Native三端同构皆在🈯️在不改动 React Native 代码下,公用一套代码架构, 在浏览器中实现同样的展示、交互、功能。

在实际开发过程中, 尤其创业公司, 需求的迭代周期是非常快的, 并且由于人力成本等因素, 单独为每个平台实现一套代码的代价是极大的。如何实现一套代码多端平台运行,就变得非常重要。而 React Native 三端同构就能轻松解决这个问题。同时, 可以使开发者花费更多的时间在功能开发上, 保证了开发团队轻、快、高的目标实现。

实现原理

做过 react-native 开发的同学肯定对 react-native 的框架不陌生, react-native 是基于 React 实现,基于React封装了一套可在Android、iOS平台同时运行的组件。经过 编译、解析、 render 后会以虚拟 DOM 的形式存储在内存中, 所以基于 React Dom 我们可以实现对应平台的不同实现

目前业界提供了几种实现方式:

reactxp

支持 ios、android、web、windows 。提供的api 较少, 平台支持度不高

JD Taro

taro 不仅支持 web,还支持编译成小程序,但是目前平台支持度也不是特别高,api支持度低,建议在支持小程序的场景下使用

react-native-web

react-native-web 官方对其称对原项目没有任何侵入性,无需改动原来的代码,只需在项目中加入一些 web 构建配置即可构建运行出和 react-native 一致的效果。并且结合 react-native 的支持度非常高, 建议使用此方案。

应用场景

基于 React Native 实现三端同构的应用场景包括:

  • 在 React Native 页面崩溃时用对应的 Web 页,保证用户可以正常使用页面。
  • 对于需要分享到社交网络如微信朋友圈、微博的页面,不可避免地需要 Web 网页。
  • ....

怎么做?

react-native-web 实现原理是将 react-native 组件生成web页面对应的标签元素。并且通过构建工具,实现 Write Once, Run Anywhere。接下来对于现有的 react-native 项目,如何将 react-native-web 进行整合, 我们一一说来。

(1) 创建 react-native 应用

     关于 react-native 项目的初始化方式就不再多说了, 可以查看 官方文档 来了解更多

(2) 使用 create-react-app 创建 web 应用

     Create React App 是一个官方支持的创建 React 单页应用程序的方法。它提供了一个零配置的现代构建设置。

npx create-react-app my-web-app

(3) 将 (2) 步创建的 react web 工程中的 public、src 目录导入 (1) 步 创建的 rn 工程

(4) 用过 npm 或 yarn  安装以下依赖

"react-art": "^16.13.1" // art 图形渲染
"react-dom": "^16.13.1" // react 组件到 web 组件到解析、渲染
"react-router-dom": "^5.1.2" // react web 导航
"react-router-modal": "^1.5.2" // react web modal router
"react-native-web": "^0.12.2" // react-native 解析成 web 组件

(5) package.json 文件中添加以下 scripts

// react-native
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
// web
"start-web": "react-scripts start",
"build-web": "react-scripts build",
"test-web": "react-scripts test",
"eject-web": "react-scripts eject"

以上步骤完成后, 将 App.js 文件 剪切到src目录, 并且在 src/index.js 文件中指向 App.js 文件, 此时我们可以使用 yarn start-web 来启动, react-native-web 即可帮我们将App.js解析成 web 端的对应实现, 并在浏览器中展示。

路由机制

实际开发中, 一个页面的应用几乎是非常少的。如果涉及多页面交互, 就离不开路由栈的支持。路由栈的存在可以帮助我们轻松实现页面间的跳转、返回、弹出、参数传递等常见交互。

react-native中主流的路由库使用最多、社区最活跃当属 react-navigation。react-navigation 路由机制类似于栈,每次 push 一个新页面,就会将其存储在路由栈中,页面退出,栈中移除。

react-web 路由代表当属 react-router-dom,该框架只会加载一个路由页面(PWA),跳转即匹配一个路由, 实现页面之间的切换, 有点类似 Android 中的 Fragment。所以,针对两种不同路由机制,需要在 web、rn 之间使用不同的路由配置。同时, 也面临了一个问题: 导航、传参、跳转方式 在这两个导航库中存在着很大不同, API的使用也几乎完全不一样。例如:  在 rn 平台中,  我们使用 react-navigation 的navigation.navigate 函数实现界面间的跳转, 并且可以借助 navigate 函数的第二个参数实现页面之间的参数传递。而在 web 端, 跳转一个页面需要使用 history.push 函数来完成, 参数的传递也是完全不同, 需要将参数在 url 中进行定义。

如何保持一致性的使用方式,是我们接下来要解决的问题。为了兼容两端,  以 react-navigation 的 api 为基准,  封装 web 端的跳转方式, 将其与 react-navigation 的使用方式保持一致。

(1) navigate 跳转

在 rn 端的跳转方式使用如下:

const { navigation } = this.props;
navigation.navigate('目标页面', params);

在 web 端, 自定义 navigate 方法

  const navigate = (toScene, params) => {const {navigationOptions} = routeMap[toScene];const isRouteModal = navigationOptions.modal;let routePath = navigationOptions.path;// 将:param? 替换成对应参数if (params && Object.keys(params).length > 0) {Object.keys(params).forEach((param) => {const re = RegExp(`:${param}\\??`);routePath = routePath.replace(re, escape(params[param]));});}//从url中删除空参数 : 和 ? 之间的每个字符串都带有实际值routePath = routePath.replace(/\/:(.*?)(?=\/|$)/g, '');if (!isRouteModal) {history.push(routePath);} else {// 检查网址是否以斜杠结尾const slash = /\/$/.test(match.url) ? '' : '/';// 浏览器中的当前网址+斜杠+带有参数的模式网址routePath = match.url + slash + routePath;// 从网址中删除*routePath = routePath.replace(/\*\/?/g, '');history.push(routePath);}};

(2) getParam 获取参数

在 rn 端的获取参数方式使用如下: 

const { navigation } = this.props;
navigation.getParam('xxx');

在 web 端, 自定义 getParam 方法 

// 获取参数
const getParam = (param, alternative) => {return match.params[param] || alternative;
};

(3) goBack 返回上一页

 在 rn 端的返回上一页方式使用如下: 

const { navigation } = this.props;
navigation.goBack();

在 web 端, 自定义 goBack 方法  

// 返回
const goBack = () => {history.goBack();
};

(4) 回退到路由栈的某个页面

在 react-navigation 中,可以使用 pop 回到导航栈中的前 n 个页面。但是在 react-router 中 并未提供这样的功能,因为在react-router 中并不存在栈的概念。为了解决这个问题,需要引入一个自定义的 pop 函数。 

react-native 端:

import {StackActions} from 'react-navigation';const pop = ({navigation, n}) => {navigation.dispatch(StackActions.pop({n}));
};export default pop;

web 端:

const pop = ({ screen, navigation }) => {navigation.navigate(screen)
}export default pop

使用方式:

// screen 用于web端跳转
// n 用于指定 rn 端回退的层级
// navigation 为当前路由
pop({screen: 'FirstScreen', n: 2, navigation})

模态框

在 react-native 端实现 Dialog 非常简单, 并且也可以使用react-navigation, 定义modal模式, 即可实现从下向上滑出的模态页面, web 端需要借助 react-router-modal 来实现类似的模态效果

const RouteMap = {Modal: {screen: ModalScene,navigationOptions: {path: '*/basemodal',modal: true //路由会用 ModalRoute 路由组件来渲染}}
}

然后将 <ModalContainer /> 添加到 render 中 即可。

状态管理

redux 或者 mobx,都可以支持复用, 建议选择 mobx

适配 NativeModules

React Native 开发的 App 中经常会出现 React Native 官方提供的 Native Modules

够用的情况,这时你会在项目中开发自己的 Native Modules,然后在 JavaScript 中去调用自己的 Native Modules。这在 ReactNative 环境下运行没有问题,但转成 Web 后执行时会报错说 Native Modules 上找不到对应的模块,这时因为在浏览器环境下是不存在这些自定义的 Native Modules。为了让页面能正常在浏览器中运行,需要为 Web 平台也实现一份自定义的 Native Modules,实现方法可以在 Web 平台的执行入口的最开头注入以下 polyfill,内容如清单 6 所示:

NativeModules polyfill.js

import { NativeModules } from 'react-native';
import MyModule from './MyModule'; // 实现自定义 Native Modules 的地方NativeModules.MyModule = MyModule; // 挂载 MyModule

这段代码的作用是把针对 Web 平台编写的自定义原生模块挂载到 Native Modules 对象上成为其属性,以让 JavaScript 代码在访问自定义 Native Modules 时访问到针对 Web 平台编写模块。

平台区分

虽然 react-native-web 可以很好的支持大部分使用场景,但在一些特殊情况下也需要我们根据不同平台来决定使用不同的实现方式,例如一些特定平台下支持的api,区分不同平台的方式有以下三种:

1. Platform.OS

import { Platform } from 'react-native';if(Platform.OS === 'web'){// Web
} else if (Platform.OS === 'android') {// Android
} else if(Platform.OS === 'ios'){// iOS
}

2. Platform.select

react-native 端提供来 Platform.select 来根据不同平台加载对应平台代码,

Platform.select({ios: () => {},android: () => {},web: () => {},
});

3. .web.js

Web 模式下会优先加载.web.js文件, .web.js 文件不存在时使用 .js 文件。 和 react-native 中的 .android.js、.ios.js 作用相同

index.android.js
index.ios.js
index.web.js

总结

经过上述的实践, 我们基本完成了基于 react-native 的三端同构, 回到最初我们提到的同构的应用场景

  • 在 React Native 页面崩溃时用对应的 Web 页,保证用户可以正常使用页面。
  • 对于需要分享到社交网络如微信朋友圈、微博的页面,不可避免地需要 Web 网页。
  • ....

其实还有很多的功能应用场景可以使用同构来轻松解决, 同样, 不足的地方也很明显, 平台的区分、react-native-web Api的支持、导航库的支持等等, 还需要我们根据实际的开发需求来针对性的进行自定义、补充实现。同时, 基于当前的架构, 我也会不断完善。


http://chatgpt.dhexx.cn/article/g8GqS5dO.shtml

相关文章

吐血推荐|2万字总结Mac所有应用程序、软件工具和相关资料

现在随着互联网的发展&#xff0c;越来越多的公司都鼓励Mac办公&#xff0c;属实MacOS系统对于我们的工作开发效率有很大提升&#xff0c;所以我们需要收集各种类别非常好用的 Mac 应用程序、软件以及工具。作为一个资深 Mac 用户&#xff0c;我需要它们帮助我快乐、高效的工作…

网易云音乐React Native体系建设与发展

本文作者&#xff1a;章伟东 &#xff08;网易云音乐大前端团队&#xff09; 0.33 历史 17 年 3 月份&#xff0c;为了解决商城性能和用户体验问题&#xff0c;云音乐技术团队组建了一只 4 人 ReactNative 开发小分队&#xff1a;我负责 RN 前端开发&#xff0c;安卓和 iOS 两…

每周分享第 26 期

这里记录过去一周&#xff0c;我看到的值得分享的东西&#xff0c;每周五发布。 Basecamp 是 IT 行业很有名的一家公司&#xff0c;提供团队协作工具&#xff0c;同时也是 Rails on Ruby 框架的创造者。这家公司的特别之处在于&#xff0c;它不仅写软件&#xff0c;还写畅销书&…

爱开源的微软是如何击败 Facebook、Google 成为 GitHub No.1 的?

拥抱开源的微软这几年究竟都做了些什么&#xff1f; 去年今月&#xff0c;我在微软开发者峰会上见到了《设计模式&#xff1a;可复用面向对象软件的基础》联合作者、现任微软技术院士&#xff08;Technical Fellow at Microsoft&#xff09;Erich Gamma&#xff0c;那是我第一次…

跨端与同构开发技术一览

关键词&#xff1a;React Native, uni-app, Flutter ,Tauri, Ionic 和 weex 文章目录 前言跨端技术简史几种常见跨端技术对比小程序的繁荣跨端同构技术uni-appTaroreact-native-webreactxpWeex阿里的RaxRemax去哪儿网的qrn-remax-unir去哪儿网的anuKbone腾讯新一代跨端开发框架…

@开发者,一份微软官方Github上发布的开源项目清单等你签收

最近在倒腾WPF的项目&#xff0c;试着搜一下微软官方提供的WPF Smaples, 结果找到了https://github.com/Microsoft/WPF-Samples. 当然还发现了Cortana相关的开源资料http://microsoft.github.io/UWPQuickStart/docs/challenges/cortana-integration.html和UWP资源http://micros…

React Native 三端同构实战

WeiboGoogle用电子邮件发送本页面 0 React Native 三端&#xff08;Web、iOS、Android&#xff09;同构是指在不改动原 React Native 的代码下&#xff0c;让其在浏览器中运行出和在 React Native 环境下一样的页面。对于使用 React Native 开发的页面&#xff0c;如果又单独为…

reactxp搭建,start:windows运行不起来

1、官网 reactxp 2、VSCode和Visual Studio2019 安装VSCode Visual Studio 下载地址 先不用勾选工作负荷&#xff0c;直接安装 3、安装nvm 访问下载地址下载安装nvm&#xff1a; 百度云分享 官网直装链接 nvm的github发行界面下载nvm-setup.exe GitCode镜像下载nvm-setup…

微软发布ReactXP:方便开发者构建跨平台应用

说起跨平台开发工具&#xff0c;开发者们最先想到的无外乎是 Cordova 和 Xamarin。但是前者无法提供足够令人满意的性能表现&#xff0c;而后者在 Web 开发上心有余而力不足。所以&#xff0c;微软 Skype 团队基于 React JS 和 React Native 开发了一款全新的跨平台开发工具 —…

跨平台技术实践案例: 用 reactxp 重写墨刀的移动端

重新编写&#xff0c;又一次&#xff0c;我们又一次重新编写了移动端应用和移动端网站。要重新编写是一个风险很大的决定&#xff0c;但是其必要性以及它所带来的收益是我们无法拒绝的。这篇文章会分享我们为什么这么做&#xff0c;我们是怎么做的&#xff0c;以及这次重写后为…

ReactXP入门指南

ReactXP入门指南 1.ReactXP介绍 ReactXP使用了React框架&#xff0c;使得开发人员可以使用React开发他们的跨平台任务。 React的理念是“学习一次&#xff0c;写在任何地方”。使用React和React Native&#xff0c;应用程序可以与iOS和Android应用程序共享大部分逻辑&#x…

SfM、VO和SLAM介绍

一家之言&#xff0c;仅作分享&#xff0c;如有不合理或需要改进的地方&#xff0c;欢迎各位讨论。 前言 在自动驾驶地图定位模块的功能开发中&#xff0c;主要研究方向分为三种&#xff1a;建图、里程计、定位。SfM&#xff08;Structure From Motion&#xff09;即 传统三维…

SfM: Structure from motion

SfM Structure from motion (SfM) is the process of estimating the 3-D structure of a scene from a set of 2-D images. 运动结构&#xff08;SfM&#xff09;是根据一组二维图像估计场景的 3-D **结构的过程。 注意Motion是指相机在移动 SFM通常用来建立image structu…

经典/深度SfM有关问题的整理

这篇博客主要是记录一些实践或看论文过程中遇到的一些不好理解的问题及解释。      Q1&#xff1a;SfM里的尺度不变性指的是什么&#xff1f;   A1&#xff1a;一般定义下&#xff0c;尺度不变性是指体系经过尺度变换后&#xff0c;其某一特性不变。比如&#xff0c;特征…

OpenCV实现SfM(一):相机模型

注意&#xff1a;本文中的代码必须使用OpenCV3.0或以上版本进行编译&#xff0c;因为很多函数是3.0以后才加入的。 目录&#xff1a; 文章目录 #SfM介绍 SfM的全称为Structure from Motion&#xff0c;即通过相机的移动来确定目标的空间和几何关系&#xff0c;是三维重建的一种…

Structure From Motion(SFM)入门讲解

概念&#xff1a; Structure From Motion(SFM) 是从一系列包含视觉运动信息的多幅二维图像序列中估计三维结构的技术。 SFM和立体视觉的区别 在立体视觉中&#xff0c;两个相机之间的相对位姿是通过标定靶精确标定出来的&#xff0c;在重建时直接使用三角法进行计算&#x…

[CV] Structure from motion(SFM)- 附我的实现结果

【更新】我的新博客&#xff1a;www.ryuzhihao.cc&#xff0c;当然这个csdn博客也会更新 本文在新博客中的链接&#xff1a;点击打开链接 完成时间&#xff1a;2017年2月27日 博客时间&#xff1a;2017年4月26日 去年&#xff0c;我有幸了解到image-based mode…

SFM(structure-from-motion)实现流程详细介绍

SFM&#xff08;structure-from-motion&#xff09;算法是一种基于各种收集到的无序图片进行三维重建的离线算法。顾名思义是从运动中&#xff08;不同时间拍摄的图片集&#xff09;恢复物体的三维结构&#xff0c;这需要估计出图片的R,t&#xff0c;结合相机内参重建稀疏点云。…

SFM算法介绍

背景 股票市场存在着短线、中长线、长线等不同频率的交易模式&#xff0c;这些交易活动决定了股票价格的变动。为了对股票价格进行预测&#xff0c;该文章提出了一种循环神经网络SFM&#xff0c;可以从股票价格的时序数据中捕捉多种频率的交易规律&#xff0c;从而做出短期/长…

增量式SfM详细流程介绍及实现方法

目前主流的SfM&#xff08;Structure from Motion&#xff0c;运动结构恢复&#xff09;可以分为两大类型&#xff0c;一种是全局式的&#xff0c;一种是增量式的。全局式&#xff08;Global&#xff09;sfm能够一次性得出所有的相机姿态和场景点结构。它通常先求得所有相机的位…