在React Native 中因爲業務的須要, 咱們每每要在諸多的頁面間,組件之間作一些參數的傳遞與管理, 在這裏我總結了幾大通過驗證,穩定好用的方式給你們react
推薦指數: ♥ ♥ ♥ ♥ ♥
適用範圍: 相鄰頁面間傳值
兼容性: IOS/Android
原理: React Navigation 爲頁面的 props 上掛載了 navigation 對象, 可用來作路由跳轉,在作頁面跳轉時能夠攜帶參數/回調方法前往目標頁面, 從而達到傳參的目的
說明: 這是官方推薦,也是咱們在業務開發中用得最多,最爲推崇的一種傳參方式, 思想與 web 在 querystring 上帶參跳轉相似,只是實現方式略微不一樣, 舉例:web
導航傳值便可正向傳值,也可反向傳值 例如 A->B 是正向傳值, 而B->A 則是反向傳值 正向傳值: A頁面跳轉向B頁面, 在組件內經過訪問 this.props.navigation.navigate('B', { type: 'list', callback:data => { console.log('data in callback: ', data); } }); 在B頁面 就能在組件的生命週期函數中拿到值 componentWillMount() { const { state: { params: { type, callback }, goBack }} = this.props.navigation; console.log('type: ', type); // type 'list' } 反向傳值: 在反回前一個頁面時, 手動調用callback,並給其傳參, 再調用 goBack 方法, 便可達到目的。 仍是上面的例子: 當從B返回A的時候 goBackToPageA: () => { const { state: { params: { type, callback }, goBack }} = this.props.navigation; callback({ id: '123', message: type + ' really?'}); goBack(); } goBackToPageA(); 回到A頁面後 'data in callback: ', { id: '123', message: 'list really?'}); 也即callBack 中的 data 參數就是 { id: '123', message: 'list really?'}
推薦指數: ♥ ♥ ♥ ♥
適用範圍: 頁面間傳值/組件間傳值
兼容性: IOS/Android
原理: 利用 React Native 包中提供的 DeviceEventEmitter 模塊訂閱事件,觸發事件,同時傳值
說明: DeviceEventEmitter 從名字就能知道他是基於事件訂閱的機制來進行傳值的, 當訂閱某種事件後, 觸發的時候會調用訂閱事件的回調, 並能把值傳送過去, 而且在同頁面內的組間件, 不一樣頁面間均可以傳值, 但前提是頁面還未被銷燬(銷燬後事件的訂閱會取消), 例如:數組
DeviceEventEmitter.addListener('warning_event', (data) => { console.log('data: ', data);}) DeviceEventEmitter.emit('warning_event', { name: 'Mega Galaxy'}); // data: { name: 'Mega Galaxy' } 在emit(觸發)事件後, 回調函數的入參就變成了咱們所傳遞的 { name: 'Mega Galaxy'}, 也可不傳值,不傳值時 callback 的入參就是 undefined
缺點: 本質是對自定義事件的監聽與觸發, 當頁面邏輯複雜時,代碼量會增多, 維護成本變高, 且監聽過多會形成性能問題, 還有一點就是在頁面銷燬時必須移除監聽: 若是忘記移除監聽會怎麼樣? 那每當 emit 事件一次, 就會多響應一次你加上去的監聽app
componentDidMount() { this.eventHandler = DeviceEventEmitter.addListner('event_name', callback); } componentWillUnmount() { this.eventHandler.remove(); }
我的建議: 在梳理清楚頁面邏輯後,合理使用異步
推薦指數: ♥ ♥ ♥ ♥
適用範圍: 跨頁面 跨組件的任性傳參
兼容性: IOS/Android
原理: 利用相似 web 中 localStorage 的思想,將參數/數據存放在 AsyncStorage中,在須要的地方再取出來
說明: localStorage 在 web 中的實用性 與 受歡迎程度你們是知道的, AsyncStorage其實就是 rn 版的 localStorage, 略微不一樣的是它是異步的,只返回 Promise, 因此與 async/await 結合會很是好用async
···ide
在A頁面 saveOrderData = async () => { try { const orderData = [{ id: 1, data: []}, { id: 2, data: []}] await AsyncStorage.setItem('Order_data_cache', JSON.stringify(orderData )); } catch (error) { // Error saving data } } 在B頁面 loadOrderData = async () => { const __orderData = await AsyncStorage.getItem('Order_data_cache'); const orderData = JSON.parse(__orderData); this.setState({ orderData }); }
缺點: 以 Key-Value 式的存儲傳參,可能重點仍是在數據存儲上, 且由於涉及到 I/O 的操做,在部份低端機型上,有卡頓的可能性函數
推薦指數: ♥ ♥ ♥
適用範圍: 不一樣頁面內的組件共享公共類的數據
兼容性: IOS/Android
原理: 利用生成的數據倉庫包裹父級組件, 再從子組件中獲取數據倉庫中的數據
說明: Context Api 在管理登陸用戶數據這類具備公共屬性的數據是一把利器, 但使用起來會至關繁瑣性能
const ContextWrapper = React.createContext(); <ContextWrapper.Provider value={{ name: 'Mega Galaxy', job: 'FrontEnd Engineer' }} <App /> <ContextWrapper.Provider> // 注意這裏的 <App /> 是指咱們 App的根組件,在包裹根組件後 咱們能夠在任意子頁面組件 中取值 任意 <App /> 裏的子頁面組件中 <ContextWrapper.Counsumer> { context => <Text> { context.name } { context.job }</Text> } </ContextWrapper.Counsumer> 會渲染成 <Text> Mega Galaxy FrontEnd Engineer </Text>
缺點: 理解須要花一些功夫, 寫法繁瑣,且只適合特定類型的數據,要明確組件間的包裹關係this
推薦指數: ♥ ♥ ♥
適用範圍: 頁面間傳值(全局任意頁面)
兼容性: IOS/Android
原理: 利用 Node.js 中的頂級對象 -- Global. 來掛載屬性, 利用屬性傳值
說明: 在跳轉的頁面前,能夠把須要傳遞的參數掛載在 Global 對象上, 在跳轉後便可在 Global 對象上訪問鍵取到對應的值, 例如:
在 A 頁面: Global.params = { name: 'Jalon', id: '123456'}, 跳轉任意頁面後: Global.params // { name: 'Jalon', id: '123456'} 除了字值串,布爾值,對象 和 數組, 也能夠傳遞函數, 若是傳遞的函數有引用組件上下文環境的變量,注意解耦,不然可能會報錯.
缺點: 若是掛載的屬性/方法過多 易形成衝突與污染, 不利於維護
我的建議: 在 react-navigation 跳轉傳值 與 DeviceEventEmitter 維護不方便的狀況下才使用, 但儘可能少用, 以避免形成全局屬性的污染與衝突
總結了5種常見的參數/數據傳遞的方法,以我的角度來看, 推薦順序爲 React Navigation 導航傳值 > DeviceEventEmitter 觸發事件並傳值 > AsyncStorage Key-Value 式的存儲傳參, 最後 兩種是在特殊場景下才會去使用,因此在合適的場景去選擇合適的方式傳值,會爲React Native項目的開發帶來事半功倍的效果.