博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
谈谈FLUX的使用
阅读量:6276 次
发布时间:2019-06-22

本文共 3076 字,大约阅读时间需要 10 分钟。

提要:本文所展示示例代码,既非JQuery代码,也是不React代码,为介于两者间的,方便行文伪代码。代码意思通过上下文即可理解。

Facebook的Jing Chen同学在2014年的F8上演示了她的FLUX架构。

clipboard.png

FLUX的工作流如下:

  1. 中央Dispatcher管理所有进来的ACTION。
  2. 可以注册任意多个Store处理ACTION.
  3. 组件在需要修改数据的时候,发出ACTION.

但是,如果只是上述那个简单的话,就实在没什么好说的了。举个例子,如果我有一个TodoList,在点击添加item的时候,需要把内容发送到服务器,根据服务器返回的结果,显示成功或失败的结果,那么采用FLUX则是这么写的:

javascript dispatcher.register(function(payload){    switch(payload.actionType) {        case "ADD_ITEM":            ajax("/add/item", payload.data, function success(res){                dispatcher.dispatch("ADD_SUCCESS", payload.data);            }, function failure(){                dispatcher.dispatch("ADD_FAIL", payload.data);            });            break;        case "ADD_SUCESS":            // do something            break;        case "ADD_FAIL"            // do something            break;    }});// 在组件中发出$("#add").click(function(){    dispatcher.dispatch({        actionType: "ADD_ITEM",        data: $("input").val()    });});

上述代码是有问题的,因为在Store中发出异步请求,然后在回调中又发出ACTION,这种情况属于Nested Update,导致的问题有:

  • 你不知道你发出的action,什么时候才会处理完
  • 你不知道你的事件,数据的流向在哪儿
  • 容易引发循环调用

当然,最最终导致的结果就是:难以维护。

因此,在FLUX中,首要的一个原则就是:

STORE代码同步化

上面的代码可以改成:

dispatcher.register(function(payload){    switch(payload.actionType) {        case "ADD_ITEM":            // 显示小菊花,表示"正在加载"            break;        case "ADD_SUCESS":            // 显示加载成功            break;        case "ADD_FAIL"            // 显示加载失败            break;    }});$("#add").click(function(){    var msg = $("input").val();    dispatcher.dispatch({        actionType:"ADD_ITEM",         data: msg    });    ajax('add/item', msg, function success(res) {        dispatcher.dispatch({            actionType:"ADD_SUCESS",            data: res        });    }, fail(res){        dispatcher.dispatch({            actionType:"ADD_FAIL"            data: res        });    });});

这样在store中的三个case里的操作都是同步的了,即任何action,我们都很清楚其触发了之后,具体发生了什么事情。

注:不要被上面代码中的注释迷惑,Store并不应该去操作DOM,上面的注释只是说明其之后发生了什么。

上面的例子中,我们将ajax请求放在组件中,成功时触发一个action,失败时又触发另一个,使得程序行为是完全可预测的。但如果这个ajax请求的数据非常复杂呢,组件内部就无法发出请求了,因为它没有收集这些数据的能力。

举个例子,在一个购物车页面内,勾选增加/删除某个商品,会:

  • 商品列表改变了
  • 收集所有其它已勾选的商品及数量
  • 发送ajax到后台,计算总价(不要问我为什么,这里涉及大量的满减,积分,立减等碧池逻辑)
  • 后台返回计算后的总价
  • 更新前端

上面的关键步骤发送ajax到后台,我们并不能在商品数量组件中发送,因为单个组件无法收集整个商品列表的信息,如果它可以收集的话,你的程序就不好维护了,因为你的组件强依赖于外部信息。

这种情况似乎又绕回了篇首的写法,因为store中有相应的信息,那么就在store收集数据,发出ajax呀。(又有同学提议说,让组件从Store中取数据,不就能收集到所需数据了吗?)。 注意,FLUX另一原则是:

不要让你的组件强依赖于Store,你组件的数据应该来自于父组件,而不是Store。强依赖于Store的后果是:

* 你的组件难以复用
* 你的组件难以测试

在此例中,我能想到的解法应该是,通过父组件传入回调给子组件处理:

// 购物车中
//数量组件中input.on('change', function(){ // 发出action,可能某个角落有store监听这个action // 用以统计当前所有商品的数量 dispatch.dispatch({ actionType: "CHANGE_QUANTITY", id: this.id, quantity: this.value }); // 调用父组件传来的onChange函数 this.props.onChange();});

如此,一可保持Store中代码的同步化,二可保持组件中对外部世界的无知。

FLUX另外最重要的特点就是,非常容易扩展。举例而言,在上面购物车例子中,如果我要增加一个区块显示每样商品的数量,我不需要修改原有的代码,只需要新增加一个store即可。

dispatcher.register(function(payload) {     switch(payload.actionType){         case "CHANGE_QUANTITY":             // 1. 收集所有商品的数量             // 2. update对应的model,更新view             break;     }});

【完】

转载地址:http://crgpa.baihongyu.com/

你可能感兴趣的文章
继承自ActionBarActivity的activity的activity theme问题
查看>>
设计模式01:简单工厂模式
查看>>
项目经理笔记一
查看>>
Hibernate一对一外键双向关联
查看>>
mac pro 入手,php环境配置总结
查看>>
MyBatis-Plus | 最简单的查询操作教程(Lambda)
查看>>
rpmfusion 的国内大学 NEU 源配置
查看>>
spring jpa 配置详解
查看>>
IOE,为什么去IOE?
查看>>
java 用反射简单应用,将Object简单转换成map
查看>>
Storm中的Worker
查看>>
dangdang.ddframe.job中页面修改表达式后进行检查
查看>>
Web基础架构:负载均衡和LVS
查看>>
Linux下c/c++相对路径动态库的生成与使用
查看>>
SHELL实现跳板机,只允许用户执行少量允许的命令
查看>>
SpringBoot 整合Redis
查看>>
2014上半年大片早知道
查看>>
Android 6.0指纹识别App开发案例
查看>>
正文提取算法
查看>>
轻松学PHP
查看>>