前端之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 ...

好了,到這裏一個完整的跨平臺的構建應該是完成了。

相關文章
相關標籤/搜索