React为何须要Flux-like的库

从进修React到如今的一点觉得

我以为应当有不少同砚和我一样,上来学React,以为甚是冷艳,看着看着,发明facebook 安利了一个flux,图画的巨庞杂,然后种种例子都有效这个东西,没办法,硬着头皮看。看得似懂非懂,然后倏忽人人又都引荐Redux,号称最简朴的flux-like的完成,效果完成的源码是很简朴,然则文档是源码的几十倍,观点甩一脸,写个简朴东西,要建十几个文件,写得云里雾里。

有无想到,为何要用Flux这类东西?本篇的定位是让人人晓得有个头绪,所以不会太注重说话的准确性.

React的数据流向

React只是一个view层的处理计划,光有界面没用,还得加上数据才行。React经由过程propsstate去衬着界面,所以有个很抽象的形貌UI = f(props,state).

有数据,就有数据通讯的题目。react是单向数据流,父组件经由过程props把数据通报给子组件。然则数据的流向不能够只需这一种。

  1. 祖父组件到孙子组件。
    这个看上去只是父到子的衍生,然则祖祖祖父到孙子组件呢。这个react在(彷佛是)0.13时经由过程context基础处理了,关于context,之前没打仗的同砚,能够看文档

  2. 子到父。下面是一种计划:父给子通报一个函数,子在只需挪用这个函数,父就可以获得相干的数据。然则孙子到祖祖祖父呢。。

  3. 非父子关联:基础能够叫做是兄弟关联,以网页为例,总归有一个合营的先人<body>,然则有多是异常异常远的兄弟。这个怎样处置惩罚。

组件的一些关联和响应的通讯体式格局,官方有简朴的申明,见文档

关于上面的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的库去运用,是由于要处理通讯题目。通讯的症结有一下几点:

  1. 数据,这个不必说的吧。由于react中,经由过程setState去触发转变界面,定名成state

  2. 种种事宜,叫event能够更直观,然则人人都叫它action,一个意义,发作了一个行动。这个行动有一下几个症结属性:什么行动,谁发出的(这个我看各个类flux库中,彷佛都没处置惩罚),有无分外信息吗。

  3. 事宜发作,要分发出去,包含转变数据,然后关照给一切监听数据变化的Listeners

  4. 注册监听者。

这些都是人人能设想到。好了,依据这几点,一个简朴的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 <div>{state}</div>
    }
}

运用吗,直接mount到body上,会报warning,疏忽…

const countStore = new CountStore()
ReactDOM.render(
    <CountComponent store={countStore}/>,
    document.body
)

如许,只需在任何处所,countStore.dispatch(upOrDown),CountComponent里的数字就会加加减减。
能够想一想一下,假如页面有2,3个组件要依据计数器的数值,做界面的响应变化,都是能够轻松满足的。

固然,假如只需一个组件用须要这个store,那末纯真代码上,如许写,要多写许多东西。然则谁晓得今后页面不会加一个要共用这个store的组件,这时候这个store就是组件间通讯的宝贝了。

现实状况要庞杂

上面只需一个store,这是store还只需一个state,这个太简朴了。现实,你的运用能够要保护多个状况。怎样办

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

    
        ListStore => ListState
        DetailStore => DetailState
    
  2. 全局就一个store,state是一个状况树,全部运用须要的state,都在这个树里。

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

    另有一个题目dispatch,是全局一个dispatch,照样每一个store一个dispatch

这些不合,加上函数式等,就致使了有flux,reflux,redux。。

另有各个事宜之间,有能够存在依靠关联,A事宜后,B也触发。又要加waitFor中间件等观点。不过团体来讲,就这些东西。

种种库特性大串烧

redux的特性

redux的文档里,有三大原则,有了上面的观点,我们来对比看一下

  1. Single source of truth:就是变动运用一个state tree,储存在一个store里,这类状况,也只能有一个dispatch

  2. State is read-only:state是全局的,假如不是只读的,很难保护。这个上面没有表现,然则也是很天然的主意。

  3. 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端,那末多年也挺过来了,虽然先进,不一定适宜。我们如今本身的项目,运用的就是本身撸的一个小东西。对我们如今的范围,开辟和保护都挺好的。

    原文作者:神猪_uuid
    原文地址: https://segmentfault.com/a/1190000003982553
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞