脚本宝典收集整理的这篇文章主要介绍了React-Native 与 React-Web 的融合,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
关于
对于react-native在实际中的应用, facebook官方的说法是react-native是为多平台提供共同的开发方式,而不是说一份代码,多处使用。 然后一份代码能够多处使用还是很有意义的,我所了解到的已经在尝试做这件事情的:
现阶段大家都是在摸索中,且react-native 还不够成熟,为此我也想通过一个实际的例子提前探究一下共享代码的可行性。
下面是我以SampleApp做的一个简单demo, 先奉献上截图:
web 版本:
react-native版本:
初步想法
组件
react-native基本上是View套上Text这样来布局,为了做web和native的兼容,我们得提供继承版本的View ,针对不同的平台返回不同做兼容,我们将提供:
- Share.View -> View (reac-native = View , web = div)
- Share.P + Share.Span -> Text (Text在react-native中分为块级别和inline级别所以得用两个元素来区分)
样式
我们知道react-native的样式是css很小的一个子集,大概支持50种属性,为了做到web和native使用同样地样式,那么我的想法是:
- 使用css文件来编写样式,通过编译的方式生产不同平台需要的样式
- 对于web,使用auto-prefixel处理,生产web兼容的css代码
- 对于react-native,生成对应的styles.js
- css的写法用OOCSS的方式
这样做的另外一个原因是,因为css是全集,react-native是子集,全集到子集可以通过删减来处理,但是如果想通过子集到全集就会很麻烦(react-style就是通过react-native来生成css)。 且这样做还有很多好处,例如我们可以支持react-native里边不支持的css写法,例如padding: a b c d;
这种写法很容易得到兼容。
其实这里,无论react-native还是react-web都支持style={}
这样的写法. 上面例子中的web截图其实是没有引用css的,但inline样式对于web来说并不是优选。
实现思路
首先大概整理一下我们需要解决的问题:
- 如何区分web和native
- js如何对应不同的平台来编译,因为react-native使用的是自己的依赖管理packager
- css如何编译为js
- 代码结构应该是怎样的
问题一 : 如何区分web和native
react-native 里边会有window变量吗?我试了一下,是有的,那window变量里边不可能有location,document之类的吧, 借着这种想法,可用如下方法来区分native和web
var isNative = !window.location;
问题二:如何对应不同平台打包
对于react-native,是通过packager来打包的,具体的实现和逻辑可以随时查看packager的readme文档。 那我们怎么将适用于native的代码打包成web的代码,首先想到的是browserify
, webpack
。 都是遵循commonJs规范,个人更喜欢前者, 用它来应该足以满足需求。
问题三: css如何编译为js
前面提到了native-css
, 可以用它来帮助我们完成打包。
问题四:代码结构应该是怎样的
web和native的代码都写在同一个地方,如何做区分呢? 这个问题当然最好就是不做区分,或者就像女生的衣服,期望是越少越好,但永远不可能木有(猥琐了:-】)。
我设想中的一个最简模型的目录结构,web和ios有不同的入口,web和ios有单独的目录, 组件共享, 如下:
├── compo.js // 我们会使用到得公共组件
├── styles.css // compo的样式文件
├── index.web.js // web 入口
├── index.ios.js // ios 入口
├── shared.js // 做兼容的共享变量文件
├── ios // ios 目录
└── web // web 目录
├── index.html // web 页面
├── index.web.js // 打包过后的js
└── react.js // react.js依赖
好像很复杂的样子, 其实相对于原本的SampleApp,只是多了index.web.js
, web目录
, shared
三者。 然后style通过style.css来描述。
具体实现
我们已经整理了具体的实现思路,下面是我就会直接吐出我的实现代码, 重点的地方都会在源码里边有注释
先看应用代码:
ios入口:index.ios.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require('react-native');
var Compo = require('./compo');
React.AppRegistry.registerComponent('ShareCodeProject', () => Compo);
web入口:index.web.js
/**
* for web
*/
var Compo = require('./compo');
React.render(<Compo />, document.getElementById('App'));
样例组件:compo.js
// 依赖的公共库,通过它获取兼容的组件
var Share = require('./shared');
// styles是style.css build过后生成的style.js
var styles = require('./styles');
var React = Share.React;
var {
View,
P,
Span
} = Share;
var Compo = React.createClass({
render: function() {
return (
<View style={styles.container}>
<P style={styles.welcome}>
Welcome to React Native!
</P>
<P style={styles.instructions}>
To get started, edit index.ios.js
</P>
<P style={styles.instructions}>
Press Cmd+R to reload,{'n'}
Cmd+Control+Z for dev menu
</P>
</View>
);
}
});
module.exports = Compo;
组件样式: style.css
/**
* 大家可能发现了css的写法还是小驼峰,是的不是横杠,暂时我们还是以这种方式处理
* native-css 目测不支持横杠,(自己重写native-css相对来说是比较容易的,完全可以做到css兼容到react-native的css子集)
*/
.container {
flex: 1;
justifyContent: center;
alignItems: center;
backgroundColor: #F5FCFF;
}
.welcome {
fontSize: 20;
textAlign: center;
margin: 10;
}
.instructions {
textAlign: center;
color: #333333;
marginBottom: 5;
}
index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello React!</title>
<script src="./react.js"></script>
<!-- No need for JSXTransformer! -->
</head>
<body>
<div id="App"></div>
<script src="./index.web.js"></script>
</body>
</html>
Share部分的处理
shared.js