资讯专栏INFORMATION COLUMN

Redux basic tutorial

baishancloud / 2785人阅读

摘要:提供,监控的触发以及的变化。在动态内容的最外层应该使用进行包裹,接收作为参数,注意是一个函数并不是。将作为往子节点进行传递,并实现的热替换。只需要声明初始状态以及在接收到之后的改变规则就可以了。

@(blog)

Redux basic tutorial
  

本文的读者为了解flux概念,熟悉react,了解es6语法的同学

redux 是最近很火的一个 flux 框架,短短的一个月现在已经有2900+的 star 了,watch之后每天收到几百封 pr 的邮件,废话就不多说了。
为什么要用 redux ,请看连接 The Evolution of Flux Frameworks。

主要特点

Everything (Stores, Action Creators, configuration) is hot reloadable. —— 配合起 hotloader 应该特别爽,虽然现在用的是 browserify,好处感觉并不明显。

store 中的数据不受限制,可以是 number object array 等等,废话,因为它的 store 只是简单的函数。

提供 devtools ,监控 action 的触发以及 state 的变化。

源码清晰简单,轻量级,根本不需要文档,直接看源码就行了....缺点就是如果看不懂源码,光看文档会觉得不够清晰。

api 很精简,不用记茫茫多的 api

every thing is simple function

connecterprovider 这两个东西用起来总觉得很繁琐,不那么优雅。

下面通过写的一个简单counter的例子 介绍 redux 的核心方法以及一些需要注意的地方。

同步与异步两种actionCreator

middleware的使用

dispatch actions

拿到并同步state

代码放在https://github.com/yeatszhang/redux-tutorial, 需要安装gulp

代码是基于分支 v1.0.0-rc api略微有些区别,详情见 Breaking API changes for 1.0。

actionCreator

actions creator 是用来生成 action 的函数,在默认情况下可以接受返回object或者function 的函数,很多人学习flux的时候把action与actionCreator弄混淆....:

// 直接返回object
actionCreators.addTodo = function(text) {
  return {
    type: types.ADD_TODO,
    text
  };
}

// 返回函数
actionCreators.incrementAsync = function() {
  return (dispatch, getState) => {
    // actionCreator中可以通过getState获得当前的state
    console.log(getState());
    // 异步action
    setTimeout(() => {
      dispatch({
        type: INCREMENT_COUNTER2,
      });
    }, 1000);
  };
};

在没有使用任何 middleware 的情况下,只有这有两种 action 可以被 dispatch

app

在动态内容的最外层应该使用Provider进行包裹,provider接收store作为参数,注意children是一个函数并不是reactElement
provider将store作为context往子节点进行传递,并实现store的热替换。因此在provider内的组件其实可以不通过connect来拿到dispatch以及state,而直接通过context拿到store对象,不过作者不推荐这么做。

import React from "react";
import { createStore, applyMiddleware, combineReducers } from "redux";
// redux midlleware repositories
import thunk from "redux-thunk";
// 将 redux 与 react 相关的部分,如 connector provider 多带带抽取出来
import { Provider } from "react-redux";
import reducers from "../reducers";
import CounterApp from "./CounterApp.js";
import logMiddleware from "../middleWares/logMiddleware.js";

const reducer = combineReducers(reducers);
const createStoreWithMiddleware = applyMiddleware(thunk, logMiddleware)(createStore);
const store = createStoreWithMiddleware(reducer);
// 使用middleWare thunk, 如果没有自定义中间层的需求可以直接写
// const store = createStore(reducer);

class App extends React.Component {
  render() {
    return (
      
        {() => }
      
    );
  }
}
smart component

smart component拥有两个特点:

自动关联store中的state并自动re-render

可以通过dispatch来分发事件,从而触发store的更新

刚接触redux的同学肯定会觉得这个connect很难以理解。还是在代码里面说把。。。

/**
 * Created by yichizhang on 15/7/26.
 */

import React, { Component } from "react";
import { bindActionCreators } from "redux";
import { Connector } from "react-redux";
import Counter from "../components/Counter";
import actionCreators1 from "../actionCreators/actionCreators1.js";
import actionCreators2 from "../actionCreators/actionCreators2.js";

// state 是各reducer中state的集合
function select(state) {
  // 从各reducer中挑选出component需要监听的state
  return {
    counter1: state.reducer1.counter,
    counter2: state.reducer2.counter,
  };
}

export default class CounterApp extends Component {
  // select函数的返回值会与dispatch组装程一个object作为参数
  // 从这里看出connector就是帮忙拿到provider中store的dispatch方法以及挑选出需要使用的state
  renderChild({ counter1, counter2, dispatch}) {
    // 个人觉得这样使用action十分不方便,尤其是当组件只需要触发actions不需要监听store的变化的时候。我会偷懒通过context去拿到dispatch~~
    const actions1 = bindActionCreators(actionCreators1, dispatch);
    const actions2 = bindActionCreators(actionCreators2, dispatch);
    const props = { ...actions1, ...actions2, counter1, counter2 };
    // 所有的action以及state都会以props的形式提供给Counter,然后在Counter里面就可以为所欲为了~
    return ;
  }

  render() {
    return (
      
        {this.renderChild}
      
    );
  }
}

reducer

redux认为程序员不需要去写store中的逻辑而只需要写明对state的处理逻辑就好:

old  sate => action  => new state

这是一个完全同步的过程。reducer只需要声明初始状态以及state在接收到action之后的改变规则就可以了。

import React from "react/addons";
import {INCREMENT_COUNTER1, DECREMENT_COUNTER1} from "../constants/actionsTypes.js";
const update = React.addons.update;

// state可以是任何类型
const initialState = {
  counter: 0,
};

// reducer只是一个简单的switch方法
export default function counter(state = initialState, action = null) {
  switch (action.type) {
    case INCREMENT_COUNTER1:
      // 需要注意的是connector当select中的state发生变化时会做一个shallow equal的操作,
      // 所以如果需要操作引用值的时候一定不能直接赋值,需要使用addon中的update或者immutable.js,知道看到这两个工具又不想继续学了..其实很简单
      // 这样可以大大避免重复的render,从而提高性能
      return update(state, {
        counter: {
          $set: state.counter + 1,
        },
      });
    case DECREMENT_COUNTER1:
      return update(state, {
        counter: {
          $set: state.counter - 1,
        },
      });
    default:
      return state;
  }
}

middleWare

感兴趣的同学可以看看,一般来说默认的thunk就够用了。我在例子里加了个log的中间层

// 打印触发的action
function logMiddleware() {
  // 这里的next是下一个middleWare
  return function(next) {
    return function(action) {
      // 打印此action并使用下一个middleWare处理该action
      console.log(action);
      next(action);
    };
  };
}

export default logMiddleware;

// 下面是默认的thunk middleWare

function thunkMiddleware(_ref) {
  var dispatch = _ref.dispatch;
  var getState = _ref.getState;

  return function (next) {
    return function (action) {
      // 如果是函数则将dispatch与getState作为参数执行函数,否则交给写一个middleware处理
      return typeof action === "function" ? action(dispatch, getState) : next(action);
    };
  };
}
结语

其实redux不明白的地方直接看源码更好,redux的代码量很小而且组织也很清晰,建议大家都去看,不过作者貌似函数式编程的思维很重,大量使用修饰器的语法,还有reduce~ 挺绕的~

之后会总结自己阅读redux源码的一些心得,以及各功能模块的实现原理~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85849.html

相关文章

  • 猫头鹰的深夜翻译:使用SpringBoot和AspectJ实现AOP

    摘要:我们会写切面来拦截对这些业务类和类的调用。切面定义何时拦截一个方法以及做什么和在一起成为切面连接点当代码开始执行,并且切点的条件满足时,通知被调用。 前言 这篇文章会帮助你使用Spring Boot Starter AOP实现AOP。我们会使用AspectJ实现四个不同的通知(advice),并且新建一个自定义的注解来追踪方法的执行时间。 你将会了解 什么是交叉分割关注点(cross...

    meislzhua 评论0 收藏0
  • 一看就懂的例子告诉你用react-redux的正确姿势

    摘要:很多小白在看过很多教程之后仍然在敲代码的时候不清楚应该以什么样的步骤进行,那么这篇文章就一步一步分解整个过程,慢动作回放让大家看的清清楚楚明明白白。另外,中视图部分最好单独出来,放在新建一个文件夹目录下,并被名为引用,把其他逻辑部分放后者。 whay write this: 很多小白在看过很多教程之后仍然在敲代码的时候不清楚应该以什么样的步骤进行,那么这篇文章就一步一步分解整个过程,慢...

    DobbyKim 评论0 收藏0
  • [译] 前端攻略-从路人甲到英雄无敌二:JavaScript 与不断演化的框架

    摘要:一般来说,声明式编程关注于发生了啥,而命令式则同时关注与咋发生的。声明式编程可以较好地解决这个问题,刚才提到的比较麻烦的元素选择这个动作可以交托给框架或者库区处理,这样就能让开发者专注于发生了啥,这里推荐一波与。 本文翻译自FreeCodeCamp的from-zero-to-front-end-hero-part。 继续译者的废话,这篇文章是前端攻略-从路人甲到英雄无敌的下半部分,在...

    roadtogeek 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<