前言

众所周知,React跟Flux是一对好基友。

其中,市场流行的Flux有Redux,Mobx,Reflux。

其中,用法最简单的是Reflux。

其数据流思路如下:

+---------+       +--------+       +-----------------+
¦ Actions ¦------>¦ Stores ¦------>¦ View Components ¦
+---------+ +--------+ +-----------------+
^ ¦
+--------------------------------------+

我们能否再减少其数据流路径?如下:

 +--------+       +-----------------+
¦ Stores ¦------>¦ View Components ¦
+--------+ +-----------------+
^ ¦
----------------------+

两个字,可以。

需求分析

  1. 集成Actions的功能到Stores。从而拿掉单独的Actions。
  2. 集成组件的State和Store在一起。
  3. 跨组件通信依赖其Store。

撸函数

这意味着我们的createStore是一个工厂函数。

用来生产每一个React组件实例对应的Store实例。

function isObject(obj) {
return Object.prototype.toString.call(obj) == '[object Object]';
} function extend(obj) {
if (!isObject(obj)) {
return obj;
}
for (let i = 1, length = arguments.length; i < length; i++) {
let source = arguments[i]; for (let prop in source) {
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
let propertyDescriptor = Object.getOwnPropertyDescriptor(source, prop);
Object.defineProperty(obj, prop, propertyDescriptor);
} else {
obj[prop] = source[prop];
}
}
}
return obj;
} function createStore(definition={}) { function Store() {
let t = this;
t.data = null;
extend(t, definition);
t.trigger = function () {
this.setState({});
} }
let store = new Store();
return store;
};

isObjectextend这两个函数按下不表。

其中,extend函数是用来对象合并,该函数某部位依赖isObject。((__) 嘻嘻……)

createStore函数产出的实例内部

  1. data作为组件实例的store。
  2. trigger作为更新组件实例的方法。

万事具备,只欠东风。

接下来就是用connect函数把组件实例和Store实例连接在一起。

function connect(listenable, context) {
if(!isObject(listenable)){
throw new Error('connect function\'s argument is not a object');
}
return {
componentDidMount() {
context = context || this;
listenable.trigger = listenable.trigger.bind(context);
},
componentWillUnmount() {
listenable.trigger = null;
}
};
}

借用React组件生命周期,在其componentDidMount阶段,

改变Store实例的trigger上下文,使其指向React组件实例,

从而方便trigger调用React组件实例的setState方法。

全套代码如下:

撸Demo

  • Samflux.js
function isObject(obj) {
return Object.prototype.toString.call(obj) == '[object Object]';
} function extend(obj) {
if (!isObject(obj)) {
return obj;
}
for (let i = 1, length = arguments.length; i < length; i++) {
let source = arguments[i]; for (let prop in source) {
if (Object.getOwnPropertyDescriptor && Object.defineProperty) {
let propertyDescriptor = Object.getOwnPropertyDescriptor(source, prop);
Object.defineProperty(obj, prop, propertyDescriptor);
} else {
obj[prop] = source[prop];
}
}
}
return obj;
} exports.createStore = function (definition={}) { function Store() {
let t = this;
t.data = null;
extend(t, definition);
t.trigger = function () {
this.setState({});
} }
let store = new Store();
return store;
}; exports.connect = function (listenable, context) {
if(!isObject(listenable)){
throw new Error('connect function\'s argument is not a object');
}
return {
componentDidMount() {
context = context || this;
listenable.trigger = listenable.trigger.bind(context);
},
componentWillUnmount() {
listenable.trigger = null;
}
};
}
  • store.js
const Samflux = require('./Samflux.js');
const Store = Samflux.createStore({
data:'old data',
onSetData: function(){
this.data = 'new data';
this.trigger();
},
}); module.exports = Store;
  • SamfluxTest.js
const Store = require('./store.js');
const Samflux = require('./Samflux.js');
const reactMixin = require('react-mixin');
const React = window.React;
require('./SamfluxTest.less'); class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
setData(){
Store.onSetData();
}
render() {
const me = this;
return (<div className="SamfluxTest" onClick={me.setData.bind(this)}><span>{Store.data}</span></div>);
}
} reactMixin.onClass(Test, Samflux.connect(Store));
module.exports = Test;

实现一个简单的flux的更多相关文章

  1. 响应式编程笔记三:一个简单的HTTP服务器

    # 响应式编程笔记三:一个简单的HTTP服务器 本文我们将继续前面的学习,但将更多的注意力放在用例和编写实际能用的代码上面,而非基本的APIs学习. 我们会看到Reactive是一个有用的抽象 - 对 ...

  2. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  3. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

  4. ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面

    前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...

  5. 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库

    57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...

  6. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

  7. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...

  8. CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator

    CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator 我还没有用过Compute Shader,所以现在把红宝书里的例子拿来了,加入CSharpGL中. ...

  9. 应用OpenMP的一个简单的设计模式

    小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...

随机推荐

  1. Docker相关知识整理

    一.进入和退出docker容器 使用docker ps查看容器id docker exec -it containerId /bin/bash //进入容器 Ctrl + P + Q //退出容器 二 ...

  2. JVM参数设置及条调优原理

    http://unixboy.iteye.com/blog/174173/     堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟 ...

  3. 调查显示数据分析已取代Web开发成为第一用例

    一项关于Python的开发者调查显示,编程语言现在主要用于数据分析,取代了之前的第一个用例Web开发. 去年秋天,由Python软件基金会和开发人员工具供应商JetBrains进行,2018 Pyth ...

  4. 【移动端】js禁止页面滑动与允许滑动

    禁止页面滑动 通常静止滑动方案:(阻止滑动事件) window.ontouchmove=function(e){ e.preventDefault && e.preventDefaul ...

  5. spring框架入门之一

    一.什么是Spring框架 1.什么是Spring Spring框架是个一个全栈的框架.意思就是使用Spring的框架可以开发web层,service层还有dao层. 本质:Spring就是一个对象的 ...

  6. 获取其他线程的数据用 queue, 多进程Q

    获取其他线程的数据用 queue, 多进程Q

  7. Tensorflow学习笔记01

    Tensorflow官方网站:http://tensorflow.org/ 极客学院Tensorflow中文版:http://wiki.jikexueyuan.com/project/tensorfl ...

  8. powermockito 常用操作

    1:Mock带参数的静态方法 PowerMockito类 package org.powermock.api.mockito; CityCodeBean cityCodeBean = CityCode ...

  9. 前端诡异参数start

    今天搞了一下午只为一个诡异事件:前端请求数据时总是会传一个start=20的参数,二搜索整个项目也找不出这个start的踪影. 倒是搜到一个pageLength的参数是20,但就是找不到start. ...

  10. Linux普通用户使用sudo免输密码(Debian/Redhat通用)

    今天使用的Debian,由于使用的是普通用户,而使用的sudo都需要输入密码的繁琐操作, 下面是使用sudo时免输入密码. 需要管理员权限进行以下操作. 修改sudoers vim /etc/sudo ...