Redux
Flux架构
Flux是为了解决在前端模块化开发后,组件之间的频繁数据交互导致的项目维护复杂的问题。
一般的组件传值,会在组件之间造成强关联,这种传值在项目比较小的时候还可控,
一旦项目变得庞大,将会导致整个项目逻辑变得十分复杂,数据交互变得冗长且不可控,
Flux应运而生。
Flux架构下,拆分成了View,Actions,Store三部分,
在View中的交互操作将会触发到actions,actions中对store进行改变,
当store进行改变后,相应的反过来去更新视图,这就是单向数据流。
单向数据流解决了组件相互传值不可控的问题,
所有数据的改变统一都流向了store。
Redux
Redux是flux的一种实现,Redux不单单可以用在react上面。
用于react的redux的package名称叫做react-redux。
基于flux的架构思想,redux分为action、reducer和state三部分
1、action用于定义函数,定义更新的数据
2、reducer用来实际的操作数据,对传来的数据进行操作
3、state即为reducer return的部分,state可以设置默认值
tips:在redux的原则当中,
state应当是只读的,要改变state,应当触发action然后触发reducer去改变;
reducer的操作应当是纯函数,在reducer中,reducer应该单纯只执行计算功能。
(取自API文档)
不应当操作传入的参数;
不应当执行有副作用的操作,例如ajax,路由跳转;
不应当调用非纯函数,如Date.now()和Math.random();
引入Redux
import { createStore, bindActionCreators } from "redux";
createStore用于将定义好的actions和reducer对象写入redux;
bindActionCreators用于将redux的actions对组件进行映射
eg:
// 1、引入state中的变量,映射state
function mapStateToProps(state){
return {text:state.text}
}
// 2、引入reducer中的function,映射actions
function mapDispatchToProps(dispatch){
return {
actions:bindActionCreators({
changeText:changeText,
buttonClick:buttonClick
},dispatch)
}
}
//connect ,将mapState和Dispatch与组件进行关联,完成映射
App = connect(mapStateToProps,mapDispatchToProps)(App)
这里注意,
1、bindActionCreators
{
actions:bindActionCreators({
changeText:changeText,
buttonClick:buttonClick
},dispatch)
}
等同于
{
actions:{
changeText:()=>dispatch(changeText()),
buttonClick:(a)=>dispatch(buttonClick(a))
}
}
其中,如果不使用bindActionCreators,需要映射的函数调用的时候带有形参,那么就必须在dispatch时加入形参。
例如buttonClick这个函数就有形参
2、connect
connect用于视图组件和store的关联,
connect会指定两个参数,第一个参数是state的映射
第二个参数是actions的映射
Action
Actions主要用来传递事件的触发,只做事件的描述和传递,不进行计算,
事件触发后,state应该如何变化,不由actions来进行,
actions将传递给reducer进行详细处理。
eg:
function buttonClick(inputText){
return {
type:"BUTTON_CLICK",
data:inputText
}
}
Tips:在这里,Actions表现为一个一个的函数,函数return的是一个对象,
对象带有一个type用来判断当前的操作类型,
data为自定义的值,可以更改,可以自己定义带有其他的属性值。
如何触发actions?
在组件内部,使用this.props.actions.buttonClick(inputText);
Reducer
还是那句话,Actions只做了事件的描述和数据的传递,没有进行计算,
计算都放到了reducer中进行,
eg:
function myApp(state = initialState , action){
switch(action.type){
case "CHANGE_TEXT":
return {
text:state.text == "Hello"?"Stark":"Hello"
}
case "BUTTON_CLICK":
return {
text:action.data || "You just click button"
}
defaultkey: "value",
return{
text:"hello!!"
}
}
}
一般地,reducer会接收两个参数,
第一个参数为state,state可以定义默认值,
第二个参数为action。
通过switch来定义针对不同actions传递过来的actions.type,
对数据进行不同的操作。
定义actions和reducer都是定义的一个函数,
定义好之后,需要将二者注册给redux对象。
let store = createStore(myApp);
Component呈递
一般情况下,redux只有一个state,因此state是全局作用的,component之间需要共享的数据,直接操作state即可。
和vuex的区别对比
vuex的流向:view——>commit——>mutations——>state变化——>view变化(同步操作)
view——>dispatch——>actions——>mutations——>state变化——>view变化(异步操作)
redux的流向:view——>actions——>reducer——>state变化——>view变化(同步异步一样)
redux的state数据设计,进行范式化。