相关资源


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. Java 中的“implements Runnable” 和“extends Thread”(转)

    知识点 “implements Runnable” 和“extends Thread”的不同 具体分析 最近在学习Android中的Handler消息传递机制时,创建新线程有两种方式:一种是实现Run ...

  2. oracle中查找和删除重复记录的几种方法总结

    平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452 :不能创建唯一索引,发现重复记录. 下面总结一下几种查找和删除重复记录的方法(以表CZ为例): 表CZ的结 ...

  3. apache hbase 发布1.0.0版本

    今天apache发布了最新的hbase 1.0.0,下图是版本变迁历史: 详情参考: https://blogs.apache.org/hbase/entry/start_of_a_new_era

  4. 转载: ASP.NET Core入门系列文章

    今天在网上发现了ithome上的asp.net core 系列文章,对于新手入门还不错,这里转载一下,也方便查阅. [Day01] 從頭開始 [Day02] 程式生命週期 (Application L ...

  5. 外卖ERP管理系统(二)

    京门时代旗下外卖ERP管理系统是一款专注外卖行业的解决方案系统! 系统介绍: 1.外卖erp系统是一款集订单分发.一键派送.实时大屏监控.店铺进销存.仓储管理及数据分析为一体的智能化外卖管理系统.已服 ...

  6. 【iOS开发】关于显示一连串图片组成动画效果UIImageView的使用

    关于使用UIImageView显示一串图片组成动画效果的总结: 1>创建装这一串图片的容器,使用NSArray NSMutableArray *images = [NSMutableArray ...

  7. 阿里云 RDS 与 DRDS 学习了解

    RDS 主页:https://help.aliyun.com/document_detail/26092.html?spm=5176.7741872.6.539.4h8LSC DRDS 主页:http ...

  8. CentOS 的 /etc/profile 和 ~/.bash_profile 及 .zshrc

    交互式登陆shell 对于交互式的登陆shell而言,CentOS规定了startup文件的加载顺序如下: 登陆过程: 1. 读取并执行/etc/profile文件: 2. 读取并执行~/.bash_ ...

  9. 发布库到仓库 maven jcenter JitPack MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  10. plsql连接oracle数据库,不用配置任何东西(转)

    在软件开发的过程中,对于使用oracle的朋友们来说,使用plsql工具操作oracle数据库是非常方便的,可是plsql连接oracle数据库的方式有很多种,今天就给大家介绍一种最简单的连接方式,只 ...