React-Native -Redux
首先,非常高兴能够接触到React-Native此项技术。来自外星的React-Native,零零散散的学习了一番,感觉非常强大,不仅能够和原生UI与模块进行交互,灵活自如,还能够热更新,不用再等待苹果的审核啦。
唯一让我感觉到非常困惑的是,React-Native对内存的要求非常高,我发现当加载视图的时候,内存飚的特别厉害,这可能是需要值得突破的位置。
总结React-Native:
1.热更新无疑是最大的优势
2.开发周期变短,运用JSX(熟练后)
3.效率提高,正因为用了原生的视图UI,与AngularJS比起来高许多。
本文介绍Redux。
Redux 在学习1个星期后,由最懵懂到思路清晰,经过很漫长的过程。可能是由于从MVC的架构转过来,也没有编写过网页的基础,导致很难接受这种模式。其实Redux就像MVC框架一样,是用来解决代码冗余,代码逻辑的一种状态机,因为可以实时的更新视图,刷新等,让他成为了一种目前比较火热的控制React-Native的一种方式。
接下来由以下程序来进行讲解:
1.首先,我们需要创建四个文件夹:Action,Reducers,Component,Contaniner。
Action:存放的是界面操作的一些方法。可以使用dispatch将事件绑定到我们的UI中。
Reducer:通过Action的返回方法对我们事先初始化的变量进行操作。
Component:存放我们需要更新的组件,一般是一个子类组件,根据状态机改变的值来刷新界面。使用const {} = this.props,获取父类中的属性,让后将其刷新。
Contaniner:通过Contaniner存放我们的父类控件。其中需要通过Connect来对我们属性进行绑定。connect 分别传递的是我们的状态属性state,和一个action函数。随后将通过这些状态将其绑定到父类的组件中。
随后参照一下Demo来解释:
import {createStore, applyMiddleware} from 'redux';
import thunkMiddleware from 'redux-thunk';
import rootReducer from '../reducers/reduceIndex';
//创建中间件
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(rootReducer, initialState);
return store;
}
如何理解上述的applyMiddleware(thunkMiddleware)(createStore),如果没有看过其源码,很可能就对这个形式有所迷糊,其实thunkMiddleware是一个函数,返回的是一个next的函数,函数里面有一个参数,即action。具体请移步何为middleware
随后,我们创建根reducer
import {combineReducers} from 'redux';
import userReducer from './userChange';
import Login from './LoginReducer'
const rootReducer = combineReducers({ userReducer, Login,});
export default rootReducer;
在此用combineReducers可以绑定多个reducers,这样优于管理。
列出其中一个reducer:
import * as TYPES from '../actions/types';
import {APP_MAIN_COLOR, APP_GROUND_COLOR} from '../common/constants'
const initialState = { text:APP_MAIN_COLOR, userText:'efios',};
export default function user(state=initialState, action) { switch(action.type){
case TYPES.USER_CHANGE:
return{
...state,
text:action.text,
}
//当时传过去的时候..
case TYPES.USER_TEXT:
return{
...state,
userText:action.text,
}
default:
return state;
}
}
上述代码中 TYPES 是在types.js文件中导入的类型,可以当作当前执行代码的类型;initialState 则是初始化的状态,根据这个里面的值去改变视图层的运行效果;在user 函数中则通过不同类型处理不同事件。
下面是action执行的函数
import * as TYPES from './types';
export function userChange(text){
return (dispatch)=>{
dispatch({'type':TYPES.USER_CHANGE,text:text});
}}
export function userText(text){
return (dispatch)=>{
dispatch({'type':TYPES.USER_TEXT,text:text});
}}
可以发现当前有两种类型,所以,在reducer中根据这两种类型来执行事件,具体类型我们是放在types.js文件里面:
//types.js
export const USER_CHANGE = 'USER_CHANGE';
export const USER_TEXT = 'USER_TEXT';
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
最后,我们通过以下方法绑定我们的reducer:
在你想执行的文件中绑定即可:
function select(state){
return{
text1 : state.userReducer.text,
text2: state.userReducer.userText
}}
export default connect(select)(Login);
然后则可以通过text1,text2来获取我们需要的初始值。
如果我们想要改变值得话,则通过action中的函数调用即可,如下代码:
//我们在action中定义过userChange的函数,通过dipatch的方式获取当前需要调用的值并进行使用即可。
this.props.dispatch(userChange('red'))
此时,你会发现点击按钮(此操作放在改变的事件之中,例如本例放在button的事件中),随后你会发现点击按钮状态就改变啦。
当然,我们还有另一种方式,这种方式是作者比较推从的方式:
1. 我们将需要显示的界面封装成一个子组件,例如本例是login.js
2.随后我们创建一个容器,例如loginContainer.js
那么我们在loginContainer.js中操作reducers需要传递的参数,在子组件获取参数,这样逻辑清楚,优于管理。
以下是代码:
在LoginContainer中解构:
class LoginContainer extends React.Component{
render(){
return(
<Login data={this.props.data} {...this.props}/>
);
}}
export default connect((state)=>{
const {data} = state.userReducer;
return { data }})(LoginContainer);
此时我们将userReducer里面的值解构出来,然后通过data的属性传递到子控件中,这样,便完成了我们一系列想要的操作。