笔记----深入浅出《React和Redux》第三章Flux框架

书中的此章节“思想”类成分较多,需要理解的内容也相对较多,如果一一列举,本文就写的相对繁琐了,推荐有兴趣的同学可以去看一下书籍以及敲一下书中的代码,有助于理解作者大牛的思想,我就在此简略的记录一些相对重要的“点”了。

一、Flux框架的诞生以及解决了MVC框架哪些问题

  1、Flux出现背景

      Facebook的工程部门发现在前端使用MVC框架进行逻辑划分时,在业务量和代码量庞大的情况下,model层和view层之间依赖过于复杂,不利于后期对于代码的维护

      

   理想中,各个模块分工:

   Model:负责逻辑以及数据

       View:负责渲染界面

       Controller:负责接收用户的输入,根据用户的输入调用对应的Model部分逻辑,把产生的数据结果交给View部分,让View渲染出必要的输出

   MVC框架的请求流程:用户请求------>Controller------>Model------>View,View和Model不能直接进行互相通信,都需要借助于Control

  

  

  在实际工作中,对于浏览器端 MVC 框架,存在用户的交互处理,界面渲染出来之后,Model 和 View 依然存在于浏览器中,这时候就会诱惑开发者为了简便,让现存的 Model和 View直接对话,当代码量和逻辑复杂时,使程序“脆弱而且不可预测”

  2、Flux框架

   

   (1)特点:更严格的数据流控制

       (2)各个模块:

             Dispatcher(相当于“Controller”):用来接收Actions、执行回调函数;

     Store(相当于“Model”):用来存放应用的状态,一旦发生变动,就提醒Views要更新页面;

     Action(相当于“用户请求”):视图层发出的消息;

             View:显示用户界面;

  (3)与MVC框架的区别:

    (i)当系统需要扩充应用所能处理的“请求”时,在MVC中,通过在Controller增加函数,来实现扩充;

               在Flux中,不需要Dispatcher增加新函数,而是通过增加新的Action类型,来实现扩充

  (4)Flux实践 (直接上代码)

    实现的效果:

       

        

                   当点击“+”按钮或者“-”按钮,对应行的数字会时时进行改变,并且总数也会时时改变,下图:

      

      

              步骤一

        安装Flux:npm install --save flux             (如果感觉慢,可以安装国内淘宝镜像)

       

       (i)Dispatcher

                     

       作用:生成Dispatcher实例,用来之后将 Action 派发到 Store

       注意!注意! 注意!Dispatcher实例在全局只有一个

      (ii)Action(分2个文件,一个定义action类型,另一个定义action构造函数)

        ActionTypes.js

        

        说明:将常量放在单独一个文件方便管理

        Actions.js 

        

        作用:根据类型,生成不同的action对象,通过Dispatcher实例的dispatch函数派发出去

        注意:出于业界习惯,这个文件被命名为Actions.js,但是要注意里面定义的并不是action对象本身,而是能够产生并进行派发action对象的函数 

                        

       (iii)Store(创建了两个store,CounterStore是为Counter组件服务,SummaryStore是为总数服务)

        CounterStore.js

         

         

        说明:在CounterStore中可以看出,首先定义了Counter组件初始化的值,然后使用Object.assgin()函数,对EventEmitter.prototype对象进行了浅拷贝,并在此浅拷贝对象的基础上扩充了getCounterValues、emitChange、addChangeListener、removeChangeListener方法。其中这四个方法的后三个方法,分别调用了EventEmitter.prototype的on(),emit(),removeListener()方法,作用如下:

         on(EVENT_TYPE,callback):用来监听事件,第一个参数是字符串事件类型,第二个参数是事件处理函数;

         emit(EVENT_TYPE):用来触发事件,第一个参数是字符串事件类型;

         removeListener(EVENT_TYPE,callback):用来移除事件,如果要调用removeListener函数,就一定要保留对处理函数的引用,

                                                                                       第一个参数是字符串事件类型,第二个参数是事件处理函数。

最后,通过把AppDispatcher.register()中的回调函数注册到Dispatcher上,来接受之前通过AppDispatcher.dispatch()派发的action对象,通过switch或if-else来实现对应类型的动作实现对应类型的操作。

        

        

        SummaryStore.js

         

         

        说明:总体代码和之前CounterStore差不多。需要说明的是在这两个store中,AppDispatcher.register()会返回一个标记,保存在各自store的dispatchToken字段中,用来之后实现多个store之间行为的依赖顺序,借助waitFor()。在这个代码中,我们希望SummaryStore的逻辑在CounterStore之后进行

  

        作用: Store是一个对象,既用于存储应用状态,也用来接受Dispatcher派发的动作,根据动作决定是否更新应用状态。

        注意:store 在Flux中可以存在多个,每一个 store 都会受到所有的 action 通知,然后自行觉得是否对这个 action 做出响应,更新 state;

             store对外只暴露了读取接口,如果想实现写入的功能,只能去实现对应action。

     

        (iv)View(用React进行实现,3个视图组件,其中ControlPanel父组件包含Counter子组件,Summary子组件)

        

         ControlPanel组件

        

        Counter

                

          

         Summary

         

        View 的代码就是常规React书写方式,就不一一叙述了

         注意:存在于Flux框架中的React组件需要实现以下几个功能

              1)创建时要读取Store上的状态来初始化组件内部状态;(而不像之前通过props传参,实现组件内部初始化)

            2)当Store上状态发生变化时,组件要立刻同步更新内部状态保持一致;(通过Store改变状态后调用emit(),以及View通过on()来监听Store中状态的变化)

            3)View如果要改变Store状态,只能派发action。(Flux中,对Store进行修改,只能通过新建action)

        (v)上述代码个人理解及总结:

    过程一:按着组件的生命周期函数顺序,进行渲染。其中componentDidMount函数通过CounterStore.addChangeListen函数监听了CounterStore的变化之后,只要CounterStore发

                         生变化,Counter组件的onChange函数就自动会被调用。不过首次挂载时,可以发现getCounterValue被重复调用了2次来读取相同值,分别是第一个是constructor中被调

                         用,第二个是componentDidMount中的this.onChange中被调用

              

              

                  

   

    过程二:当进行点击“+”按钮时,this.props.caption立即读取了当前组件上的属性值First,以形参的形式传入increment()方法,并触发increment();

              (以First为例子)         

                  

    过程三:此时Dispatcher的实例(AppDispatcher)调用dispatch()方法,将刚产生的action对象派发出去,此时action对象上携带着动作类型,以及刚刚传入的First字符串标记

                           

    过程四: 通过AppDispatche.register()来注册回调函数,之后这个回调函数就可以接受派发出来的action对象,并根据这个action对象的类型,执行对应的逻辑,即在这里的逻辑是根

                        据action.counterCaption拿到First,然后通过counterValues[First]拿到当前保存在Store中的初始值,并进行加一操作,最后通过emit(),将事件触发

                        

             

        过程五:在过程一首次挂载时,onChange函数作为形参数,最终传入on()中,监听事件的触发,也就是等待emit函数被调用,然后执行onChange函数内部操作,通过

                                    getCounterValues获得Store的新状态值,即First字段加一后的值,最后通过setState函数将这个值同步到组件内部状态count上,同时State的更新会触发生命周期    

            的shouldComponentUpdate函数,判断此次渲染是否与上一次不同,如果不同则返回true,并将结果渲染到页面 

            

             

                        

             其他的“-”按钮以及计算总和的步骤流程也差不多,我就不继续进行描述了,可以按照上面过程进行推演。 

            结合自己理解,画了一个图,完毕。

            

            睡觉睡觉!!!!!!!

其他参考:http://www.ruanyifeng.com/blog/2016/01/flux.html

猜你喜欢

转载自www.cnblogs.com/qianbin/p/10171834.html