前端之React实战:建立跨平台的项目架构

本篇为翻译文章,原文地址这里javascript

React/React Native一个很受欢迎的地方在于它可以在不一样平台之间共享业务逻辑,在看完 Desktop, Mobile, and Web app in one project这个项目以后笔者就开始思考应该如何组织项目结构,可以使其在web、desktop(Electron)以及mobile应用之间尽量地共用相同的代码基础,而且保证能在之后的项目中扩展到其余平台。java

文件索引

首先须要认识到在mobile项目与web/desktop项目中最大的代码区别在render()函数中,换言之,咱们所须要作的工做就是将render函数抽象出来,以容许具体平台的工程可使用正确的代码。react

要作到这一点,最简单的方式就是利用React Native的一个内部特性,即在使用import/require导入文件时:android

import File from './File';

React Native的打包器会首先寻找 File.<platform>.js文件,而后再去寻找File.js。这就容许咱们将Android平台的代码放置到 File.android.js, iOS 的放入到File.ios.js, 以及Web平台的代码放入到 File.js, 而不须要改变导入的声明 ./Fileios

Render独立于Component

这种方式适合于能够在多个平台之间共享复杂状态与逻辑代码的状况下,固然,在该示例中有点过于复杂了。不过笔者认为在实际项目中的做用仍是不言自明的。git

基础的组件以下所示:github

class Hello extends Component {  
    constructor(props) {
       super(props);
    }
    render() {
        // Code to render a container with 
        // "Hello, {props.name}" inside of it
    }
}

在web项目中,Render函数以下所示:web

render() {  
    return (<div>Hello, {this.props.name}</div>);
}

而在移动端项目中,Render函数可能以下所示:react-native

render() {  
    return (<View>
        <Text>Hello, {this.props.name}</text>
    </View>);
}

那么整个项目的结构以下所示:app

- index.js
- index.ios.js
- index.android.js
- src/
-- Hello.js
-- HelloRender.js
-- HelloRender.android.js

接下来将各个独立的渲染函数和它们的依赖放置到各自的文件中:

// HelloRender.js
import React from 'react';

export default function (props) {  
    // we would like a pure function, for easy testing
    return (<div>Hello, {props.name}</div>);
}

// HelloRender.android.js
import React, {View, Text} from 'react-native';

export default function (props) {  
    return (<View>
        <Text>Hello, {props.name}</text>
    </View>);
}

最终在咱们的Hello.js文件中:

// This will import our platform-specific render function
import Render from './HelloRender';

class Hello extends Component {  
    constructor(props) {
        super(props);
    }

    render() {
        // Now we call our render function,
        // bound to the context of our component
        // In this case we're only using component props,
        // but later we may desire to access the state or
        // other methods on the component.
        return Render.call(this, this.props, this.state);
    }
}

注意,虽然咱们是针对不一样平台使用了不一样的渲染函数,可是仍是能够共享不少的逻辑控制代码。

Component与模块冲突

上文中一直没有说起一件事,就是应该在哪边引入React / React Native提供的官方的组件,譬如通用的Component这个类。在最新的React v0.14中是分红了react与react-dom两个部分,它的设计思想在于一般的应用只要导入react的模块便可,而在特殊须要的时候能够选择性地导入react-native的模块,不过笔者在本身的试验中没发现这样的解决方法,所以仍是决定用相似于上文说起的抽象render函数的方法。咱们须要建立两个新的文件:

- index.js
- index.android.js
- src/
-- Component.js
-- Component.android.js
-- Hello.js
-- HelloRender.js
-- HelloRender.android.js

接下来,咱们须要根据平台正确地导入不一样的组件,即在新文件中:

// Component.js
export {Component} from 'react';  

// Component.android.js
export {Component} from 'react-native';

最后,在咱们的Hello.js这个统一的文件中:

// import platform-specific component class
import {Component} from './Component';

class Hello extends Component ...

好了,到这里一个完整的跨平台的构建应该是完成了。

相关文章
相关标签/搜索