ReactNative開發的一些經驗

ReactNative開發的一些經驗

本文主要是本人從Android原生到開發出一套完整的RN模塊嵌入原生的經驗。react

state與props

他們兩者是RN的數據核心。state主要是自身數據更新,props主要是父組件傳入到子組件中使用,也會有自身的默認props。 對於props,建議通常都傳入子組件,防止之後進行修改。特定的flag則進行指定,好比:有一個Page A,他包含Component Bgit

A extends Component{
...
render(){
    return (
        ...
        <B url=this.state.url {...this.state}/>
        ...
    );
}
...
}
複製代碼

對於State,須要注意死循環,這種狀況可能發生在render過程(不是事件響應過程),假如在渲染過程當中,咱們須要修改state,通常先進行判斷,而後再去設置,不然可能一直死循環render好比下面的ImageHolderComponent例子。github

Component

在RN中,提倡組件化。他是能夠根據UI劃分組件,對於底層組件,咱們須要實現邏輯不須要實現業務。好比,對於styles,咱們通常須要提供一個默認樣式,而後再經過外部插入的props樣式,經過數組組合一塊兒,外部能夠覆蓋內部。 例如,下面例子是定義一個通用的Image組件,他能夠在圖片加載失敗或者是URL爲空等適合顯示出place holder圖片。json

export default class ImageHolderComponent extends Component {
    static defaultProps = {
        url: "",
        imageStyle: {},
        holderResizeMode: "cover"
    };

    constructor(props) {
        super(props);
        this.state = {
            loadState: 0
        }
    }

    _emptyUri = () => {
        return <Image
            resizeMode={this.props.holderResizeMode}
            source={this._holder()}

            style={[{
                width: 60,
                height: 60,
                borderRadius: 60,
            }, this.props.imageStyle]}/>;
    };

    _normal = () => {
        return <Image
            source={{uri: this.props.url}}
            defaultSource={this._holder()}
            onError={() => {
                if (this.state.loadState === 1) {
                    //防止死循環
                    return;
                }
                this.setState({loadState: 1});
            }}
            onLoad={() => {
                if (this.state.loadState === 2) {
                    ////防止死循環
                    return
                }
                this.setState({loadState: 2});
            }
            }
            style={[{
                width: 60,
                height: 60,
                borderRadius: 60,
            }, this.props.imageStyle]}/>;
    };

    _holder = () => {
        const {holder} = this.props;
        if (holder) {
            return holder();
        }
        return require("../../img/pic_empty_data.png");
    };

    render() {
        const showView = this.props.url && (this.props.url.indexOf("http") >= 0) && this.state.loadState !== 1 ? this._normal() : this._emptyUri();
        return (
            <TouchableWithoutFeedback onPress={() => {
                const {onPress} = this.props;
                if (onPress) {
                    onPress(this.props.url);
                }
            }}>
                {showView}
            </TouchableWithoutFeedback>
        );
    }
}
複製代碼

他須要外部傳入一個url便可,假如須要複寫樣式則傳入參數名爲imageStyle的style便可。 這樣子,就作到Component獨立,又能與外部進行交互。redux

fetch封裝

由於fetch是返回一個Promise的,因此仍是比較友好的。 咱們能夠對fetch進行一個比較好的封裝,需求是:react-native

  1. 外部須要傳入參數便可
  2. 返回一個Promise
  3. 對於基本錯誤,咱們可以catch返回。
function _body(method, params) {
    const _params = JSON.stringify(params);
    console.log(("http=> params = " + _params));
    return {method: method, headers: HEADER, body: _params}
}


function _get(url, params) {
    return _request(url, _body("GET", params));
}


function _post(url, params) {
    return _request(url, _body("POST", params))
}

//發起請求
function _request(url, params, timeout) {
    console.log(("http=> url = " + url));
    const request = fetch(url, params)
        .then(result => {
            if (result.ok) {
                console.log(("http=> respond = " + result.json()));
                return result.json();
            } else {
                return Promise.reject({code: -1, message: "請求失敗"});
            }

        })
        .then(value => {
            //能夠進行進一步刷選
            return value;
        })
        .catch(error => {
            return Promise.reject(error);
        });
    return _wrapRequest(request, timeout)
}

//設置超時,默認10000
function _wrapRequest(promise, timeout = 10000) {
    return Promise.race([promise, new Promise(function (resolve, reject) {
        setTimeout(() => {
                reject({code: -1, message: "請求超時"});
            },
            timeout);
    })]).catch(e => {
        return Promise.reject(e)
    })
}

複製代碼

好比對於登錄而言數組

//登錄
function _body(password,username) {
    const params = {};
    params[USER_NAME] = username;
    params[PASSWORD] = password;
    ....
    return _post("loginurl",params)
}

複製代碼

就能夠了。promise

啓用代碼檢測

我的認爲這個仍是比較有必要的,這樣子能夠統一代碼風格,什麼分號,括號,無用導入,一些可能出現錯誤的地方,經過ESLint均可以檢測出來。須要能夠前往ReactNativeDemo 查看.eslint文件和package.json文件。緩存

分包+代碼

在開發中,通常獨立頁面使用Page結尾,通常組件使用Component結尾。 對於對內方法添加下劃線,對外方法就不用,仍是使用駝峯的命名規則。 通常,咱們儘可能使用解構賦值取數據,這樣子能夠給一些默認值。bash

方法問題

在RN中,他相對於CSS頂層的this是window,RN頂層的this是自己Component,因此咱們儘可能使用方法變量而不是定義方法,這樣子他就能夠自動綁定this了。例如

A extends Component{
    //不推薦
    methodA(){
        //...
    }
    
    //推薦
    methodB = ()=>{
        //。。
    }
}
複製代碼

navigate

咱們進行頁面跳轉的時候,好比使用的是react-navigation,咱們儘可能帶一個from這樣子一個key,value是該頁面的String值。這樣子方便下一個頁面不管是goback仍是navigate去別的頁面在過把存款都比較好操做

Android物理back鍵

對於Android物理back鍵,咱們可能在特殊的頁面須要進行特殊處理,好比back的時候須要彈窗什麼的。 可是,在RN中,好比一個需求是A.navigate(B),而後B.navigate(C)。假如是有這樣子一個跳轉關係,在B中須要監聽back鍵,這時候在C中沒有監聽,在C中按下back鍵就會把B也結束掉,由於B中的監聽並無被移除,而在C中,他是沒有處理back event的返回值的,致使B響應了,就連續返回了。 須要處理該問題,咱們就須要定義一個BaseComponent,之後每個獨立頁面Page,都須要繼承該Component,假如是有特殊處理的,須要注意super。

function log(msg) {
    console.log("BaseComponentPage==>" + msg);
}

export default class BaseComponentPage extends Component {
    constructor(props) {
        super(props);
        log("addEventListener hardwareBackPress");
        BackHandler.addEventListener("hardwareBackPress", this._onBackPress);
    }
    //子類須要重寫該方法到時候,必須super
    componentWillUnmount() {
        log("removeEventListener hardwareBackPress");
        BackHandler.removeEventListener("hardwareBackPress", this._onBackPress);
    }

    _onBackPress = () => {
        this.props.navigation.goBack();
        log("_onBackPress");
        return true;
    };
}

複製代碼

經常使用第三方開源Package

  • react-navigation 導航
  • react-native-router-flux 導航,他更加友好的封裝了react-navigation
  • react-reduxreduxredux-loggerredux-thunk redux全家桶
  • react-native-scrollable-tab-view 能夠作到相似Android的TabLayout
  • prop-types 類型檢測
  • react-native-video 視頻播放
  • react-native-image-zoom-viewer圖片縮放
  • react-native-fetch-blob 網絡請求,也能夠本身直接封裝一下fetch。
  • react-native-cached-image 圖片緩存+顯示
相關文章
相關標籤/搜索