【原】flux学习笔记
最近React(web/native)依旧如火如荼,相信大家都跃跃欲试,入职新公司,现在的团队也开始在React领域有所尝试. 2016年应该是
React 逐渐走向成熟的一年。之前在原来公司搞不懂的问题,同样是自学,发觉在新公司都搞懂了。哈哈,我也不知道为什么。
flux是干嘛的?
其实我刚开始学习的时候,一直不知道flux有什么鸟用。
官方说法是:Flux是Facebook内部用来构建React应用的一套架构。它本身并不是一个框架或库。它仅仅是一个用于完善React应用开发的一种新的应用程序架构, Flux架构最大的特点是其倡导的是单向数据流方案。
个人理解就是:比如我删除了一条数据,或者新增了一条数据,我怎么来让view知道我删除或者新增了该数据来做相应显示的改变呢,就是通过这种单向的数据流来告知,从而让数据的流动变得更加清晰。
比如 action就专门来处理你是点击删除,还是新增件,dispatcher就专门来派发这些动作,store就专门用来对数据的删除,增加做操作。view就专门来更新视图和发出动作。我是这么理解的。
首先来看看这张图:

flux包括了四个东西:
view: 视图
action:动作
dispatcher:派发器
store:数据层
打个比方,用户要删除一条数据,流程是这样的:
用户点击删除按钮-->传递给action,告诉action,我要删除啦-->派发器接收到了这个动作--->告诉store这个数据层。把用户点击的数据删除了-->store通过一个change时间告诉view,数据删掉了,然后显示的时候删掉的数据就没有了
demo1
写了一个demo,demo是在阮一峰大神的案例里做修改的。当然这篇文章也是基于阮一峰里的flux来写的,期间加一些自己的理解和思考
阮一峰flux地址:http://www.ruanyifeng.com/blog/2016/01/flux.html#comment-text
我的demo地址如下:https://github.com/xianyulaodi/myFluxTest
界面是这样的:

这个demo比较简单,就是数据的增加和删除,在输入框中输入内容,然后出来上面的东西,点击删除按钮可以对数据就行删除
下面对demo进行解读:
view部分
index.jsx
var React = require('react');
var ReactDOM = require('react-dom');
var MyButtonController = require('./components/MyButtonController');
ReactDOM.render(
<MyButtonController/>,
document.querySelector('#example')
);
比较简单,就是将组建渲染到页面上
component部分。
这里面包含两个组件,一个是 MyButtonController.jsx, 一个MyButton.jsx
MyButtonController.jsx内容如下:
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 () {
this.setState({
items: ListStore.getAll()
});
},
// view把用户的动作传给action。新增一个数据
createNewItem: function (event) {
var text=this.refs.myInput.value;
if(text!==''){
// 这个是action里面的函数 ,用户通过这个点击事件,告诉action,我点击了增加了按钮了
ButtonActions.addNewItem(text);
this.refs.myInput.value='';
}else{
alert('请输入内容');
}
},
// 删除元素,告诉action,我点击了删除按钮
deleteItem:function(id){
ButtonActions.destroy(id);
},
render: function() {
// 将事件传给这个组件的子组件,MyButton
return (
<div>
<MyButton
items={this.state.items}
onClick={this.createNewItem}
delFn={this.deleteItem}
/>
<input type="text" ref="myInput" placeholder="请输入内容" style={{"height":"25px","width":"200px","border":"1px solid #ccc"}}></input>
</div>
)
}
});
module.exports = MyButtonController;
这里先介绍这个组件的两个函数,createNewItem 和deleteItem .这里就相当于view发出的action.当触发这个事件的时候,就调用action里面对应的事件,从而将用户的动作达到一个传给action的作用。
MyButton是它的子组件,我们将这些事件传给它的子组件,由子组件来执行。
MyButton.jsx的内容如下:
var React = require('react');
var MyButton = function(props) {
var items = props.items;
var _this=this;
var itemHtml = items.map(function (ele, i) {
return <li key={i}>您增加的文本是:{ele.text},它的id是 {ele.id}<a href="#" onClick={props.delFn.bind(_this,ele.id)} >点击删除</a></li>;
});
return <div>
<ul>{itemHtml}</ul>
<button onClick={props.onClick}>确认添加</button>
</div>;
};
module.exports = MyButton;
它的作用主要是显示我们的内容。比如新增了什么,点击是否删除等等。
Action部分
var AppDispatcher = require('../dispatcher/AppDispatcher');
var ButtonActions = {
// 从用户那里传来的动作
addNewItem: function (text) {
AppDispatcher.dispatch({
actionType: 'ADD_NEW_ITEM',
text: text
});
},
destroy: function(id) {
AppDispatcher.dispatch({
actionType: 'DELETE_ITEM',
id: id
});
},
};
module.exports = ButtonActions;
因为我们只有两个动作,新增和删除,所以里面也只有两个事件。因为新增的是文本内容,所以我们传入text,因为删除是需要根据id来就行删除,所有我们传入id.
Dispatcher部分
var Dispatcher = require('flux').Dispatcher;
var AppDispatcher = new Dispatcher();
var ListStore = require('../stores/ListStore');
// 用来接收action,并把它传递到store,一个页面有且只有一个dispatcher,而且是全局的
AppDispatcher.register(function (action) {
switch(action.actionType) {
case 'ADD_NEW_ITEM':
// 根据传入动作的不同,来调用不同的数据
ListStore.addNewItemHandler(action.text);
ListStore.emitChange();
break;
case 'DELETE_ITEM':
ListStore.deleteItem(action.id);
ListStore.emitChange();
break;
default:
// no op
}
})
module.exports = AppDispatcher;
dispatcher的作用是派发器,根据不同的动作,来执行不同的store。也就是说,根据不同的动作,来生成不同的数据。比如上面的。如果你的动作是ADD_NEW_ITEM,那我就执行store里面的addNewItemHandler这个函数来生产数据。如果你是DELETE_ITEM这个动作,我就执行store里面的deleteItem这个动作来执行删除数据。
dispatcher就是这样来联系action和store的。那我怎么告诉页面我删除或者新增数据了呢,store里面的emitChange帮我们完成了这个动作。每次数据的改变,就执行一下这个 emitChange.来告诉view,我新增数据啦,你给我赶紧跟着跟新,我删除数据啦,给老子跟新你的页面
值得注意点是:在flux中,一个页面只有一个dispatcher.
store部分
// 这里就是相当于MVC中的model,只用来生成数据
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
// Store 更新后(this.addNewItemHandler())发出事件(this.emitChange()),
// 表明状态已经改变。 View 监听到这个事件,就可以查询新的状态,更新页面了。
var ListStore = assign({}, EventEmitter.prototype, {
items: [],
getAll: function () {
return this.items;
},
addNewItemHandler: function (text) {
// 新增一个元素
var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
var obj= {
id: id,
text: text
};
this.items.push(obj);
},
deleteItem:function(id){
// 删除指定元素
var myItems=this.items;
for (var i =0;i<myItems.length;i++) {
var delId=myItems[i].id;
if(id==delId){
this.items.splice(i,1);
}
}
},
emitChange: function () {
this.emit('change');
},
addChangeListener: function(callback) {
this.on('change', callback);
},
removeChangeListener: function(callback) {
this.removeListener('change', callback);
}
});
module.exports = ListStore;
在flux中,store的作用是数据工厂,也就是说所有的数据操作都在这里执行,不管你是新增也好,删除也好。还有就是view里面的数据都是从这里来的。
我们可以看到,我们首先定义了一个item这个数组用来存放数据。我们再来回看一下我们的 MyButtonController.jsx

初始化状态也是直接拿我们store里面的数据。
所以,flux就是一个数据流的操作方式,让我们的数据流动很清晰。向一条河流一样,流完这个地方才能到达另外一个地方。
flux缺点:
如果你搞懂了flux,虽然你会被他清晰的数据流所震撼和吸引,不过有没有发觉它很复杂,很啰嗦。比如我就想增加一个元素,兜了那么大的一个圈。
这也是它不好的地方之一。而且如果一个项目中,有些人才会用,有些人不会用。那也不好沟通。
所以在理解了flux之后,我准备去学redux了。
【原】flux学习笔记的更多相关文章
- Matplotlib学习笔记(二)
原 Matplotlib学习笔记 参考:Python数据科学入门教程 Python3.6.1 jupyter notebook .caret, .dropup > .btn > .car ...
- Matplotlib学习笔记(一)
原 matplotlib学习笔记 参考:Python数据科学入门教程 Python3.6.1 jupyter notebook .caret, .dropup > .btn > .ca ...
- 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL
周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...
- 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理
(1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...
- Flutter学习笔记(30)--Android原生与Flutter混编
如需转载,请注明出处:Flutter学习笔记(30)--Android原生与Flutter混编 这篇文章旨在学习如何在现有的Android原生项目上集成Flutter,实现Android与Flutte ...
- JUC源码学习笔记4——原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法
JUC源码学习笔记4--原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法 volatile的原理和内存屏障参考<Java并发编程的艺术> 原子类源码基于JDK8 ...
- 【原】redux异步操作学习笔记
摘要: 发觉在学习react的生态链中,react+react-router+webpack+es6+fetch等等这些都基本搞懂的差不多了,可以应用到实战当中,唯独这个redux还不能,学习redu ...
- Spring.NET学习笔记——目录(原)
目录 前言 Spring.NET学习笔记——前言 第一阶段:控制反转与依赖注入IoC&DI Spring.NET学习笔记1——控制反转(基础篇) Level 200 Spring.NET学习笔 ...
- ucos实时操作系统学习笔记——操作系统在STM32的移植
使用ucos实时操作系统是在上学的时候,导师科研项目中.那时候就是网上找到操作系统移植教程以及应用教程依葫芦画瓢,功能实现也就罢了,没有很深入的去研究过这个东西.后来工作了,闲来无聊就研究了一下这个只 ...
随机推荐
- [BZOJ1407][NOI2002]Savage(扩展欧几里德)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1407 分析: m,n范围都不大,所以可以考虑枚举 先枚举m,然后判定某个m行不行 某个 ...
- java 中遍历hashmap 和hashset 的方法
一.java中遍历hashmap: for (Map.Entry<String, Integer> entry : tempMap.entrySet()) { String ...
- 数据库表转javaBean
复制后修改部分代码 package com.study; import java.io.BufferedWriter; import java.io.File; import java.io.File ...
- python学习笔记整理——元组tuple
Python 文档学习笔记2 数据结构--元组和序列 元组 元组在输出时总是有括号的 元组输入时可能没有括号 元组是不可变的 通过分拆(参阅本节后面的内容)或索引访问(如果是namedtuples,甚 ...
- Chrome 自动填充的表单是淡黄色的背景
Chrome 自动填充的表单是淡黄色的背景解决方案; input:-webkit-autofill { -webkit-box-shadow: 0 0 0px 1000px #fff inset; - ...
- 初步认识ajax(个人整理)
通过使用ajax可以实现页面的部分动态化 ajax可以发送一个请求去服务端,而服务端则发送回一小段数据给客户端,这样就可以避免加载整个页面,因为很多时候页面只需要刷新某一部分的数据,而其他大部分体就不 ...
- Jenkins+svn+maven
首先我们在我们的服务器上安装好svn和maven 这里在前两步骤基本上没有啥问题,主要就是在Jenkins的步骤我弄了好长时间,这里记录一下 Jenkins的问题我是在这个网址解决的:http://b ...
- js-读取系统时间
转载 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.o ...
- APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了
APP的缓存文件到底应该存在哪?看完这篇文章你应该就自己清楚了 彻底理解android中的内部存储与外部存储 存储在内部还是外部 所有的Android设备均有两个文件存储区域:"intern ...
- Vim快捷键操作命令
Vim是一个超牛的编辑器,命令功能十分强大 .而且这些命令大都可以进行组合 ,比如,9yy命令表示复制9行内容,9表示要复制的行数,同样100dd表示删除100行,当数字和命令合作的时候,就比单纯的命 ...