Flux入门

这篇文章来自国外一位作者的Flux For Stupid People,文章没有深究flux的具体实现,但对于想入门flux的你会有所收获。

我应该使用Flux么

  • 如果你的应用有很多动态数据需要处理,你可能需要flux。
  • 如果你的应用多包含静态视图,并且很少涉及到数据的存储和更新,那么flux也许不会给你带来任何好处。

什么是Flux

Flux通过事件和监听来实现了单向数据流,具体请看后文。
我们在示例代码中使用了这两个库:Flux Dispatchermicroevent.js

官方的文档过于意识流,不适合新手学习。我们在学习时也不要将Flux与一些MVC框架相比,否则你会更加迷惑。

下面是一些Flux中提到的基本概念

1. Your Views "Dispatch" "Actions"(视图触发事件)

dispatcher 是一个基本的事件系统,他有自己的一些规则。他会广播事件,并注册回调函数。这里我们有仅一个全局的dispatcher。你应该使用FB的Dispatcher Library。初始化很容易:

var AppDispatcher = new Dispatcher(); 

假设你有一个按钮,点击之后会向列表增加一条数据。

<button onClick={ this.createNewItem }>New Item</button> 

点击之后,你的视图会分发一个action,其中有action的名称和增加的数据内容:

createNewItem: function( evt ){
  AppDispatcher.dispatch({
      actionName: 'new-item', 
      newItem: { name: 'Marco' } // 所需要增加的一条数据 
  });
}

"action"是一个核心概念。他是一个js对象,描述了我们需要做的事和我们需要的数据。如上所述,我们要做的是添加一条数据,我们需要的数据是一个名叫"Marco"的name。

Your "Store" Responds to Dispatched Actions(store触发回调)

store也是一个核心概念。我们在应用中创建一个集合,存放方法和数据,它通常是一个列表。

store是单例的,在你的整个应用中只有一个store存在:

// Single object representing list data and logic
var ListStore = {  
// Actual collection of model data 
  items: []
};

store会对被分发的action做出处理:

var ListStore = ...

//在dispatcher中注册我们需要监听的一些事件
AppDispatcher.register( function( payload ) {
    switch( payload.actionName ){
        //对action作出处理
        case 'new-item':
            //存储一个数据
            ListStore.items.push( payload.newItem);
            break;
   }
});

以上是一个典型的例子,介绍了Flux处理回调函数的方式。传入的参数payload包含了action的名称和需要处理的数据。
switch语句中会对相应的action做出数据的处理。

关键概念:

  • store不是MVC中的model,但是它包含了models。
  • 应用中数据处理只能在store中进行,这是Flux核心理念。被分发的action无法增加或者删除一条数据。

假设,你的应用中需要保存一些图片及其基本信息,那么你应该再创建一个Items,命名为ImageItems。一个数组即可代表一种数据类型了。

只有stores能够注册被分发action的回调函数。千万不要在视图中调用AppDispatcher.register。dispatcher只会单向地从视图传递数据给store。视图会针对不同的事件重新渲染。

Your Store Emits a "Change" Event(store触发change事件)

现在,store中的数据已经改变了,我们传递出数据改变的信息了。

我们将让store出发一个事件,如果在你使用了MicroEvent.js

MicroEvent.mixin( ListStore );

然后触发change事件:

case 'new-item':
     ListStore.items.push( payload.newItem ); 
  
   // Tell the world we changed! 
     ListStore.trigger('change');
     break;

关键概念:

  • 事件触发的时候不传递数据,视图只关心是否有数据发生变化。

Your View Responds to the "Change" Event(视图接收到事件重新渲染)

视图会在数据发生变化后重新渲染,没错是重新渲染。

我们在react组件的初始化完成后为store注册监听:

componentDidMount: function( ) {
    ListStore.bind( 'change', this.listChanged );
},

为了简单起见,我们调用forceUpdate,使视图重新渲染。

listChanged : function() {
    this.forceUpdate( );
},

别忘记在组件回收时,解绑监听的事件:

componentWillUnmount: function( ){
      ListStore.unbind( 'change', this.listChanged );
},

然后来看下组件的render函数:

render: function() {  
    // Remember, ListStore is global!  
    // There's no need to pass it around 
    var items = ListStore.getAll();  
    // Build list items markup by looping  
    // over the entire list 
    var itemHtml = items.map( function( listItem ) {  
      // "key" is important, should be a unique  
      // identifier for each list item 
        return <li key={ listItem.id }>
              { listItem.name }
                    </li>; 
      });
     return <div> 
                  <ul> { itemHtml } </ul> 
                  <button onClick={ this.createNewItem }>New Item</button> 
     </div>;
}

我们已经完成了整个数据,视图更新过程.当你添加一条数据的时候,视图会分发一个action,store会对action做出数据处理,并且触发一个change事件,之后视图接受到change事件并重新渲染。

但是有一个问题,每当数据更新的时候,视图将全部重新渲染,这样是否会造成效率低下?
其实并不会发生你所担心的事情,React内部构建了虚拟DOM,react会比较视图是否发生变化,实现部分的渲染,是以JS计算开销换取了dom渲染开销的方法来提升效率。

One More Thing: What The Hell Is An "Action Creator"?(Action Creator是什么鬼?)

我们在点击按钮的时候触发了一个action

AppDispatcher.dispatch({
     eventName: 'new-item', 
     newItem: { name: 'Samantha' }
 });

当我们拥有很多按钮,需要出发不同的action时,我们需要这么写看起来会比较优雅:

ListActions = { 
add: function( item ) { 
  AppDispatcher.dispatch({ 
      eventName: 'new-item', 
      newItem: item 
  }); 
}

del: ...

};

现在增加一条数据的时候就只需要这么写:ListActions.add({ name: '...' })

PS:不要使用 forceUpdate

文中只为了简单起见,使用了forceUpdate,正确的做法应该从store中读取数据,并且改变state,触发视图更新。

这里有一个demo,主要实现了一个简单的Todo。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 去年翻译的flux官方文档对flux架构的描述,觉得最近很多朋友开始react编程了,所以我觉得有必要拿出来这篇水...
    余歌_非鱼阅读 2,509评论 0 9
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,809评论 1 18
  • 翻译:莫铭原文地址:Flux-In Depth Overview Flux是Facebook用来构建客户端web应...
    莫铭阅读 2,093评论 0 0
  • 莫名其妙的来到这个世界,紧接着你和某些人有了联系,过了很多年,中间发生了很多事,最后她(他)们离开了你,莫名其妙的...
    b5ae43851ea6阅读 238评论 0 1
  • 广州刚又下了一场雨,雨后心情反而烦闷。
    话不多Mr阅读 241评论 0 0