今天,学习下RN中的另外一个全家桶套餐架构:dva+React-Navigation,
本文基于react-native:0.55.4,dva-core:^1.3.0,react-navigation:^2.5.1,react-navigation-redux-helpers:^2.0.4,react-redux:0^5.0.7所撸.

react-native的官方dva-demo
dva官方github

废话不多缩,首先,新建一个项目,添加一堆相应库:
npm install mobx dva-core --save 引入dva
npm install mobx react-navigation-redux-helpers --save 引入react-navigation-redux-helpers
npm install mobx react-redux --save 引入react-redux
npm install babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0 --save-dev 能够使用@标签
npm install react-navigation --save 引入导航库
然后修改一下工程里面的.babelrc:

1
2
3
4
5
{
"presets": ["react-native"],
"plugins": ["transform-decorators-legacy"]
}

OK,基本的架子已经搭好.
然后新建一个src目录.这里存放基本代码和基本图片之类的.
mdva代码结构

然后,在入口文件index.js中,修改一下代码:

1
2
3
4
5
6
7
8
import './App';

console.ignoredYellowBox = [
'Warning: componentWillMount is deprecated',
'Warning: componentWillReceiveProps is deprecated',
'Warning: componentWillUpdate is deprecated',
'Warning: isMounted(...) is deprecated',
]

App.js中基础代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React from 'react'
import { AppRegistry } from 'react-native'

import dva from './src/Utils/dva'
import Router, { routerMiddleware, routerReducer } from './router'
import appModel from './src/models/app'

const app = dva({
initialState: {},
models: [appModel],
extraReducers: { router: routerReducer },
onAction: [routerMiddleware],
onError(e) {
console.log('onError', e)
},
})

const App = app.start(<Router />)

AppRegistry.registerComponent('rn_dva', () => App)

ok,如上图所示,dva的代码相比redux来说少了很多,不在需要大量的赋值粘贴,基本的逻辑代码均可以放在models中,其中的Utils只是dva的一个工具组,其中的代码并不多.一如既往,对着IDE就是一堆疯狂输出.完成的功能和之前的redux和Mobx一样.
models下的app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { createAction, NavigationActions } from '../Utils'

export default {
namespace: 'app',
state: {
num: 0,
mineType: '红',
},
reducers: {
updateState(state, { payload }) {
return { ...state, ...payload }
},
},
effects: {
*add({ payload }, { call, put }) {
yield put(createAction('updateState')({ num:payload ,mineType:'红'}))
},
*sub({ payload }, { call, put }) {
yield put(createAction('updateState')({ num:payload ,mineType:'蓝' }))
}
},
subscriptions: {

},
}

Utils下的dva.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react'
import { create } from 'dva-core'
import { Provider, connect } from 'react-redux'

export { connect }

export default function(options) {
const app = create(options)
// HMR workaround
if (!global.registered) options.models.forEach(model => app.model(model))
global.registered = true

app.start()
// eslint-disable-next-line no-underscore-dangle
const store = app._store

app.start = container => () => <Provider store={store}>{container}</Provider>
app.getStore = () => store

return app
}

Utils下的index.js

1
2
3
4
export { NavigationActions, StackActions } from 'react-navigation'

export const createAction = type => payload => ({ type, payload })

剩下的就是两个UI界面了:
One.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/

import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image
} from 'react-native';
import { connect } from 'react-redux'
import { createAction, NavigationActions } from '../Utils'
import {Images} from "../Image";

const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});

type Props = {};
@connect(({ app }) => ({ ...app }))
export default class One extends Component<Props> {

static navigationOptions = {
tabBarLabel: '苹果',
tabBarIcon: ({ focused, tintColor }) => (
<Image
source={focused ? Images.Tab.OneActive : Images.Tab.One}
style={{ width: 25, height: 25 }}
/>
),
}

render() {
return (
<View style={styles.container}>
<Text onPress={()=>this.add()}>
+ 红
</Text>
<Text>
One {this.props.num}
</Text>
<Text onPress={()=>this.sub()}>
- 蓝
</Text>
</View>
);
}

add =() =>{
this.props.dispatch(createAction('app/add')(this.props.num + 1))
}

sub =() =>{
this.props.dispatch(createAction('app/sub')(this.props.num - 1))
}

componentDidMount() {
console.log(this.props)
}

}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

Two.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/

import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image
} from 'react-native';
import { connect } from 'react-redux'
import { createAction, NavigationActions } from '../Utils'
import {Images} from "../Image";

const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});

type Props = {};
@connect(({ app }) => ({ ...app }))
export default class Two extends Component<Props> {

static navigationOptions = {
tabBarLabel: '安卓',
tabBarIcon: ({ focused, tintColor }) => (
<Image
source={focused ? Images.Tab.TwoActive : Images.Tab.Two}
style={{ width: 25, height: 25 }}
/>
),
}

render() {
return (
<View style={[styles.container,{backgroundColor:this.props.mineType == '红' ? 'red' : 'blue'}]}>
<Text style={styles.welcome}>
TWO + {this.props.mineType}
</Text>
</View>
);
}

componentDidMount() {
console.log(this.props.mineType)

}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

OK,以上就是全部代码.
效果图:
dva-result

源码地址

另外:redux+react-navigation
另外:Mbox+react-navigation