前端和RN代码互转总结

React Native出现的目的本就是“learn once, write anywhere”,Facebook希望人们能够学习一次,到处使用,但是同样是JS代码,从前端移植到RN,或者RN移植到前端,却并没有想象的那么容易。事实上除了语法相同外,还有很多不一样的地方,导致我们没法做到直接copy,以下是我在做迁移代码的时候,总结的一些经验

1 Antd Mobile

Antd Mobile的蚂蚁金服开源的一套UI组件,已经实现了前端、iOS、Android的三端统一UI,推荐大家多多使用

1.1 Flex

1.1.1 使用Flex的参数

多用direction justify align 属性,因为某些移动端浏览器不支持Flex功能,影响到适配,而antd已经帮我做过了,只是需要我们采用以下写法,否则无效
例如:
Good:
<Flex direction="column" align="start" justify="startt">

Bad:(这种写法并没有利用到Flex本身的适配)

<Flex style={{  
flexDirection: "column",  
backgroundColor: "white",
justifyContent: "flex-start"
}}>

这样的话,因为前端的兼容性你需要写很多适配的css代码,例如

{
      display: flex;
      display: -webkit-flex;
      flex-direction: row;
      -webkit-flex-direction: row;
      justify-content: flex-start;
      -webkit-justify-content: flex-start;
      align-items: center;
      -webkit-align-items: center;
}

1.1.2 显示指定flexDirection

因为某些情况下Flex无法使用,例如RN端的Touchable组件只能包裹原生组件,必须用View替代Flex,而View和Flex的默认方向是不一样的,因此显示写出flexDirection,明确告知方向,方便迁移者改动代码
Good:

<Flex  direction="column">
     {...}
</Flex>

Bad:(替换成View时候方向会错)

<Flex>
     {...}
</Flex>

1.2 ListView

在RN 0.51版本下,antd的ListView会报错,还是使用RN提供的ListView,只需要修改import ListView即可,其他写法完全一致

// 不推荐
import { ListView } from "antd-mobile";
// 推荐
import { ListView } from "react-native";

2 代码规范

2.1 尽量组件化

某些页面很复杂,常见的一种写法是将页面拆分成若干模块,每个模块写一个moduleRender函数,再在render函数里分别调用,类似以下

Bad:

class SomeComponent extends Component {
      renderSubOne() {
        return <Flex>{...}</Flex>;
      }
      renderSubTwo() {
        return <Flex>{...}</Flex>;
      }
      renderSubThree() {
        return <Flex>{...}</Flex>;
      }
      render() {
         return <Flex>
            {this.renderSubOne()}
            {this.renderSubTwo()}
            {this.renderSubThree()}
          </Flex>
      }
}

Good:

  1. 因为迁移很可能是迁移某一部分,尽量拆分成组件迁移起来更灵活
  2. 这种写法性能更高,分开写的话每个组件有自己的生命周期,某个子组件刷新时不会影响父组件
class SomeComponent extends Component {
      render() {
         return <Flex>
            <SubOne />
            <SubTwo />
            <SubThree />
          </Flex>
      }
}

2.2 不要用css

关于样式的写法,RN和前端有个显著的差别
RN:

import { StyleSheet } from "react-native";

const styles = StyleSheet.create({
 someContainer: {
    fontSize:16,
    fontWeight: 'bold',
  },
  ...
})

<Flex style={styles.container} />

前端:

// js 文件
import CSSModules from 'react-css-modules';
...

@CSSModules(styles)
...

<Flex className="someContainer">
// css文件
.someContainer{
      font-size: 16px;
      font-weight: bold;
 }

由上面示例可知

  1. 前端的样式是藏在css文件内的,迁移起来需要一一去查找
  2. 关键字命名不同(font-size,fontSize)

而这些不同都需要我们迁移的时候一一手动修改,工作量很大

推荐的写法,是统一使用RN的写法:

// 前端js文件
const styles = { // 这里不需要像RN一样,使用StyleSheet.create
 someContainer: {
    fontSize:16,
    fontWeight: 'bold',
  },
  ...
}

<div style={styles.container} />

2.3 第三方组件

挑选第三方组件要注意

  1. 尽量使用原生,或者antd
  2. 尽量选择支持前端和移动端的
  3. 尽量选择有人维护的
  4. 如果git无人维护或者年代久远,建议将代码copy过来,而不是用npm管理,因为RN和React版本更新的原因,常常需要手动修改部分代码,才能运行,因此直接copy至工程里,比较方便

3 差异

有一些差异是前端和RN天然的差异,需要注意

3.1 Image

加载图片资源在两端写法并不一样,需要手动修改
前端:

<img style={{ width: 98, height: 82 }} src={nullImg} alt="nullImg" />

RN:

<Image style={{ height: 15, width: 15, marginLeft: 10 }} source={{ uri: 'search3' }} />

3.1.1 RN的Image

需要特别注意一下的是,React Native 0.50.3以后,Image不再能包裹child

<Image> // 0.50.3以后,这种写法报错
      {...child...}
</Image>

3.2 Text文本

前端渲染文本有多种标签,<div>,<span>等,但是RN端只有一种<Text>,这在迁移时会带来很大的工作量,文本散落在各个地方,需要人工一一替换。
推荐使用react-intl,这个有Yahoo提供的第三方组件,实现了在前端、RN端的统一

  <FormattedMessage
    style={styles.valueDesc}
    id="someId"
    defaultMessage={text}
  />

3.3 响应事件

前端:

// 可以添加在任何标签上
<div onclick={()=>{}} />
<img onclick={()=>{}} />

RN:

<TouchableHighlight onPress={}>// 只能有一个子元素,且必须是RN原生组件,不能是自定义组件
  <View> // 要用一个View来包裹更多的元素
      {child}
  </View
</TouchableHighlight>

由上可知,点击事件迁移时,常常需要改动较多的代码

  1. 增加TouchableHighlight标签
  2. 原标签下,如果有多个子标签,那么还需要增加View来嵌套,还要注意样式保持不变
  3. onClick改成onPress

3.4 路由跳转

  • 前端使用react-route
  • RN端根据具体情况会有不同选择,例如react-navigationreact-native-navigation

写法上会有不同,需要迁移者根据具体选择的库,手动修改

3.5 PropTypes

PropTypes是React提供的一种类型检测工具,但是随着版本的变迁,从React v15.5起,PropTypes被移出了React,形成了一个单独的库,如果前端和RN两边版本不一致,还有可能需要人工大量修改

// react version < 15.5
import React, { Component, PropTypes } from 'react';

// react version >= 15.5
import React, { Component } from 'react';
import PropTypes from 'prop-types';

3.6 全局变量

前端js代码的运行环境通常是浏览器,浏览器本身提供全局变量window,而RN端则没有,因此不要在前端使用window全局变量,而是要使用导入文件

Bad:

window.someVar = var

Good:

// 新建constants.js文件
const object = {
   website:'http://www.hao123.com',
   name:'好123',
};
export default object;

// 需要使用时导入
import constants from './constansts.js'
<Text>{constants.name}</Text>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343