相关资源


Ref: [Android Module] 03 - Software Design and Architecture

Ref: 详解React Flux架构工作方式

Ref: 阮一峰

*** Redux 和 Flux 很像 ***

主要区别在于Flux有多个可以改变应用状态的store,它通过事件来触发这些变化。【store较多】

组件可以订阅这些事件来和当前状态同步。

    • Redux 没有分发器dispatcher,
    • Flux 中dispatcher被用来传递数据到注册的回调事件。

另一个不同是Flux中有很多扩展是可用的,这也带来了一些混乱与矛盾。

*** 下一步 ***

(1) Redux

Goto: 《看漫画,学 Redux》

你以为Redux就是终结了么? NO, NO, NO!

(2) redux-saga又是什么鬼?

redux-saga 是一个 redux 的中间件,而中间件的作用是为 redux 提供额外的功能。

聊一聊 redux 异步流之 redux-saga

框架结构


Flux将一个应用分成四个部分,对,我们故意将代码写成这种单向流的逻辑形式。

  • View: 视图层
  • Action(动作):视图层发出的消息(比如mouseClick)
  • Dispatcher(派发器):用来接收Actions、执行回调函数
  • Store(数据层):用来存放应用的状态,一旦发生变动,就提醒Views要更新页面

$ git clone https://github.com/ruanyf/extremely-simple-flux-demo.git
$ cd extremely-simple-flux-demo && npm install
$ npm start

示范代码下载

代码演示


一、"controll view" 模式

  • (1) MyButton,不包含状态,是一个纯组件,从而方便了测试和复用。
  • (2) MyButtonController,只保存状态,将参数传给子组件MyButton。

Ref: React中的无状态和有状态组件

无状态组件:无状态组件(Stateless Component)是最基础的组件形式,由于没有状态的影响所以就是纯静态展示的作用。一般来说,各种UI库里也是最开始会开发的组件类别。如按钮、标签、输入框等。它的基本组成结构就是属性(props)加上一个渲染函数(render)。由于不涉及到状态的更新,所以这种组件的复用性也最强。

有状态组件:在无状态组件的基础上,如果组件内部包含状态(state)且状态随着事件或者外部的消息而发生改变的时候,这就构成了有状态组件(Stateful Component)。有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。这种组件也是通常在写业务逻辑中最经常使用到的,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同。

button如何跟这个状态扯上了关系?思考下如果自己实现会采用怎样的思路?

二、代码解读

(1) 可见是个“纯组件”的代码,方便独立测试!

一旦用户点击,就调用this.createNewItem 方法,向Dispatcher发出一个Action。

一问:props.onClick在哪里?

答:button的onClick指向了外边的MyButton的onClick的内容,也就是createNewItem。

二问:为什么这么做?

如此,状态就可以独立在button的外边,button就是个“纯组件”了。

(2) 将“状态”转发给子组件,并发一道命令(action) 给store。

// components/MyButtonController.jsx
var React = require('react');
var ButtonActions = require('../actions/ButtonActions');
var MyButton = require('./MyButton'); var MyButtonController = React.createClass({
createNewItem: function (event) {
ButtonActions.addNewItem('new item');    // ----> 调用createNewItem方法,会触发名为addNewItem的Action。
}, render: function() {
return <MyButton
onClick={this.createNewItem}   // <---- 赋具体的onClick,也即是干活的地方
/>;
}
}); module.exports = MyButtonController;

找到了干活的地方(改变状态的地方),但具体的事该怎么去做,是交给了下面的action来处理,也即是发了“一道命令”。

(3) 把动作ADD_NEW_ITEM派发到Store,看上去:dispatch就会与switch紧密相连。

var AppDispatcher = require('../dispatcher/AppDispatcher');

var ButtonActions = {
 addNewItem: function (text) {
  AppDispatcher.dispatch({      // ButtonActions.addNewItem方法,使用AppDispatcher,把动作ADD_NEW_ITEM派发到Store
  actionType: 'ADD_NEW_ITEM',
  text: text
  });
  },
}; module.exports = ButtonActions;

(4) 看作是一个路由器,负责在 View 和 Store 之间,建立 Action 的正确传递路线。

注意,Dispatcher 只能有一个,而且是全局的。

Jeff:

  这里调用了store的具体改变state的函数,如此,函数其实就都集中写在了store里。

  如何正确的判断request来调用store里的函数,也即是"router"问题,便是dispatch的事儿。

var Dispatcher    = require('flux').Dispatcher;
var AppDispatcher = new Dispatcher();
var ListStore = require('../stores/ListStore');

/**
* 全局性的注册,因为dispatcher只能有一个
*/
AppDispatcher.register(function (action) {
switch(action.actionType) {
case 'ADD_NEW_ITEM':
ListStore.addNewItemHandler(action.text);  // 执行回调函数,对ListStore进行操作
ListStore.emitChange();   // 触发“change”事件,在哪里监听到了呢?
break;
default:
// no op
}
}) module.exports = AppDispatcher;

可见,来什么actionType,就分配对应的函数去干活;具体改变状态的函数在接下来的store里面。

(5) Store 改变 并 保存着整个应用的状态,也就是具体干活的地儿。

// stores/ListStore.js
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');

/**
* Store 需要在变动后向 View 发送"change"事件,因此它必须实现事件接口
*/
var ListStore = assign({}, EventEmitter.prototype, {
items: [], getAll: function () {
return this.items;
}, addNewItemHandler: function (text) {
this.items.push(text);
}, emitChange: function () {
this.emit('change');  // --> 触发事件
},

-------------------------------------------------------
addChangeListener: function(callback) {
this.on('change', callback);  // <-- 监听事件
}, removeChangeListener: function(callback) {
this.removeListener('change', callback);
}
}); module.exports = ListStore;

(6) 补充上View中的监听事件

可见,在(2)的MyButtonController中,还少了什么:监听“change"触发时间的listener。

var React = require('react');
var ListStore = require('../stores/ListStore');        // 添加
var ButtonActions = require('../actions/ButtonActions');
var MyButton = require('./MyButton'); var MyButtonController = React.createClass({ ----------------------------------------------------------
getInitialState: function () {
return {
items: ListStore.getAll()
};
}, componentDidMount: function() {
ListStore.addChangeListener(this._onChange);
}, componentWillUnmount: function() {
ListStore.removeChangeListener(this._onChange);
}, _onChange: function () {      // <---- listener
this.setState({
items: ListStore.getAll()
});
},

----------------------------------------------------------
createNewItem: function (event) {
ButtonActions.addNewItem('new item');
}, render: function() {
return <MyButton
items={this.state.items}      // 添加
onClick={this.createNewItem}
/>;
} }); module.exports = MyButtonController;

[React] 07 - Flux: uni-flow for react的更多相关文章

  1. 使用 React 和 Flux 创建一个记事本应用

    React,来自 Facebook,是一个用来创建用户界面的非常优秀的类库.唯一的问题是 React 不会关注于你的应用如何处理数据.大多数人把 React 当做 MV* 中的 V.所以,Facebo ...

  2. 【转】浅谈React、Flux 与 Redux

    本文转自<浅谈React.Flux 与 Redux>,转载请注明出处. React React 是一个 View 层的框架,用来渲染视图,它主要做几件事情: 组件化 利用 props 形成 ...

  3. react及flux架构范例Todomvc分析

    react及flux架构范例Todomvc分析 通过分析flux-todomvc源码,学习如何通过react构建web程序,了解编写react应用程序的一般步骤,同时掌握Flux的单向数据流动架构思想 ...

  4. 理顺react,flux,redux这些概念的关系

    作者:北溟小鱼hk链接:https://www.zhihu.com/question/47686258/answer/107209140来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  5. [React] Remove React PropTypes by using Flow Annotations (in CRA)

    Starting from v15.5 if we wanted to use React's PropTypes we had to change our code to use a separat ...

  6. React学习笔记-1-什么是react,react环境搭建以及第一个react实例

    什么是react?react的官方网站:https://facebook.github.io/react/下图这个就是就是react的标志,非常巧合的是他和我们的github的编辑器Atom非常相似. ...

  7. React系列(一):React入门

    React简介 1.由来 React是有Facebook开发出来用于构建前端界面的JS组件库,由于其背后的强大背景,使得这款库在技术开发上完全没有问题. 2.React的优势 解决大规模项目开发中数据 ...

  8. React Native是一套使用 React 构建 Native app 的编程框架

    React Native是一套使用 React 构建 Native app 的编程框架 React Native at first sight what is React Native? 跟据官方的描 ...

  9. react.js 从零开始(七)React (虚拟)DOM

    React 元素 React 中最主要的类型就是 ReactElement.它有四个属性:type,props,key 和ref.它没有方法,并且原型上什么都没有. 可以通过 React.create ...

随机推荐

  1. exce中42093和日期之间的关系

    在EXECEL中数字0 代表日期 1900-1-0 ,即这个日期为起始日期,算是第0天数字1 代表日期 1900-1-1 ,即第一天数字2 代表日期 1900-1-2 ,即第二天......数字415 ...

  2. ecshop 添加后台页面以及设置权限

    转自 http://blog.csdn.net/tgh1981/article/details/10394059 ecshop 添加新页面 给ecshop后台增加管理功能页面 比如我们增加一个统计报表 ...

  3. Django缓存1

    1. 开发调试 # 此为开始调试用,实际内部不做任何操作 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.du ...

  4. 用c#监控网络状态

    1.查询当前网络状态: using Microsoft.VisualBasic.Devices; //判断当前网络连接状态 Network nw=new Network(); if(nw.IsAvai ...

  5. ZooKeeper开发手册中文翻译

    本文假设你已经具有一定分布式计算的基础知识.你将在第一部分看到以下内容: ZooKeeper数据模型 ZooKeeper Sessions ZooKeeper Watches 一致性保证(Consis ...

  6. YUV 4:2:0 格式和YUV411格式区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/coloriy/article/details/6668447 MPEG 储存的 YU(Cb)V(Cr ...

  7. logback身份证脱敏

    logback身份证脱敏 学习了:https://shift-alt-ctrl.iteye.com/blog/2425469 https://blog.csdn.net/fywfengyanwei/a ...

  8. Redis在SSM项目中的简单使用

    一.基于SSM的Redis环境配置 前提是你的开发电脑安装和配置好了redis,如果没安装请看Window配置Redis环境和简单使用 1.1.pom文件中引入redis客户端jar包(pom.xml ...

  9. jni4net使用小结

    网站首页 http://jni4net.com/ 一个简单的例子: 1)      从这里下载binaries,然后解压缩. https://sourceforge.net/projects/jni4 ...

  10. LightCapture for Mac(流程化截图工具)破解版安装

    1.软件简介    LightCapture 是 macOS 系统上的截图软件.LightCapture Mac 版号称是用最简洁的方式来截图,其的界面也确实非常简单整洁,不过功能同样出色,一键截屏. ...