浅说Flux开发

前端之家收集整理的这篇文章主要介绍了浅说Flux开发前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

浅说Flux开发

前段时间,写了篇关于React的文件React:组件的生命周期,比较详细的说了下React组件的生命周期。

说道 React,很容易可以联想到 Flux。今天以 React 介绍及实践教程 一文中的demo为示例,简单说说 Flux 的开发方式。

Flux是什么

Flux 是 Facebook 用户建立客户端 Web 应用的前端架构, 它通过利用一个单向的数据流补充了 React 的组合视图组件。

Flux 的设计架构如图:

Flux 架构有三个主要部分:Dispatcher 、Store 和View(React 组件)。Store 包含了应用的所有数据,Dispatcher 负责调度,替换了 MVC中 的Controller,当 Action 触发时,决定了 Store 如何更新。当 Store变化后,View 同时被更新,还可以生成一个由Dispatcher 处理的Action。这确保了数据在系统组件间单向流动。当系统有多个 Store 和 View 时,仍可视为只有一个 Store 和一个 View,因为数据只朝一个方向流动,并且不同的 Store 和 View 之间不会直接影响彼此。

Flux的简单开发

在颜色盘的demo中,对界面的组件划分是这样的:

用户在 ColorPanel(View) 上产生一个 Action,Action 将数据流转到 Dispatcher,Dispatcher 根据 Action 传递的数据更新 Store,当 Store变化后,View 同时被更新。

(若你要获取本文的源代码,可以戳此:Flux-Demo

Store

Store 包含了应用的所有数据,并负责更新 View(ColorPanel),为简单,简化 Store 的定义:

  1. let EventEmitter = require('events').EventEmitter;
  2. let emitter = new EventEmitter();
  3.  
  4. export let colorStore = {
  5. colorId: 1,listenChange(callback){
  6. emitter.on('colorChange',callback);
  7. },getColorId(){
  8. return this.colorId
  9. },setColorId(colorId){
  10. this.colorId = colorId;
  11. emitter.emit('colorChange');
  12. }
  13. };

Dispatcher

Action 要靠 Dispatcher 去调度,才能更新 Store,并有 Store 去更新对应的 View 组件。定义一个 colorDispatcher 用于调度:

  1. import {Dispatcher} from 'flux';
  2. import {colorStore} from './colorStore';
  3.  
  4. export let colorDispatcher = new Dispatcher();
  5.  
  6. colorDispatcher.register((payload) => { switch (payload.action){ case 'CHANGE_COLOR_ID': colorStore.setColorId(payload.colorId); break; } });

Action

当鼠标悬浮在 ColorBar 中的一个颜色框时,根据颜色框 ID 的变化,ColorDisplay 显示对应的颜色。我们定义一个 Action 为 CHANGE_COLOR_ID:

  1. import {colorDispatcher} from './colorDispatcher';
  2.  
  3. export let colorAction = {
  4. changeColorId(colorId){
  5. colorDispatcher.dispatch({
  6. action: 'CHANGE_COLOR_ID',colorId: colorId
  7. })
  8. }
  9. };

建议定义的 Action 符合 FSA 规范。

View

按照上图的组件划分,我们渲染出界面:

ColorDisplay:

  1. import React,{Component} from 'react';
  2.  
  3. class ColorDisplay extends Component {
  4. shouldComponentUpdate(nextProps,nextState){
  5. return this.props.selectedColor.id !== nextProps.selectedColor.id;
  6. }
  7.  
  8. render(){
  9. return (
  10. <div className = 'color-display'>
  11. <div className = {this.props.selectedColor.value}>
  12. {this.props.selectedColor.title}
  13. </div>
  14. </div>
  15. )
  16. }
  17. }
  18.  
  19. export default ColorDisplay;

ColorBar:

  1. import React,{Component} from 'react';
  2. import {colorAction} from '../flux/colorAction';
  3. import {colorStore} from '../flux/colorStore';
  4.  
  5. class ColorBar extends Component {
  6. handleHover(colorId){
  7. let preColorId = colorStore.getColorId();
  8. if(preColorId != colorId){
  9. colorAction.changeColorId(colorId);
  10. }
  11. }
  12.  
  13. render(){
  14. return (
  15.  
  16. <ul>
  17. {/* Reaact中循环渲染元素时,需要用key属性确保正确渲染,key值唯一*/}
  18. {this.props.colors.map(function(color){
  19. return (
  20. <li key = {color.id}
  21. onMouSEOver = {this.handleHover.bind(this,color.id)}
  22. className = {color.value}>
  23. </li>
  24. )
  25. },this)}
  26. </ul>
  27. )
  28. }
  29. }
  30.  
  31. export default ColorBar;

ColorPanel:

  1. import React,{Component} from 'react';
  2. import ColorDisplay from './colorDisplay';
  3. import ColorBar from './colorBar';
  4. import {colorStore} from '../flux/colorStore'
  5.  
  6. class ColorPanel extends Component {
  7.  
  8. constructor(props){
  9. super(props);
  10. this.state = {
  11. selectedColor: this.getSelectedColor(colorStore.getColorId())
  12. };
  13. colorStore.listenChange(this.onColorHover.bind(this));
  14. }
  15.  
  16. getSelectedColor(colorId){
  17. if(! colorId){
  18. return null
  19. }
  20.  
  21. let length = this.props.colors.length;
  22. let i;
  23. for(i = 0; i < length; i++) {
  24. if(this.props.colors[i].id === colorId){
  25. break;
  26. }
  27. }
  28. return this.props.colors[i];
  29. }
  30.  
  31. shouldComponentUpdate(nextProps,nextState){
  32. return this.state.selectedColor.id !== nextState.selectedColor.id;
  33. }
  34.  
  35. render(){
  36. return (
  37. <div>
  38. <ColorDisplay selectedColor = {this.state.selectedColor} />
  39. <ColorBar colors = {this.props.colors} />
  40. </div>
  41. )
  42. }
  43.  
  44. onColorHover(){
  45. let colorId = colorStore.getColorId();
  46. this.setState({
  47. selectedColor: this.getSelectedColor(colorId)
  48. })
  49. }
  50. }
  51.  
  52. ColorPanel.defaultProps = {
  53. colors: [
  54. {id: 1,value: 'red',title: 'red'},{id: 2,value: 'blue',title: 'blue'},{id: 3,value: 'green',title: 'green'},{id: 4,value: 'yellow',title: 'yellow'},{id: 5,value: 'pink',title: 'pink'},{id: 6,value: 'black',title: 'black'}
  55. ]
  56. };
  57.  
  58. export default ColorPanel;

App:

  1. var ReactDom = require('react-dom');
  2. import React from 'react';
  3. import ColorPanel from './panel/colorPanel';
  4.  
  5. require('./app.css');
  6.  
  7. window.onload = function () {
  8. ReactDom.render(<ColorPanel />,document.getElementById('demos'));
  9. }

最终的的界面如下:

总结

本文简单的说了下如何利用 Flux 去开发实际应用,对于负载要求不高的应用,Flux 是完全可以使用的,复杂的富应用则可以借助 Redux + React 构建,Redux 负责数据分发和管理,其数据流的可控性比 Flux 更强,React 则依旧负责 View,但二者并不能直接连接,需要依赖 react-redux

若你要获取本文的源代码,可以戳此:Flux-Demo

原文出处:http://www.ido321.com/1658.html

猜你在找的React相关文章