工程化ReactNative中的页面资源

  就RN生态来说,绝大部分基础组件都能轻松找到开源实现,唯独在地图方面可选项并不多,要么是对系统地图组件的简单封装、要么就是像Mapbox这样使用门槛略高,反而是OpenLayers这样的纯js组件不仅使用简单、功能还强大。

devtools

  嘛…… 唯一的缺点是没有RN封装,需要借助于webview的hybird模式。

  一开始功能简单,就一个单一h5页面,什么逻辑都往里面塞,在源码目录下建个pages文件夹,iOS不用操心,打包时会自动拷贝至ios/assets目录下,Android在打包前需要手工拷贝至android/app/src/main/assets目录,然后使用WebView加载本地html文件即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
renderMap() {
let source = require('../pages/explore.html');
let originWhitelist = ['*'];
if ('android' === Platform.OS && !Global['__DEV__']) {
source = { uri: 'file:///android_asset/pages/explore.html' };
originWhitelist = null;
}
let view = null;
view =
<WebView
ref={(webview) => {
this.webview = webview;
}}
originWhitelist={originWhitelist}
allowUniversalAccessFromFileURLs={true}
source={source}
/>
return view;
}

  等到代码膨胀至几千行滚轮滚着实在太累、就又拆分出来数个功能函数js,但想再继续扩展就有些力不从心了:

  1. 只能使用ES5语法,好多ES6新特性用不上 —— 不是太清楚跟RN的打包怎么集成,也没有太多时间精力去研究;
  2. 页面上第三方组件库引入麻烦;
  3. 功能调试只能使用像是alert、console.log这类原始方法。

框架

  因为最近一直在用vuejs写点别的东西,学习曲线确实平滑,所以就决定是它了,虽然感觉上来说react-native + react似乎会更搭……

集成

  首先自然是用Vue CLI 3创建工程,至于创建、打包过程都略去了,总之是吧得到的dist目录下文件整个当原本的pages目录下文件来用就好了,并没有什么区别。

通讯

  框架更换后原本跟RN通讯的代码也有些小改动(RN一侧无变化):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export default {
...
created () {
// 添加postMessage监听
document.addEventListener('message', this.handleMessage);
},
methods: {
// 发送消息
sendMessage(message) {
if (window.originalPostMessage) {
window.postMessage(JSON.stringify(message));
}
},
// 处理消息
handleMessage(e) {
let message = JSON.parse(e.data);
...
}
}
...
}

地图

  对于OpenLayers的使用,首先安装ol库:npm install ol,然后参考官网实例,引入对应类就可以使用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<template>
<div id="explore">
<div id="map" class="map"></div>
</div>
</template>

<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import Tile from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';

export default {
name: 'Explore',
mounted () {
this.$nextTick(() => {
this.initMap();
});
},
initMap() {
new Map({
layers: [
new Tile({
source: new OSM()
})
],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
})
});
}
}

</script>

  这样,原本RN/h5混杂的工程就被拆分成了2个,就可以像开发vue工程一样开心的使用ES6、乃至typescript、使用npm方便的添加各类支持库了。