redux和dva
作者:互联网
实习的时候,公司使用的是react,react说实话生态学的还不是很完善,就暂时先不做跟react相关的博客,等以后学好了react全家桶之后,专门再总结一下react的内容
这两天看了公司的alita和dva,具体项目还没上手,但是对dva很感兴趣,一方面因为dva名字的由来,另一方面刚好在看redux的内容。
在讲redux的时候,不得不把vuex拿出来讲讲,说实话,vuex很久之前学的了,vue是我前端框架第一次接触的,vue的方便性也让我很喜爱,但是身为一个前端攻城狮怎么能不学其他框架呢,趁着在公司实习的日子里,把react的学习提上日程
扯远了,回到redux和vuex中。redux是一个状态数据的管理库,它可以用在react,也可以用在vue中,但是vue自己有一个vuex,兼容性更好,所以更大多数redux用在react的项目中。
学习vuex的时候,与现在的redux做对比,很清晰能比较出来,vuex比redux简单
下图是vuex的工作流程原理
VueX是数据管理框架,在之前我们vue里面的数据是data,父子组件,provide等等传递 在vue工程里面,数据就不是组件级别的创建,而是页面级别的创建了
VueX创建了全局的仓库,在vuex的state中,存放在全局的数据。我们使用vuex提供的store对象的state属性,来获取全局的数据
export default{ name:'Home', computed:{ myName(){ return this.$store.state.name; } } }
我们如何修改全局的数据?Vuex不允许我们直接修改全局的数据
因此我们要 调用$store里面一个方法叫做dispatch,他去派发一个action,这个action的名字叫做change 在createStore里就有一个action接收派发而来的change,执行这个change方法。在这个方法中提交一个commit触发一个mutation,在mutations里面接收触发而来方法并执行,在该方法中我们就可以修改数据
vuex的工作流程就是,组件之间使用dispatch去派发一个action,vuex中主要有三个属性action,commit,state用来操作管理数据。
actions感知到组件所派发的action,执行action对应参数的方法,提交一个commit去触发mutation,mutation中执行收到的commit的参数方法。从而修改state数据,而这个state数据就是全局的数据仓库
在最近的学习中,我接触到了redux,说实话,redux复杂程度高于vuex。
react整个应用中会存在很多个组件,每个组件的state是由自身进行管理,包括组件定义自身的state、组件之间的通信通过props传递、使用Context实现数据共享
将所有的状态进行集中管理,当需要更新状态的时候,仅需要对这个管理集中处理,而不用去关心状态是如何分发到每一个组件内部的
redux就是一个实现上述集中管理的容器,遵循三大基本原则:
- 单一数据源
- state 是只读的
- 使用纯函数来执行修改
redux要求我们把数据都放在 store公共存储空间
一个组件改变了 store 里的数据内容,其他组件就能感知到 store的变化,再来取数据,从而间接的实现了这些数据传递的功能
React Components (组件)需要获取一些数据, 然后它就告知 Store 需要获取数据,这就是 Action Creactor , Store 接收到之后去 Reducer 查一下, Reducer 会告诉 Store 应该给这个组件什么数据
如何使用?
创建一个store
import { createStore } from 'redux' // 引入redux const store = createStore() // 创建数据的公共存储区域
还需要创建一个记录本去辅助管理数据,也就是reduecer,本质就是一个函数,接收两个参数state,action,返回state
// 设置默认值 const initialState = { counter: 0 } const reducer = (state = initialState, action) => { }
将记录本传递给store,两者建立连接,获取store里面的数据,则通过store.getState()来获取当前state
const store = createStore(reducer) store.getState()
那么如何更改store中的数据呢?
是通过dispatch来派发action,通常action中都会有type属性,还有传入的更改数据。
type属性代表这个action所要做的操作
store.dispatch({ type: "ADD_NUMBER", number: 5 })
ruducer中处理所要进行操作,使用swich去接收不同action所代表的操作方法
const reducer = (state = initialState, action) => { switch (action.type) { case "INCREMENT": return {...state, counter: state.counter + 1}; case "DECREMENT": return {...state, counter: state.counter - 1}; case "ADD_NUMBER": return {...state, counter: state.counter + action.number} default: return state; } }
注意,reducer是一个纯函数,不需要直接修改state
这样派发action之后,既可以通过store.subscribe监听store的变化,如下:
store.subscribe(() => { console.log(store.getState()); })
小结
- createStore可以帮助创建 store
- store.dispatch 帮助派发 action , action 会传递给 store
- store.getState 这个方法可以帮助获取 store 里边所有的数据内容
- store.subscrible 方法订阅 store 的改变,只要 store 发生改变, store.subscrible 这个函数接收的这个回调函数就会被执行
在React项目中,会搭配react-redux进行使用
何为react-redux?
如下图
在react-redux中,我们将UI组件去除掉redux的操作,将redux的操作全部放在容器组件身上
容器组件向redux进行数据获取和更改,通过props将数据传递给UI组件,UI组件也通过props告知容器组件要对redux中的数据进行何样的操作
容器组件用以专门向reduxi请求修改状态,存在containers文件夹里面
UI组件无法向redux去修改,存在component文件夹里面
connet是一个函数,这个函数调用的返回值依旧是一个函数 ,返回值的函数让容器组件与UI组件进行关联,从而通过props进行组件间的通信。
const CountContainer=connect()(CountUI)
connect在第一次调用的时候要传入两个参数,传入的两个参数必须是函数 一个是redux中所保存的状态,另一个就是操作状态的方法。简写如下
function a(){ return {n:900} } function b(){ return {jia:(num)=>{dispatch({
type: "ADD_NUMBER", number: 5
})}} } export default connect(a,b)(CountUI)
a函数返回的对象key作为UI组件的props的key,value作为UI组件的props的value,以供UI组件接收到state
b函数返回的对象实际上向redux派生一个action,告知redux对state中的数据进行何种操作
容器组件的两个方法:mapStateToProps和mapDispatchToProps.
这是官方给的名称,为了好理解上面的代码使用a,b简述。实际使用以官方文档为主
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
回到今天所学习到的新框架——dva
dva 好像就是redux的一些轻量级应用整合,简化了API,让开发更方便,但果然这是我自己的理解。
核心概念
- State:一个对象,保存整个应用状态
- View:React 组件构成的视图层
- Action:一个对象,描述事件
- connect 方法:一个函数,绑定 State 到 View
- dispatch 方法:一个函数,发送 Action 到 State
不难发现,其本质和redux一样,只不过dva让redux的操作更加的方便简洁,提高了我们的开发效率。
Action 是用来描述 UI 层事件的一个对象。
connect 方法返回的也是一个 React 组件,也是称为容器组件。因为它是原始 UI 组件的容器,即在外面包了一层 State。
connect 方法传入的第一个参数是 mapStateToProps 函数,mapStateToProps 函数会返回一个对象,用于建立 State 到 Props 的映射关系。
dispatch 是一个函数方法,用来将 Action 发送给 State。
dispatch 方法从哪里来?被 connect 的 Component 会自动在 props 中拥有 dispatch 方法。
其实dva内容和react-redux是一样的原理,只不过为了开发速度,dva封装的API使得操作redux更为便捷
dva中有model对象,这个对象是我第一次遇到的,在这个对象中,封装这对redux中的各种操作
model最简结构
export default { namespace: 'count', state: 0, reducers: { add(state) { return state + 1; }, }, effects: { *addAfter1Second(action, { call, put }) { yield call(delay, 1000); yield put({ type: 'add' }); }, }, };
Model 对象的属性
- namespace: 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成
- state: 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出
- reducers: Action 处理器,处理同步动作,用来算出最新的 State
- effects:Action 处理器,处理异步动作
Reducer
Reducer 是 Action 处理器,用来处理同步操作,可以看做是 state 的计算器。它的作用是根据 Action,从上一个 State 算出当前 State。
Effect
Action 处理器,处理异步动作,基于 Redux-saga 实现。Effect 指的是副作用。根据函数式编程,计算以外的操作都属于 Effect,典型的就是 I/O 操作、数据库读写。
Generator 函数
Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。
call 和 put
dva 提供多个 effect 函数内部的处理函数,比较常用的是 call
和 put
。
-
- call:执行异步函数
- put:发出一个 Action,类似于 dispatch
我们约定当 src/models
下存在 dva 的 models 文件时,会被自动加载到项目中。 即约定了存在即生效,因此我们约定仅在这个文件夹下存放 dva 的 models 文件,虽然存放其他的文件会被框架自动过滤忽略,但是在这个目录存放其他文件会增加理解的心智负担,建议不要存放无关的文件。且为了管理方便,一般将文件名和 models 的 namespace 一一对应,不仅可以直观的找到相应的 models ,而且能够保证不会存在 models 冲突的问题,因为文件系统本身就不允许同名文件。
时间不早,先休息,后面将会针对dva操作redux的具体进行总结,在这个总结中我们可以很直白的看出dva与redux操作上的简易程度
宣传下自己的网站mishi-blog.com
尚在襁褓中的一个网站。
标签:dva,action,state,组件,redux,store 来源: https://www.cnblogs.com/mishi-blog/p/15037722.html