不管我们项目中是否是用的redux思想的最佳实践,但是他的基本思想基本如上图,是不是十分简单明了。有人说,redux这类不能称为框架,只能说是一种思想,不过我们在此就不讨论这么学术的问题了,为了描述统一,以下我们姑且称之为框架。redux这个框架思想很简单,不过,有时候最简单的就是最复杂的,简单的,灵活,也意味着我们需要做的更多,这时候,最佳实践方案就比较不好说了,这里我也只能是就着自己的一点点项目经验来稍稍讨论一下,肯定谈不上最佳实践,但是作为抛砖引玉还是有一定价值的。接下来直接进入正题。
首先简单介绍一下上图,redux基本原则是,state中的数据由store进行统一管理,不可对state中的数据进行直接操作,也就是说,store是作为数据仓库的存在,当然,store并不是state,他只是个仓库,当我们变更store中的数据后,可以根据store.getState()这个方法获取数据,然后取出需要的数据,进行setState操作更新视图。这就很容易明白store跟state具体是什么关系了,store是将数据逻辑层与视图层更好地隔离开来。当然,这还得有其他两个小兄弟的帮忙,那就是action和reducer,严格的说,应该是actions和reducers。顾名思义很好理解,action就是定义了一系列动作,reducer就是进行数据的裁剪,清洗,再输出,reducer应该是无副作用的纯函数。我们再来看上图,这看着其实是不是有点眼熟,dispatch/subscribe的方式,好像有点像监听者模式,没错了,不过,这是个更加粗犷的监听者。为什么说粗犷,后面再说。先说说这个监听者模式,这是redux的关键所在。代码中,我们首先会引入redux库文件,其中我们最常用的两个函数是createStore和applyMiddleware,伪代码如下:
let store = createStore(reducer,{},applyMiddleware(thunk));
reducer作为参数,创建了一个store,reducer就是store的监听器,这个监听器是在store创建之初就已经定下来的,可以称为内置监听器,不再需要我们手动去绑定。这里我们就有一个疑惑了,那难不成这个监听器是每次都会调用的?没错,就是这样的,这也是一开始让我不太适应的地方。暂且先往下看,接下来看看store的几个重要方法,首先是store.subscribe(action,()=>{}),然后是dispatch(action),当我们派发一个action的时候,首先触发的是内置监听器reducer,生成可用于state来更新视图的数据,执行完毕之后,触发subscribe监听的函数,可进行store.getState()操作获取数据以及setState()更新视图。以上还有两个东西没有细讲,action和applyMiddleware是什么呢?action好理解,就是动作定义,它是个对象,也可以是个函数,但最终它还得是个对象。说起来有点绕,解释一下,定义一个动作,其实就是定义一个对象,类似这样:{type:"testAction",text:"行为描述",data:{}}
,但它也不一定是个对象,比如,我们有个数据需要从服务端获取,然后获取到数据后才能进行派发,这时候,我们有两种方式,一、是直接进行数据请求,请求成功后,将获取的数据填充入action,并派发;二、派发一个函数action,也叫异步action,由该函数进行数据请求,请求完成后自动派发。我们来对比一下两种action:
actionNotify = {type:"通知",text:"我准备请求数据了"};
actionAsync1 = (opts)=>{
return (dispatch)=>{
dispatch(actionNotify);//发个通知,我要开始请求数据了
//发起网络请求
return fetch(...).then((resData)=>{ dispatch({type:"数据到了",text:"数据请求成功了,请显示",data:resData}); }); } }
看以上代码,是两个不同类型的action,异步actionAsync1返回的函数,可以直接dispatch一个普通actionNotify,也可以网络请求数据完成后,再dispatch新的action,但最终被dispatch的还是一个普通的action,所以说action是个对象,也可以是个函数,但最终它还得是个对象。其实我们可以简单理解一下,action之所以会有异步函数的形式,只是为了数据层和UI层更好的分离,网络请求必不可少,如果不在action,那必然在UI层或者reducer层,显然都不太合适,所以异步action就是为了解决这个问题而存在的。但是我们知道,store.dispatch本身并不支持action是个函数,redux-thunk帮我们完美解决了这个问题。上面我们略过的redux中的applyMiddleware方法,就是用于引入thunk这个中间件,对普通的store进行dispatch异步action的赋能。如此一来,store.dispatch(异步action)就解决了。至此,我们就大致讲清楚了store,action,reducer三者的关系了,也就基本搞清楚redux究竟是干什么的问题。
本篇就谈到这里,下一篇我们继续。如有问题,随喷。
个人简介:
前端小司机,倒腾前端一切,砸尽一切非前端的饭碗。
有兴趣请加前端交流群