美文网首页
redux让人又爱又恨

redux让人又爱又恨

作者: GrowthCoder | 来源:发表于2018-11-14 10:46 被阅读0次

快照:关于指定数据集合的一个完全可用拷贝,该拷贝包括相应数据在某个时间点(拷贝开始的时间点)的映像。快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。

零、你可能不需要 Redux

需要使用Redux的场景

  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • view要从多个来源获取数据

多交互、多数据源

从组建的角度

  • 某个组建的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组建需要改变全局状态
  • 一个组建需要改变另一个组建的状态

==你需要一种机制,可以在同一个地方查询状态、改变状态、传播状态的变化==

一、设计思想

  • Web 应用是一个状态机,视图与状态是一一对应的
  • 所有的状态,保存在一个对象里面

基本概念和 API

Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。

Redux 提供createStore这个函数,用来生成 Store。

import { createStore } from 'redux';
const store = createStore(fn);

上面代码中,createStore函数接受另一个函数作为参数,返回新生成的 Store 对象。

State

Store对象包含所有数据。如果想得到某个时点的数据,就要对Store 生成快照。这种时点的数据集合,就叫做Store

当前时刻的 State,可以通过store.getState()拿到

import { createStore } from 'redux';
const store = createStore(fn);

const state = store.getState();

一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。

store.subscribe 设置监听函数,一旦state有变化,则自动执行这个函数,触发监听。
一般情况下传入render,一旦state发生变化,则执行render,得到最新的视图。

// store的简单实现
const createStore = (reducer) => {
  let state;
  let listeners = [];

  const getState = () => state;

  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };

  const subscribe = (listener) => {
    listeners.push(listener);
    return () => {
      listeners = listeners.filter(l => l !== listener);
    }
  };

  dispatch({});

  return { getState, dispatch, subscribe };
};
image.png

redux 异步请求

React-Redux 的用法

React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)

UI组件负责UI呈现 容器组件负责管理数据和逻辑

connect() 连接两种组件

connect方法可以省略mapStateToProps参数,那样的话,UI 组件就不会订阅Store,就是说 Store 的更新不会引起 UI 组件的更新

<Provider>组件

提供一个上下文,自组件可以使用store

connect 装饰器写法

对于redux的理解

combineReducers会对传入的reducer进行校验,是否符合规则,会获取每个reducer的初始值,并判断reducer的正确性。

// combineReducers中会调用这个方法
// 获取每个reducer的初始值
function assertReducerShape(reducers) {
  Object.keys(reducers).forEach(function (key) {
    var reducer = reducers[key];
    var initialState = reducer(undefined, {
      type: ActionTypes.INIT
    });

    if (typeof initialState === 'undefined') {
      throw new Error("Reducer \"" + key + "\" returned undefined during initialization. " + "If the state passed to the reducer is undefined, you must " + "explicitly return the initial state. The initial state may " + "not be undefined. If you don't want to set a value for this reducer, " + "you can use null instead of undefined.");
    }

    if (typeof reducer(undefined, {
      type: ActionTypes.PROBE_UNKNOWN_ACTION()
    }) === 'undefined') {
      throw new Error("Reducer \"" + key + "\" returned undefined when probed with a random type. " + ("Don't try to handle " + ActionTypes.INIT + " or other actions in \"redux/*\" ") + "namespace. They are considered private. Instead, you must return the " + "current state for any unknown actions, unless it is undefined, " + "in which case you must return the initial state, regardless of the " + "action type. The initial state may not be undefined, but can be null.");
    }
  });
}

最后

// 1、init事件,会返回nextState对象,包含所有reducer的初始值
// 2、每次dispatch的时候,会调用这个函数,循环遍历,判断state是否改变,更新返回的state对象
return function combination(state, action) {
    for (var _i = 0; _i < finalReducerKeys.length; _i++) {
      var _key = finalReducerKeys[_i];
      var reducer = finalReducers[_key];
      var previousStateForKey = state[_key];
      var nextStateForKey = reducer(previousStateForKey, action);

      if (typeof nextStateForKey === 'undefined') {
        var errorMessage = getUndefinedStateErrorMessage(_key, action);
        throw new Error(errorMessage);
      }

      nextState[_key] = nextStateForKey;
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
    }

    return hasChanged ? nextState : state;
  };    
}

createStore(rootReducer) 方法注册了几个事件

//createStore function
var currentReducer = reducer;
var currentState = preloadedState;

// 默认会dispatch初始化事件,存下reducer的初始值
dispatch({
    type: ActionTypes.INIT
});
  
return {
    dispatch: dispatch,
    subscribe: subscribe,
    getState: getState,
    replaceReducer: replaceReducer
}
// dispatch function
try {
  isDispatching = true;
  currentState = currentReducer(currentState, action); // 第一次会记录初始值
} finally {
  isDispatching = false;
}

每次dispatch回执行combination 遍历reduces,调用所有的reducer,通过返回的nextState与state进行判断,如果不同返回nextState,相同还是返回之前的state。最后dispatch获得新的state。

参考文章

阮一峰

redux源码

相关文章

  • redux让人又爱又恨

    快照:关于指定数据集合的一个完全可用拷贝,该拷贝包括相应数据在某个时间点(拷贝开始的时间点)的映像。快照可以是其所...

  • Redux管理状态-todoList实现

    初衷 Redux的学习,让人又爱又狠,爱它状态管理的便捷,恨它的文档让人一脸懵逼。总之学习Redux的过程痛并快乐...

  • 让人又爱又恨

    打扫卫生可真让人又爱又恨! 爱是说,喜欢这种亲手把杂乱的事物归纳整齐的感觉,很有成就感哇! 恨是说,好累啊……打扫...

  • 此路让人又爱又恨

    海誓山盟没用处,还得金山银海填. 自古深情留不住,总是套路得人心。 现在套路这个词已经被人们玩坏了,貌似对一般人来...

  • 时间,让人又爱又恨

    五一三天,过的太神速,还没好好享受就这样结束了。 还想着4.30那天盯着手机期盼,没想现已快结束。 时间真的有时候...

  • 时光,让人又爱又恨

    一晃眼具体的两年过去了,从不成熟的心智,开始慢慢懂事。自己还是变成了小时候不愿成为的人,毫无特长,且不自知。...

  • 预设,让人又爱又恨

    前天偶然间我点开了思达帕特的微信公众号,里面有一集鹿晗经纪人杨天真的采访,印象最深刻的是杨天真说她从来不进行预设,...

  • 冬雾,让人又爱又恨

    图| 淸凉地儿-了琹 © 物道君语:生活如冬雾,雾起雨雪不休,雾散旭日可求。 中国有句话说:“春雾日头,夏雾雨,秋...

  • 手机,让人又爱又恨。

    在这个智能的时代,就算是意识到手机上的每个应用和那些小红点,不仅仅是单纯的让我们点击,而是在争夺我们的时间,浪费我...

  • 让人又爱又恨的“外卖”

    凌晨,正昏昏欲睡,手机叮咚一声,打开一看,是朋友发来的一则新闻,本来肚子就有点饿,打开看后瞬间饱了还有点犯恶心。 ...

网友评论

      本文标题:redux让人又爱又恨

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