首先在进行父子组件传值时,由于react是单向数据流
父组件数据可以通过props流向子组件,可以通过props传值
子向父传值通过props和回调函数
跨层级可以使用context进行传值(https://react.docschina.org/docs/context.html#dynamic-context)
当组件订阅了context后,会去离自身最近的匹配了Provider的组件中获取当前context的值比如后面的value中的值,包裹在<Provider value={....}>内。redux-react主要通过context将store传递给connect也就是<Provider store={....}>,connect通过this.context.store.getState()拿到state,this.context.store.subscibe()监听state变化,this.context.store.dispatch()映射action,经过mapStateToProps、mapDispatchToProps、mergeProps以及options组合成props注入到高阶组件传入组件中并返回新组件,实现从this.props拿到值。
react-redux源码解析: https://www.jianshu.com/p/d57d6aabcfcb
但是
就上面的情况而言,数据和传递都是通过props和state控制,响应数据放到state里通过setState存储起来,当此state变化会引其同层级或是跨层级组件都变化时,耦合性过高,各个组件牵扯过多,逻辑会变得不清晰,组件复用性也比较差
针对上述情况可以通过redux做集中数据管理:
1、组件通过store.dispatch(action)触发state更新,state数据存储在store中;每次dispatch都可以通过store.subscribe()订阅store变化
2、store做数据集中存储具备只读属性,通过reducer函数来响应action并将更改数据传入store实现数据的集中存储数据的更新,同时reducer是一个纯函数,reducer接收参数为state和action,返回值也是store和action,可以使用es6中的扩展运算符...进行store和action的浅拷贝。
3、组件可以通过store.getState()获取到state
对此需要说明一下纯函数的理念:
参考:https://www.jianshu.com/p/3ea5cd37c138
1、相同输入得到相同输出
比如说一个函数function add(x,y){return x+y};入参(1,1)得到的是2,下次甚至多次输入(1,1)得到的永远都是2,前后两次输入相同都是(1,1),两次得到的输出也相同都是2,保证了相同输入得到相同输出;
2、输出由输入和内部变量提供
比如说在外部声明了一个变量a,function add(b){return a+b};输出值由输入和全局共享变量提供,函数内部并不能保证全局变量一直不变
3、不会对外部程序造成影响。
当页面越来越多,每个功能页面都需要创建各自的redux进行数据管理,reducer会变多,用combineReducer()将多个reducer输出为1个reducer,这个reducer执行createStore返回新的store,实现每个页面可以调用各自的reducer, combineReducer对reducers进行遍历,子refucer名当成键值传入。参考: https://www.jianshu.com/p/1785c2cecb44
const reducer1 = (state = [], action) => {
return { ...state, ...action };
};
const reducer2 = (state, action) => {
return { ...state, ...action };
};
function combineReducer(reducers) {
return (state, action) => {
return Object.keys(reducers).reduce((total, currentValue) => {
total[currentValue] = reducers[currentValue](
state[currentValue],
action
);
return total;
}, {});
};
}
const rootReducer = combineReducer({
reducer1,
reducer2
});
console.log(rootReducer);
在createStore()的时候,除了添加reducer我们一般还会在里面添加redux-thunk此类中间件,那为什么需要中间件?
action发出以后reducer立即更新store;但也会出现action发出reducer一段时间后再执行的现象,通过中间件可以使reducer在异步操作结束后自动执行。
容器组件和展示组件
容器组件相当于父组件,父组件中进行数据的交互,例如把state中存储响应数据,主要进行数据的交互
展示组件也就相当于子组件,注册到父组件中,负责ui的展示,展示数据依靠父组件传递过来的数值,此页面多可以通过函数组件接收props将数据展示在视图上不牵扯生命周期。
展示组件和容器组件将视图和数据逻辑分离开来,耦合性更低。
react-redux:https://github.com/reduxjs/react-redux/blob/master/src/utils/Subscription.js#L69