react-native-dva-starter: 集成 dva

2018-02-07  本文已影响0人  静夜秋雨

前言

本教程是使用 create-react-native-app 创建基于 dva,react-native,antd 的 react-navigation 综合案例

相关的 react-navigation的配置请参考 https://www.jianshu.com/nb/21581559
下面用到了 修饰器 @connect() 请参考 阮大爷的教程 http://es6.ruanyifeng.com/
如果对 dva 不是很了解 请参考 https://www.jianshu.com/nb/20964535
或者 官方文档https://github.com/Sawyer-china/dva
本文案例地址:https://github.com/Sawyer-china/react-navigation-dva-antd
现在我们就开始一步一步的构建 如遇见问题可 添加 qq群:218618405 进行提问

如果你觉得该文章对你有帮助加个喜欢,github 加个 start 谢谢

1. 创建项目 react-native-dva-antd

create-react-native-app 的安装方式我就不在阐述,如果有问题欢迎 + QQ群进行咨询

$ create-react-native-app react-native-dva-antd

进入工程目录

$ cd react-native-dva-antd 

运行

$ yarn start  
// 如果遇到管理员权限问题:
// error: EACCES: permission denied, open '/Users/ectouch/.expo/log'  
// 使用 sudo yarn start

使用 expo 扫码查看项目运行效果

2. 引入我们需要的基础包

$ yarn add dva react-navigation@1.0.0beta.27 antd-mobile react-redux react-native-vector-icons react-dom --save

注:react-navigation 版本请以 react-navigation@1.0.0beta.27为准,版本高了会有意外的情况发生

3. 创建 Home 页面

在根目录下面创建 containers 的文件夹然后 创建 Home.js 文件 并写入以下代码

import React, { Component } from 'react'
import { StyleSheet, View, Text } from 'react-native'
import { connect } from 'react-redux'
import { Button } from 'antd-mobile'
import Ionicons from 'react-native-vector-icons/Ionicons'

// @connect()  es7 的语法 修饰器 如果对这个不是很了解请看 阮大爷的 教程  http://es6.ruanyifeng.com/
@connect()
class Home extends Component {
    static navigationOptions = {
        title: 'Home',
        tabBarLabel: '首页',
        tabBarIcon: ({ tintColor, focused }) =>
            // focused 当前 tab 被选择  !focused  未被选中
            // tintColor tabNavigator 传入的配置颜色
            <Ionicons
                name={focused ? 'ios-home' : 'ios-home-outline'}
                size={26}
                style={{ color: tintColor }}
            />
    }

    render() {
        return (
            <View style={styles.container}>
                <Text style={{ marginBottom: 20 }}>这是首页</Text>
                <Button type="warning">default</Button>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    },
    icon: {
        width: 32,
        height: 32
    }
})

export default Home

创建 Cart.js, Category.js, Search.js, User.js 页面 请查看
github: https://github.com/Sawyer-china/react-navigation-dva-antd

4. 在根目录创建 router.js

import React, { PureComponent } from 'react'
import {
    BackHandler,
    Animated,
    Easing,
    View,
    Text,
    StyleSheet,
    ActivityIndicator
} from 'react-native'

import {
    StackNavigator,
    TabNavigator,
    TabBarBottom,
    addNavigationHelpers
} from 'react-navigation'

import { NavigationActions } from '../utils'

import { connect } from 'react-redux'

import Home from './containers/Home'
import Cart from './containers/Cart'
import User from './containers/User'
import Category from './containers/Category'
import Search from './containers/Search'

const Loading = () =>
    <View style={styles.container}>
        <ActivityIndicator />
    </View>

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    }
})

const HomeNavigator = TabNavigator(
    {
        Home: { screen: Home },
        Category: { screen: Category },
        Cart: { screen: Cart },
        User: { screen: User }
    },
    {
        tabBarComponent: TabBarBottom,
        tabBarPosition: 'bottom',
        swipeEnabled: false,
        animationEnabled: false,
        lazyLoad: true,
        tabBarOptions: {
            activeTintColor: '#ff0000'
        }
    }
)

const AppNavigation = StackNavigator(
    {
        Home: {
            screen: HomeNavigator
        },
        Search: { screen: Search }
    },
    {
        headerMode: 'screen'
    }
)
@connect(({ router }) => ({ router }))
class Router extends PureComponent {
    render() {
        const { dispatch, app, router } = this.props
        const navigation = addNavigationHelpers({ dispatch, state: router })
        return <AppNavigation navigation={navigation} />
    }
}

export function routerReducer(state, action = {}) {
    return AppNavigation.router.getStateForAction(action, state)
}

export default Router

并创建 models/router.js 的 model 和 utils/dva.js 请参考github 地址
router文件是 router 的相关信息
dva 是启用这个项目的文件

5. 修改 根目录 App.js 文件

import React, { Component } from 'react'

import dva from './utils/dva'
import Router from './router'

// import appModel from './models/app'
import routerModel from './models/router'

const app = dva({
    initialState: {},
    models: [routerModel],
    onError(e) {
        console.log('onError', e)
    }
})

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

export default App

6. 如何进行页面跳转

打开Home.js页面

<Button
    type="warning"
    onClick={() => {
       this.props.dispatch(
            NavigationActions.navigate({ routeName: 'Search' })
       )
    }}
>
    点我到搜索页面
</Button>

6. Ionicons 的使用方式

Ionicons 是一个字体库 使用方法如下所示:
实际打包时你需要集成该字体包才可能正确的打包 应用 ,
具体用法可百度 react-native-vector-icons

......
import Ionicons from 'react-native-vector-icons/Ionicons' 
// 因为我们在创建项目的时候已经安装了该包了,所以可以直接引入
......
class Home extends Component {
    static navigationOptions = {
        header: null,
        tabBarLabel: '首页',
        tabBarIcon: ({ tintColor, focused }) =>
            // focused 当前 tab 被选择  !focused  未被选中
            // tintColor tabNavigator 传入的配置颜色
            <Ionicons
                name={focused ? 'ios-home' : 'ios-home-outline'}
                size={26}
                style={{ color: tintColor }}
            />
    }
......
}

7. 在案例中实现登录退出的基本原理

(登录页面我们会用到本地存储的功能)
安装有reactnative 中文网提供的本地存储插件

$ npm install react-native-storage --save

创建 app models (在models目录下创建 app.js)

export default {
    namespace: 'app',
    state: {
        isLogin: false // 登录状态
    },
    reducers: {
        
    },
    effects: {
    }
}

修改User.js页面 render 函数中的 return

如果页面登录了,就显示退出登录按钮,否则显示 我要登录

return (
            <View style={styles.container}>
                <Text style={{ marginBottom: 20 }}>会员中心</Text>
                {!isLogin
                    ? <Button
                          type="warning"
                          onClick={() => {
                              this.props.dispatch(
                                  NavigationActions.navigate({
                                      routeName: 'Login'
                                  })
                              )
                          }}
                      >
                          我要登录
                      </Button>
                    : <View>
                          <Text style={{ marginBottom: 20 }}>您已经登录了</Text>
                          <Button
                          type="warning"
                          onClick={() => {
                              console.log('退出成功')
                          }}
                      >
                        退出登录
                      </Button>
                      </View>}
            </View>
        )

在 Login.js 页面中添加 onLogin 方法 调用 models/app.js 中的login 改变状态

...
onLogin = () => {
    this.props.dispatch({ type: 'app/login' })
}
...
<Button type="ghost" onClick={this.onLogin}>
    确认登录
</Button>
修改 models/app.js

增加 state状态

state:{
    isLogin: false,
    fetching: false // 加载进度条
}

增加 login 方法

*login({ payload }, { call, put }) {
            yield put({ type: 'updateState', payload: { fetching: true } })
            const login = yield call(authService.login, payload)
            if (login) {
                yield put({
                    type: 'updateState',
                    payload: { isLogin: true, fetching: false }
                })
                yield put(NavigationActions.back())
            }
        }

修改 containers/Login.js 页面增加活动指示器

import { Button, ActivityIndicator } from 'antd-mobile'

...
render() {
        const { fetching } = this.props
        return (
            <View style={styles.container}>
                <ActivityIndicator
                    text="正在加载"
                    toast={true}
                    color="#ff0000"
                    animating={fetching}
                />
                <Text style={{ marginBottom: 20 }}>我是登录页面</Text>
                <Button type="ghost" onClick={this.onLogin}>
                    确认登录
                </Button>
            </View>
        )
    }
增加退出功能

修改 models/app.js 增加logout方法

*logout({ payload }, { call, put }) {
    yield put({ type: 'updateState', payload: { isLogin: false } })
}
修改 containers/User.js

增加 logout 方法

logout = () => {
    this.props.dispatch({ type: 'app/logout' })
}

修改 退出登录 按钮的事件

<Button type="warning" onClick={this.logout}>
    退出登录
</Button>

(未完待续...)
下面会为大家分享 本地存储的使用

上一篇下一篇

猜你喜欢

热点阅读