• redux介绍与入门


    一、什么是flux

      1.redux的设计思想与flux是差不多一样的,所以我们先来了解什么flux

      2.flux是一种设计模式或者说是框架。以mvc模式来划分的话react是mvc中的view, flux相当于mc,m就是model c就是control。那么我们就明白flux到底是什么了,看下图: 

     

      flux包含四个部分 Store、Dispatch、Action、View,其中Store就对应着model,Dispatch、Action就组合成了Control。这么划分仅仅是帮助全局理解flux到底是什么。

      3.flux就是一种设计模式,当view或者用户产生一个Action时,Dispatch会解析Action根据不同的Action修改Store,被修改的Store会发消息通知View说:我已经修改了过来取我并更新你自己吧。

      4.一个简单例子

    // store
    var Store = {
     state:{
      loginData:{
       type:'login',
       data:'no login',
      },
      logoutData:{
       type:'logout',
       data:'',
      }
     },
     login:function(data){
      this.state.loginData = data;
     },
     logout:function(data){
      this.state.logoutData = data;
     },
     getState:function(){
      return this.state;
     },
     sendEvent:function(){
      this.callback();
     },
     addChangeListener: function(callback) {
         this.callback = callback;
       },
       removeChangeListener: function(callback) {
        }
    }
     
    // Dispatch
    var Dispatcher = require('flux').Dispatcher;
    var dispatch = new Dispatcher();
    dispatch.register(function(payload){
     switch (payload.type){
      case 'login' :
       Store.login(payload);
       Store.sendEvent();
       break;
      case 'logout':
       Store.logout(payload);
       Store.sendEvent();
       break;
     }
    });
     
     
    // View
    Store.addChangeListener(()=>{
     console.log('{
    loginData:{type:'+Store.getState().loginData.type + ' data:' + Store.getState().loginData.data+ '}');
     console.log('logoutData:{type:'+Store.getState().logoutData.type + ' data:' + Store.getState().logoutData.data+ '}
    }');
    });
     
     
    // Action
    var loginAction = { 
     type: 'login',
     data: 'login sucessed'
    };
    var logoutAction = { 
     type: 'logout',
     data: 'logout sucessed'
    };
    console.log('登录....');
    dispatch.dispatch(loginAction);
    console.log('退出....');
    dispatch.dispatch(logoutAction);

    二、redux

      1.我们先看看看官网的一个例子

    var Redux = require('redux')
    var
    createStore = Redux.createStore function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } }
    // 创建store let store
    = createStore(counter) store.subscribe(() => console.log(store.getState()) ) store.dispatch({ type: 'INCREMENT' }) // 1 store.dispatch({ type: 'INCREMENT' }) // 2 store.dispatch({ type: 'DECREMENT' }) // 1

      可以看到redux与flux原理是一样的,只是实现不一样。

      1.redux把dispatch封装到了Store里

    // 所以我们可以直接通过store来发送dispatch
    store.dispatch({ type: 'INCREMENT' })

      2.抽象出一个reducer概念(counter就是一个reducer),reducer就是一个[根据不同的dispatch处理并生产新的state的一个程序]。

    // 处理自增、或者自减的程序
    function counter(state = 0, action) {
      switch (action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return state
      }
    }

      要理解redux,其实就是要理解Redux提供的Store与reducer。 

    三、react中使用redux

      我们将会重头创建一个React-native项目,然后加入redux框架 

    #初始化一个react-native项目
    $ react-native init reduxTest
    $ cd reduxTest/ios
    $ open reduxTest.xcodeproj
    #这样就创建并打开了一个iOS的react-native项目

      1.添加app.js

    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      TouchableHighlight
    } from 'react-native';
    class App extends Component {
      onPress(){
    
      }
      render() {
        let welcome = this.props.appInfo?this.props.appInfo.welcome:'Welcome to Redux test!'
        return (
          <View style={styles.container}>
            <Text style={styles.welcome}>
              {welcome}
            </Text>
            <TouchableHighlight onPress={this.onPress.bind(this)}>
              <Text >
                Click me!
              </Text>
            </TouchableHighlight>
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
    });
    module.exports = App;

      2.修改reduxTest/index.ios.js

    import React, { Component } from 'react';
    import {
      AppRegistry,
    } from 'react-native';
    import App from './app'
    export default class reduxTest extends Component {
      render() {
        return (
          <App></App>
        );
      }
    }
    AppRegistry.registerComponent('reduxTest', () => reduxTest);

      这时候我们得到一个简单的测试app,下面我通过redux来管理app组件的state(redux把state映射到props)。

      效果:当点击Click me! 按钮时,会吧welcome信息改为 have clicked!

      具体流程就是:

      (1).点击 Click me! 按钮 ,会通过redux的Store发送一个dispatch给reducer,reducer把welcome改为‘have clicked’

      (2).然后redux会通知app 组件重新渲染

      3.安装redux、react-redux、redux-thunk

    $ npm install redux --save 
    $ npm install react-redux --save
    $ npm install redux-thunk --save

      3.直接上源码,代码后面有解释

      总共涉及4个文件,需要重点关注的代码将会被标红

    • index.ios.js --  创建store 
    • app.js      --  根据store的改变做出相应的处理、用户点击时发出action
    • reducer.js    --  处理action 
    • action.js      --  具体的action

      index.ios.js:

    import React, { Component } from 'react';
    import {
      AppRegistry,
    } from 'react-native';
    
    import App from './app'
    import appReducer           from './reducer'
    
    import {createStore,
      applyMiddleware}        from 'redux';
    import {Provider}           from 'react-redux';
    import thunk                from 'redux-thunk';
    
    let store = createStore(appReducer,
      applyMiddleware(thunk)              // 用于异步的action
    );
    
    export default class reduxTest extends Component {
      render() {
        return (
          <Provider store={store}>
            <App></App>
          </Provider>
    
        );
      }
    }
    AppRegistry.registerComponent('reduxTest', () => reduxTest);

      解析

      这里引入了四个redux相关组件

    • createStore        --- 是一个函数,用于创建store
    • applyMiddleware    --- 是一个函数,用于使用中间件
    • hunk                     --- 是一个函数,是中间件用于使action函数支持异步;
    • Provider                --- 是一个react组件,主要提供一个全局的store使得它的子组件都能访问到

      创建store的代码:

    let store = createStore(
        appReducer,
        applyMiddleware(thunk)     // 用于异步的action
    );
    /**
        @appReducer :是一个reducer,我们说过是用于处理action的。
        @applyMiddleware(thunk) : 应用一个叫thunk的中间件,任何一个action执行前会先执行thunk
    
        这里我们应该记住:
        store提供一个保存state的地方
        store也提供了一个发出dispatch的方法
        store也提供了一个监听state的方法  
    */

      Provider:Provider是提供者,意思就是给他的子组件提供一个store,这个store就是我们上面创建的。

      app.js:

    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      TouchableHighlight
    } from 'react-native';
    import {connect}        from 'react-redux';
    import {bindActionCreators}  from 'redux';
    
    import WelcomeAction from './action'
    
    class App extends Component {
      // 定义 上线文里store属性的类型为object
      static contextTypes = {
        store: React.PropTypes.object
      }
      componentDidMount() {
        // store的作用1: 监听state的变化
        const { store } = this.context;
        store.subscribe(
          ()=>{
            // store的作用2: 获取state
            let state = store.getState();
            // state改变了
            console.log('state:',state);
          }
        );
      }
      onPress(){
        // 1.直接用store发生dipatch
        let action = {
          type:'welcome',
          data:{
            text:'have clicked from app.js',
          }
        }
        // store的作用3: 发送dispatch
        this.context.store.dispatch(action)
        
        // this.props.onPressAction()
      }
      render() {
        let welcome = this.props.welcome
        return (
          <View style={styles.container}>
            <Text style={styles.welcome}>
              {welcome}
            </Text>
            <TouchableHighlight onPress={this.onPress.bind(this)}>
              <Text >
                Click me!
              </Text>
            </TouchableHighlight>
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
    });
    function mapStateToProps(state) {
      return {
        welcome: state.welcome
      }
    }
    function mapDispatchToProps(dispatch) {
      return {
        onPressAction:bindActionCreators(WelcomeAction,dispatch),
      }
    }
    module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

      解析

     (1)获取store

      因为app组件是Provider组件的子组件,所以app组件跟Provider组件是共享一个context(上下文)的 --- 这个是react的规定,不了解的请自行补相应知识。

      只要在app组件定义一下store的类型就能使用了

    // 定义 上线文里store属性的类型为object
      static contextTypes = {
        store: React.PropTypes.object
      }
    // 通过下面就能获取到store
    this.context.store

      这个store是与创建Provider时传入的store是同一个

    <Provider store={store}>
        <App></App>
    </Provider>

     (2)使用store

      获取到store之后我们就可以用于发送dispatch、监听state了

      发送dispatch:

        let action = {
          type:'welcome',
          data:{
            text:'have clicked from app.js',
          }
        }
        // store的作用3: 发送dispatch
        this.context.store.dispatch(action)

        action参数是一个对象,对象结构没有做要求。

      action被dispatch之后会被reducer处理,处理完后就会发一个通知说state已经更新了。

      通过下面代码来监听通知

    // store的作用1: 监听state的变化
        const { store } = this.context;
        store.subscribe(
          ()=>{
            // store的作用2: 获取state
            let state = store.getState();
            // state改变了
            // 根据state做相应的渲染
            console.log('state:',state);
          }
        );

     我看下面的reducer是怎么处理action的

     reducer.js:

    function Reducer(state = {welcome:'Welcome to Redux test!'}, action) {
      switch (action.type) {
        case 'welcome':
          return {welcome:action.data.text};
        default:
          return state
      }
    }
    module.exports = Reducer;

      解析:

      很简单的处理,如果action的type等于‘welcome’的话,就直接返回一个对象{welcome:action.data.text};

      监听者收到的就是这个返回的对象。

      值得注意,Reducer的参数 state = {welcome:'Welcome to Redux test!'},是state的默认值

    ---------------------------------------------------------------------

      每次都通过this.context.sotre来dispatch、subscribe,大家都觉得很烦,好吧redux已经做了封装:

      引入两个组件:

    • connect   ----  用于封装App组件
    • bindActionCreators   --- 绑定action的构造者

      具体使用:

    function mapStateToProps(state) {
      return {
        welcome: state.welcome
      }
    }
    function mapDispatchToProps(dispatch) {
      return {
        onPressAction:bindActionCreators(WelcomeAction,dispatch),
      }
    }
    
    module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

      解析:

      function mapStateToProps(state)

      正如函数名所表示,它的作用就是把state映射到props上。这里的state是指store保存的state,props是指app组件的props。

      这个函数需要返回一个对象

    return {
        welcome: state.welcome
      }

      然后通过connect组件封装一下

    module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

      这样子,在app组件内部就能通过this.props.welcome来获取store保存的state对应的welcome的值了,是不是分方便?

      既然state能映射到props,那么dispatch action也能映射

    
    
    import WelcomeAction from './action'

    function
    mapDispatchToProps(dispatch) { return { onPressAction:bindActionCreators(WelcomeAction,dispatch), } } module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

      上面的代码意思就是吧dispatch映射到props上,dispatch是sotre的dispatch,props是app的props.

      我们可以这样直接发出一个action,

    this.props.onPressAction()

      onPressaction()等同于  WelcomeAction

      WelcomeAction是什么请看往下看:

      action.js:

    function WelcomeAction () {
      // 异步
      return (dipatch, getState) => {
        return new Promise((resolve,reject)=>{
          setTimeout(()=>{
            let action = {
              type:'welcome',
              data:{
                text:'have clicked??',
              }
            }
            dipatch(action);
            resolve();
          },2000);
        });
      }
      // 同步
      // return {
      //   type:'welcome',
      //   data:{
      //     text:'have clicked',
      //   }
      // }
    }
    module.exports = WelcomeAction   

      WelcomeAction函数用到dispatch等于store.dispatch

       这样做的目的是把action独立出来方便单独管理。

      action函数,如果需要异步执行就返回一个Promise,同步执行可以直接返回一个新的state  

      值得注意如果action函数需要异步执行,在创建store的时候必须使用中间件trunk

    import thunk                from 'redux-thunk';

    let store = createStore( appReducer, applyMiddleware(thunk) // 用于异步的action );
  • 相关阅读:
    DIV圆角
    ASP.net在线购物商城系统完全解析
    javascript选中一定数量文字触发事件进行分享、转发
    javascript获取2月份天数
    新版JDBC连接SqlServer2005数据库
    一些有用的SQL Server函数
    BI(Business Intelligence)
    CASE运用
    [SQL SERVER] 跨服务器查询
    java 中的 io 系统总结
  • 原文地址:https://www.cnblogs.com/shuigu/p/6186720.html
Copyright © 2020-2023  润新知