基于react-native & antd-mobile进行三端开发

要做移动端应用,同时要适配ios、android和微信。搜索、试验、思考...几天内进行了好几轮,最终决定采用react-native & antd-mobile来实现我们的目的。

思路&选择

在网上搜索,看到了多种方案。第一种,利用redux,共享业务逻辑,自己维护两套UI组件;第二种,利用react-native-web,先写移动端,再将移动端转换成H5;第三种:利用styled-components来封装UI组件,也要维护两套UI;第四种:利用antd-mobile来适配三端。
最终决定选择antd-mobile方式,因为其本身就是一套很好的解决方案,文档较全,实现方式简单,虽然是两套代码,但现有组件已经很多,也容易扩展。我已经修复了一个小bug,自行发布到了npm,并替换到项目中,这样能够快速方便的实现自己想要的组件。

代码编写原则

所有的界面元素都使用antd-mobile的组件来实现,不够用的,不符合要求的,直接改动antd-mobile。

关键步骤

webpack2配置

antd-mobile要支持H5,在要webpack中进行配置,打包web版的代码。

import antd-mobile

{
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: [{
                    loader:'babel-loader',
                    options:{
                        presets: ['es2015', "stage-2", 'react'],
                        plugins: [ ["transform-runtime"],["import", {libraryName: "antdm", style: true}]
                        ],
                    }
                }],
            },

resolve web.*

resolve: {
        mainFiles: ["index.web","index"],// 这里哦
        modules: ['app', 'node_modules', path.join(__dirname, '../node_modules')],
        extensions: [
            '.web.tsx', '.web.ts', '.web.jsx', '.web.js', '.ts', '.tsx',
            '.js',
            '.jsx',
            '.react.js',
        ],
        mainFields: [
            'browser',
            'jsnext:main',
            'main',
        ],
    },

布局组件

antd-mobile文档中只提了复杂的组件,但我们在H5中经常用的div与native中的View应该如何处理呢?看文档、搜索,都没有找到我想要的方法;在github中看别人家的代码,发现都是直接用了div或native的View,不能同时适配三端。以至于我一度想引入styled-components来封装,但总觉得引入styled-components只用来处理几个基本元素,不划算。最后是想起来要看看antd-mobile的源码,在antd-mobile中来做引入styled-components做的事,不就可以了吗!结果发现antd-mobile已经有封装了,就是View。

问题基本解决了,但运行时会有如下的警告信息:

Warning: Unknown prop `Component` on <div> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
    in div (created by View)
    in View (at Root.js:15)
    in Provider (at Root.js:14)
    in Root (at index.js:20)
    in AppContainer (at index.js:19)

看源代码,是有个小bug,顺手修改了,编译,运行,问题解决。提交pull requests,人家不可能很快的更新,而且可能有的改动只是为了适应我们自己的项目,因此发布到npm中,名字叫antdm。

程序入口

入口文件会有三个,原则是尽量保持简单

ios:index.ios.js

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';
import Root from  './src/containers/Root';
import configureStore from './src/store/configureStore.js';
const store = configureStore();
class T3 extends Component {
    render() {
        return (
            <Root store={store}/>
        );
    }
}

AppRegistry.registerComponent('t3', () => T3);

web:/src/web/index.js

import React          from 'react';
import { render }     from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import Root           from '../containers/Root';
import configureStore from '../store/configureStore';
const store = configureStore();
render(
  <AppContainer>
    <Root store={store} />
  </AppContainer>,
  document.getElementById('root')
)

android:index.android.js

还未编写,应该与ios差不多。

项目地址

https://git.oschina.net/zhoutk/t3.git
https://github.com/zhoutk/t3.git

使用方法

git clone https://git.oschina.net/zhoutk/t3.git
or git clone https://github.com/zhoutk/t3.git
cd t3
npm i
ios: npm run ios
web: npm run web

小结

利用react-native和antd-mobie基本达到移动端适配三端的要求,但在做项目的同时,可能需要基于antd-mobile逐步建立起一套适合自己的UI组件。谢谢阿里的兄弟们!