相关资源


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. 3DMax 2014中文版安装破解教程

    周末的时候,因为帮忙别人做动画,要用到3dmax.然后发现自己真的很菜啊....弄了好久,然后终于阔以了,以后在慢慢研究.贴出详细的步骤: . 1.如果没有软件,就请自行下载[百度上很多的] 2.双击 ...

  2. ES-常见搜索方式

    1.query string search 2.query DSL 3.query filter 4.full-text search 5.phrase search 6.highlight sear ...

  3. 我使用过的Linux命令之date - 显示、修改系统日期时间(转)

    用途说明 ate命令可以用来显示和修改系统日期时间,注意不是time命令. 常用参数 格式:date 显示当前日期时间. 格式:date mmddHHMM 格式:date mmddHHMMYYYY 格 ...

  4. SQLite日期时间函数

    SQLite日期时间函数 SQLite支持以下五个日期时间函数: date(timestring, modifier, modifier, …) time(timestring, modifier, ...

  5. AllJoyn+Android开发案例-android跨设备调用方法

    AllJoyn+Android开发案例-android跨设备调用方法 项目须要涉及AllJoyn开源物联网框架.前面主要了解了一些AllJoyn主要的概念.像总线,总线附件,总线对象,总线接口这种概念 ...

  6. 了解 JavaScript (2)- 需要了解的一些概念

    Ajax 是什么 Ajax 是一种创建交互式 Web 应用程序的方式. Ajax 是 Asynchronous JavaScript and XML 缩写(异步的 JavaScript 和 XML), ...

  7. 权威公布:彻底搞清楚哪些笔记本和台式机主板能够支持42mm SATA M.2 NGFF(2242)接口的固态硬盘!!!

    在京东,天猫上搜寻半天.致电联想客服以及各个固态盘的店小二.都搞不清楚兼容性问题.并且联想客服的回答明显错误,官网描写叙述也错误,客服project师也含糊不清说:要拆机试一试才知道是否兼容. 我就不 ...

  8. PL/SQL学习笔记之循环语句

    一:基本循环 LOOP 循环体: 退出循环: )IF condition THEN exit; END IF; ) exit WHEN condition; END LOOP; 二:WHILE循环 W ...

  9. Shell脚本编程基础笔记二

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/8177697.html 一:输入 1:运行时参数 可以在启动脚本时,在其后输入参数. ./脚本 参数1 参数2. ...

  10. Bash 中的特殊字符大全【转】

    Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...