美文网首页
react-native-dva-starter: 集成 dva

react-native-dva-starter: 集成 dva

作者: 静夜秋雨 | 来源:发表于2018-02-07 16:34 被阅读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>
    

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

    相关文章

      网友评论

          本文标题:react-native-dva-starter: 集成 dva

          本文链接:https://www.haomeiwen.com/subject/cnsizxtx.html