资讯专栏INFORMATION COLUMN

React为什么需要Flux-like的库

wangtdgoodluck / 855人阅读

摘要:的关键构成梳理了一下,需要配合的库去使用,是因为要解决通信问题。还有各个事件之间,有可能存在依赖关系,事件后,也触发。相比于传统的事件系统,融入了不少的思想。中,将会是最大的门槛之一。

从学习React到现在的一点感受

我觉得应该有不少同学和我一样,上来学React,觉得甚是惊艳,看着看着,发现facebook 安利了一个flux,图画的巨复杂,然后各种例子都有用这个东西,没办法,硬着头皮看。看得似懂非懂,然后突然大家又都推荐Redux,号称最简单的flux-like的实现,结果实现的源码是很简单,但是文档是源码的几十倍,概念甩一脸,写个简单东西,要建十几个文件,写得云里雾里。

有没有想到,为什么要用Flux这类东西?本篇的定位是让大家知道有个脉络,所以不会太注意措辞的准确性.

React的数据流向

React只是一个view层的解决方案,光有界面没用,还得加上数据才行。React通过propsstate去渲染界面,所以有个很形象的描述UI = f(props,state).

有数据,就有数据通信的问题。react是单向数据流,父组件通过props把数据传递给子组件。但是数据的流向不可能只有这一种。

祖父组件到孙子组件。
这个看上去只是父到子的衍生,但是祖祖祖父到孙子组件呢。这个react在(好像是)0.13时通过context基本解决了,关于context,之前没接触的同学,可以看文档

子到父。下面是一种方案:父给子传递一个函数,子在只要调用这个函数,父就能得到相关的数据。但是孙子到祖祖祖父呢。。

非父子关系:基本可以叫做是兄弟关系,以网页为例,总归有一个共同的祖先,但是有可能是非常非常远的兄弟。这个怎么处理。

组件的一些关系和相应的通信方式,官方有简单的说明,见文档

对于上面的23两点,用react本事的机制,写出来都很别扭,特别是第3点。两个不相关的地方,要数据通信,最简单就是一个全局变量吗。当然光有全局变量还不行,你改了全局变量,其他所有对这个变量感兴趣React组件的都要被通知到,这样才能相应改变界面。你如果接触到设计模式,应该能想到观察者模式(中介者模式也可以,实际上flux更像中介者中,不过观察者应该接受度更高点,而且这里不影响理解)。

其实官方文档中,也有些小线索。

For communication between two components that don"t have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this.

这段的关键是you can set up your own global event system。所以你只要去研究以前各种事件系统是怎么设计,就可以自己撸一套 **ux了。

**UX的关键构成

梳理了一下,React需要配合Flux-Like的库去使用,是因为要解决通信问题。通信的关键有一下几点:

数据,这个不用说的吧。因为react中,通过setState去触发改变界面,命名成state

各种事件,叫event可能更直观,但是大家都叫它action,一个意思,发生了一个动作。这个动作有一下几个关键属性:什么动作,谁发出的(这个我看各个类flux库中,好像都没处理),有没有额外信息吗。

事件发生,要分发出去,包括改变数据,然后通知给所有监听数据变化的Listeners

注册监听者。

这些都是大家能想象到。好了,根据这几点,一个简单的Myux就可以写了

class Myux{
    state:{},
    actionTypes:{},
    dispatch(){},
    subscribe(){}
    listeners:[]
}

与上面四个组成部分项对应。来个例子吧,以计数器为例吧。

class CountStore{
    static actionTypes:{
        UP:"UP", //你英语好,你用increase
        DOWN:"DOWN"
    }
    
    state:0 //数据,计数开始是零
    listeners:[]
    
    dispatch(actionType){
        if(actionType === CountStore.actionTypes.UP){
            this.state++;
        }
        if(actionType === CountStore.actionTypes.DOWN){
            this.state--;
        }
        this.listeners.forEach((ln)=>{
            ln(actionType,this,undefined)//对应什么动作,谁发出的,额外信息。
        })
    }
    
    subscribe(ln){
        this.listeners.push(ln)
        //返回一个函数,调用,就取消注册
        return ()=>{
            const index = this.listeners.indexOf(ln);
            if(index !== -1){
                this.listeners.splice(index,1)
            }
        }
    }
}

react的组件里,只要注册成listener,然后state发生变化,被通知到,调用setState进行视图更新就好。

class CountComponent extends React.Component{
    constructor(props,context){
        super(props,context)
        const store = this.props.store;
        this.state = store.getState();
        
    }
    
    componentDidMount(){
        this.unsubscribe = store.subscribe((actionType,store)=>{
            if(this.state !== store.getState()){
                this.setState(store.getState());
            }
        })
    }
    
    componentWillUnmount(){
        if(typeof this.unsubscribe === "function"){
            this.unsubscribe();
        }
    }
    
    
    render(){
        const state = this.state
        return 
{state}
} }

使用吗,直接mount到body上,会报warning,忽略...

const countStore = new CountStore()
ReactDOM.render(
    ,
    document.body
)

这样,只要在任何地方,countStore.dispatch(upOrDown),CountComponent里的数字就会加加减减。
可以想想一下,如果页面有2,3个组件要根据计数器的数值,做界面的相应变化,都是可以轻松满足的。

当然,如果只有一个组件用需要这个store,那么单纯代码上,这样写,要多写很多东西。但是谁知道以后页面不会加一个要共用这个store的组件,这时候这个store就是组件间通信的法宝了。

实际情况要复杂

上面只有一个store,这是store还只有一个state,这个太简单了。实际,你的应用可能要维护多个状态。怎么办

一个store里一个state,然后多个store

    ListStore => ListState
    DetailStore => DetailState

全局就一个store,state是一个状态树,整个应用需要的state,都在这个树里。

    GlobalStore => state:{list:[],detail:{}} //...
    

还有一个问题dispatch,是全局一个dispatch,还是每个store一个dispatch

这些分歧,加上函数式等,就导致了有flux,reflux,redux。。

还有各个事件之间,有可能存在依赖关系,A事件后,B也触发。又要加waitFor中间件等概念。不过整体来说,就这些东西。

各种库特点大串烧 redux的特点

redux的文档里,有三大原则,有了上面的概念,我们来对照看一下

Single source of truth:就是更改应用一个state tree,储存在一个store里,这种情况,也只能有一个dispatch

State is read-only:state是全局的,如果不是只读的,很难维护。这个上面没有体现,但是也是很自然的想法。

Mutations are written as pure functions:这个算redux最大的特点,引入了reducers的概念,和第二点有相辅相成的感觉。

另外还有中间件系统。2、3两点,其实是函数式编程的基本概念,不变量pure function。相比于传统的事件系统,Redux融入了不少functional reactive programming(FRP)的思想。

flux的特点

单dispatch,多store多state,用waitFor处理store的依赖。

reflux

多dispatch,多store多state。这个并没实际用过,看文档,应该是这样的。有问题,请提出。

后记

现在有种趋势,传统的事件系统逐渐让大家觉得low b,functional reactive programming(FRP)高大上。
Redux有一些FRP的思想,被大家觉得比Flux高大上,但是不是很复杂的项目,应该会有:卧槽,那么简单的东西,为毛有那么多文件,写得那么绕的感觉。

angular2中,RxJS将会是最大的门槛之一。

我觉得把,从能解决问题的复杂度上,FRP的确比传统的事件系统高级,但是概念也更多,不是特复杂的程序,这些概念只会增加你的开发难度,并且对后面维护的人要求更高。

Java那么多年,没RxJava,服务器端,android端,那么多年也挺过来了,虽然先进,不一定合适。我们现在自己的项目,使用的就是自己撸的一个小东西。对我们现在的规模,开发和维护都挺好的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86184.html

相关文章

  • 专治前端焦虑的学习方案

    摘要:不过今天我希望能够更进一步,不仅仅再抱怨现状,而是从我个人的角度来给出一个逐步深入学习生态圈的方案。最后,我还是想提到下对于的好的学习方法就是回顾参照各种各样的代码库,学习人家的用法与实践。 本文翻译自A-Study-Plan-To-Cure-JavaScript-Fatigue。笔者看到里面的几张配图着实漂亮,顺手翻译了一波。本文从属于笔者的Web Frontend Introduc...

    codeGoogle 评论0 收藏0
  • React 升级:Redux

    摘要:正如我们前面的教程所提到的,在组件之间流通数据更确切的说,这被叫做单向数据流数据沿着一个方向从父组件流到子组件。这就是如何使数据流变得更简单的原因。它是一种倾向单向数据流比如的设计模式。这是因为总是接受和返回状态用来更新。 前言 近期接触React项目,学到许多新知识点,网上教程甚多,但大多都把知识点分开来讲,初学者容易陷入学习的误区,摸不着头脑,本人在学习中也遇到许多坑。此篇文章是笔...

    garfileo 评论0 收藏0
  • 14个最好的 JavaScript 数据可视化库

    摘要:适用于,演示这是开发的一个简单的可视化库,它允许你创建所有常用的图表类型条形图,树形图,折线图,面积图等。可以轻松地对折线图和条形图进行混合和匹配以组合不同的数据集,这是非常棒的功能。 翻译:疯狂的技术宅原文:https://www.monterail.com/blo... 本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章 你的程序有多...

    Mertens 评论0 收藏0
  • 精读《12 个评估 JS 库你需要关心的事》

    摘要:大公司广泛使用的开源库,并且有一定国际影响力,而且大厂也有成功开源历史经验的话,就会增加说服力。总结下次技术选型讨论时,可以拿出规则一条一条比对了然后技术选型只是基础库,利用这些基础可以维护好自己的开源库,把更多时间用在创造业务价值上。 1 引言 作者给出了从 12 个角度全面分析 JS 库的可用性,分别是: 特性。 稳定性。 性能。 包生态。 社区。 学习曲线。 文档。 工具。 发...

    junbaor 评论0 收藏0
  • 一个治愈 JavaScript 疲劳的学习计划

    摘要:只是抱怨事物的状态并没有什么卵用,我打算给你一个实实在在的一步一步征服生态圈的学习计划。好消息是,这刚好是本学习计划关注的问题。比如,一个不错的出发点是的课。是一个由创建和开源的库。我个人推荐的初学者课程。而个人项目是尝试新技术的完美时机。 本文转载自:众成翻译译者:网络埋伏纪事链接:http://www.zcfy.cc/article/1617原文:https://medium.fr...

    jhhfft 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<