react 移动端项目总结

        最近基本都是在研究及实现react 移动端项目,这里做一个有关react 的总结,以便之后深入理解与使用

       首先react 最初来自Facebook内部的广告系统项目,与之后的Vue 一样,核心解决的问题是数据绑定避免操作大量真实DOM 。本质上还是遵循模块化理念,实现View 层的渲染视图。主要操作包括:模块定义、接口暴露、模块引入、模块调用。它鲜明的一个特性就是组件化开发,通过组件实现视图的渲染。一个组件内可以实现数据请求、H5页面渲染、组件嵌套、传递参数并返回结果等一系列围绕数据进行的渲染操作。

       当然为了达到最终的视图渲染,还需要处理的关键问题是数据的管理。react 提出的是进行状态管理,也就是如何处理state。这里使用的  Redux(与 Redux 对比的flux 区别暂不具体阐述),下面就Redux 做一个简单总结。

       Redux 中可以分为5个主要内容():Store、Action、Components、Routes、Reducer

        也许这张图看的有点懵,这里重点解释一下。从最底端的用户开始,用户看到的实际是组件 components 中的内容,而它的上级Containers 可以简单理解为用户打开的App 或者 小程序这样一个概念。那么这时候会提出一个疑问,components 是视图层,那它的数据会从哪里来?这时再往上追溯到 Store 层,这里从Containers 到 Components 会有一句话,放大了看就是 

       “无论何时当应用的state 改变时,组件会重新被渲染”,而 Container 的上级Provider 说的是,“让所有Container 可以获取到store 里的数据。”   。

 

       这里结合到实际项目中就是,store 作为数据的“存储仓库”,提供给 react-dedux 暴露出来的 Provide 的所有子组件使用(这里暂时不必深究其他组件的作用)。下图给的是移动端里的App.js ,也就是整个项目的入口文件。这里还有一块内容Router 是第一张大图没有提及的。将在文章的最后一部分分析。

import React from 'react';
import { StyleSheet,View,SafeAreaView,Text,Image,Dimensions} from 'react-native';
import {Font,AppLoading} from 'expo';
import { Ionicons } from '@expo/vector-icons';
import { Peoples,HomeScene,DetailsScene,NewsScene,NewsDetailsScene,ProductScene,ProductDetailsScene,UserScene}  from './scenes'
import {Router,Stack,Scene,Tabs}   from 'react-native-router-flux'
import { TabIcon,HomeNavBar,Camera,NewsNavBar,UserNavBar} from './components'
import {Provider} from 'react-redux'
import store from './store'

export default class App extends React.Component {
  state={
    loading:true
  }
  async componentDidMount() {
      await Font.loadAsync({
        'Roboto'       : require('./node_modules/native-base/Fonts/Roboto.ttf'),
        'Roboto_medium': require('./node_modules/native-base/Fonts/Roboto_medium.ttf'),
        ...Ionicons.font,
      });
      this.setState({
        loading:false
      })

  }
  render() {
    if(this.state.loading){
       return <AppLoading />
    }else{
        return (
          <Provider store={store}>
             // Router 路由操作
          </Provider>
        );
    }
  }
}

       而 store 中的内容是:

import { createStore,applyMiddleware } from 'redux';
import reducers from '../reducers'
import thunk from 'redux-thunk';
const store = createStore(reducers,applyMiddleware(thunk));
export default store;

       这里调用 redux 中的两个方法 createStore 和 applyMiddleware ,前者就是字面意思创建 Store,后者是应用组件,而thunk 就是确保之后的内容可以进行异步操作。

       下面是Action 和 Reducer 层。action中的方法被暴露在Component 后,可通过设定方法的专属名称,来找到Reducer 中对应的 action.type ,随后对改方法中的属性进行操作。

Action: 
export const addToCarts = (data)=>{
    console.log(data)
    return {
        type: 'ADDTOCARTS',
        payload:data
    }
}

Reducer:
var initialState = {
    counter : 1,
    lists   : [],
    total   :0
};

function counter(state = initialState ,action){
    // 有且只有一棵状态数,状态是只读的,需要利用纯函数来进行状态的修改
    switch(action.type){
        case 'INCREASE':
            return {...state,counter:state.counter+1};
        case 'DECREASE':
            return {...state,counter:state.counter-1};
        case 'GETLISTS':   // 获取列表,payload 负载
            return {...state,lists:action.payload}
        default:
            return state;
    }
}
export default counter;

        那么下面最后一步是路由操作。这里由于移动端用的是 react Native ,所以在一开始判断loading 属性是否存在时,会先加载一个 <AppLoading /> 组件。这里用到的是 react-base UI 框架。本身react Native 自身会携带一些可用标签。下图的代码是路由的一个示例。路由用的依赖是 react-native-router-flux ,因为 router-flux 用的是 Action 跳转,因此在入口文件的跳转Scene 中要加 path 属性,这样可以在首页部分传入Id 给详情页。这里的原理用到的是栈,不同 Tab 就是一个栈,独立于其他Tab 进行地址的切换。这里每个 Scene 的 key 值唯一,也是Action 跳转的依据。例如 Action.newsDetailsScene() 就从初始化的页面 NewScene 跳转到详情页 NewsDetailsScene。这里的视图都是入口文件定义的组件名称,且注意组件名称一定大写。

render() {
    if(this.state.loading){
       return <AppLoading />
    }else{
        return (
          <Provider store={store}>
              <SafeAreaView style={styles.container}>
                  <Router>
                      <Tabs key="tabbar" activeBackgroundColor="white">
                        <Stack key="news" title="新闻" icon={TabIcon} iconName="newspaper-o">
                          <Scene
                          key       = "newsDetailsScene"
                          path={"/newsDetailsScene/:id"}
                          component = {NewsDetailsScene}
                          title     = "详情页"
                          />
                          <Scene key="newsScene" component={NewsScene} title="新闻" navBar={NewsNavBar} initial />
                        </Stack>
                      </Tabs>
                  </Router>
              </SafeAreaView>
          </Provider>
        );
    }
  }

       为了更清晰给出移动端项目的逻辑结构,给出下图。简单说来就是同 mapDispatchToProps 暴露方法,mapStateTopProps 暴露属性,通过connect 将属性与方法注入到组件中。

         整个移动端做下来的感觉是,数据不完全通过reducer 、action  层获取,直接axios 获取json-server 中的数据也可以,除非当前页面涉及到多个模块的相互引用。当然在过程中还发现,如果要做轮播图,可以用 swiper ,但是要做线性渐变效果、瀑布流等效果,现有的 JS 编码开发环境还是达不到想要的效果。这里react Native 还有另外一种开发模式。就是 JS编码+原生代码 结合模式开发环境。环境安装及配置更为复杂 不仅需要了解React Native相关的编码规范 需要熟悉Android Studio/Xcode原生开发软件 需要了解Java/Objective-c/Swift原生开发程序。这之后在下一轮的学习计划中,会尝试与 Java 结合有进一步的尝试。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值