redux理解
-
react的困扰
项目开发中服务器响应、缓存数据、本地生成尚未持久化到服务器的数据、也包括UI状态,如激活的路由。被选中的标签、是否显示动效或者分页器等等。这些数据统称为state。
由于js数据类型的特点,管理不断变化的 state 非常困难。当系统变得错综复杂的时候,想重现问题或者添加新功能就会变得举步维艰。
-
redux的作用
redux的作用就是用来管理混乱的state。
redux三大原则:
①数据单一:整个应用state的被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个store中。
②state 是只读的: 唯一改变 state 的方法就是触发action,action 是一个用于描述已发生事件的普通对象。
③使用纯函数来执行修改: 为了描述 action 如何改变 state tree ,你需要编写reducers。 -
redux的常用API
action: 它来描述“发生了什么”。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。在 Redux 中的 action 创建函数只是简单的返回一个 action。
注:
① action对象中必须有type字段,用来指定将要执行的动作。
② action只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
reducer: 它根据 action 更新 state。它指定了应用状态的变化如何响应 actions 并发送到 store 。reducer 是一个纯函数,接收旧的 state 和 action,返回新的 state。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。
store: 是把action和reducer联系到一起的桥梁。Redux 应用只有一个单一的 store。维持应用的 state;提供 getState() 方法获取 state; 提供 dispatch(action) 方法更新 state;通过 subscribe(listener) 注册监听器; 通过 subscribe(listener) 返回的函数注销监听器。
connect: 通过react-redux提供的connect方法将我们需要的state中的数据和actions中的方法绑定到props上。原理解析
首先connect之所以会成功,是因为Provider组件:在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
接收Redux的store作为props,通过context对象传递给子孙组件上的connect
那connect做了些什么呢?
它真正连接 Redux 和 React,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。connect方法声明:
connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
参数介绍:
mapStateToProps(state, ownProps) : stateProps
这个函数允许我们将 store 中的数据作为 props 绑定到组件上。
当 state 变化,或者 ownProps 变化的时候,mapStateToProps 都会被调用,计算出一个新的 stateProps,(在与 ownProps merge 后)更新给组件。mapDispatchToProps(dispatch, ownProps): dispatchProps
它的功能是,将 action 作为 props 绑定到组件上,也会成为 MyComp 的 props。
redux-thunk理解
-
react的困扰
用户发出 Action,Reducer 函数算出新的 State,View 重新渲染。但是,一个关键问题没有解决:异步操作怎么办?Action 发出以后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步。怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)。 -
redux-thunk的作用
他允许你的action可以返回函数, 带有dispatch和getState两个参数, 在这个action函数里, 异步的dispatch action; -
redux-thunk的使用
① 安装:npm install redux-thunk --save-dev
② 导入thunk: import thunk from 'redux-thunk'
③ 导入中间件: import {createStore,applyMiddleware} from 'redux'
④ 创建store:let store = createStore(reducer函数,applyMiddleware(thunk))
⑤ 激活redux-thunk中间件,只需要在createStore中加入applyMiddleware(thunk)就可以1 /** 2 * @author:水痕 3 * @time:2017-03-28 08:48 4 * @email:332904234@qq.com 5 * @version:1.0 6 * @fileName:index 7 * @direction: 8 * @title: 9 */ 10 'use strict'; 11 import {createStore, applyMiddleware} from 'redux'; 12 import thunk from 'redux-thunk'; 13 14 function count(state = 0, action) { 15 switch (action.type) { 16 case 'ADD': 17 return state + 1; 18 case 'REDUCER': 19 return state - 1; 20 default: 21 return state; 22 } 23 } 24 const store = createStore(count,applyMiddleware(thunk)); 25 //action创建函数 26 function add() { 27 return { 28 type: 'ADD', 29 } 30 } 31 function reducer() { 32 return { 33 type: 'REDUCER' 34 } 35 } 36 function addIfOdd() { 37 return (dispatch, getState) => { 38 const currentValue = getState(); 39 if (currentValue % 2 == 0) { 40 return false; 41 } 42 dispatch(add()) 43 } 44 } 45 function addAsy(delay = 2000) { 46 return (dispatch, getState) => { 47 setTimeout(() => { 48 dispatch(add()) 49 }, delay) 50 } 51 } 52 53 //获取当前值 54 let currentValue = store.getState(); 55 //创建一个监听 56 store.subscribe(() => { 57 const previosValue = currentValue; 58 currentValue = store.getState(); 59 console.log('上一个值:', previosValue, '当前值:', currentValue) 60 }); 61 62 //分发任务 63 store.dispatch(add()); 64 store.dispatch(reducer()); 65 store.dispatch(addIfOdd()); 66 store.dispatch(addAsy());
Immutable理解
-
react的困扰
JavaScript 中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。如 foo={a: 1}; bar=foo; bar.a=2 你会发现此时 foo.a 也被改成了 2。虽然这样做可以节约内存,但当应用复杂后,这就造成了非常大的隐患,Mutable 带来的优点变得得不偿失。为了解决这个问题,一般的做法是使用 shallowCopy(浅拷贝)或 deepCopy(深拷贝)来避免被修改,但这样做造成了 CPU 和内存的浪费。
Immutable 可以很好地解决这些问题。
-
Immutable的作用
Immutable数据就是一旦创建,就不能更改的数据。每当对Immutable对象进行修改的时候,就会返回一个新的Immutable对象,以此来保证数据的不可变。
-
Immutable的常用API
1.fromJS()
作用:将一个js数据转换为Immutable类型的数据。用法:fromJS(value, converter)
简介:value是要转变的数据,converter是要做的操作。第二个参数可不填,默认情况会将数组准换为List类型,将对象转换为Map类型,其余不做操作。
代码实现:
const obj = Immutable.fromJS({a:'123',b:'234'},function (key, value, path) { console.log(key, value, path) return isIndexed(value) ? value.toList() : value.toOrderedMap()) })
2.toJS()
作用:将一个Immutable数据转换为JS类型的数据。用法:value.toJS()
3.is()
作用:对两个对象进行比较。用法:is(map1,map2)
简介:和js中对象的比较不同,在js中比较两个对象比较的是地址,但是在Immutable中比较的是这个对象hashCode和valueOf,只要两个对象的hashCode相等,值就是相同的,避免了深度遍历,提高了性能。
代码实现:
1 import { Map, is } from 'immutable' 2 const map1 = Map({ a: 1, b: 1, c: 1 }) 3 const map2 = Map({ a: 1, b: 1, c: 1 }) 4 map1 === map2 //false 5 Object.is(map1, map2) // false 6 is(map1, map2) // true
4.List 和 Map
创建
List() 和 Map()作用:用来创建一个新的List/Map对象。
数据读取
get() 、 getIn()关于merge
merge作用:浅合并,新数据与旧数据对比,旧数据中不存在的属性直接添加,旧数据中已存在的属性用新数据中的覆盖。