React: 研究React Redux的使用

一、简介

在上一篇的Redux文章中,详细介绍了Redux的概念和综合利用,开发者可以通过Redux的State管理系统管理整个应用程序的数据流,依靠功能完备的Store来分发Action,进而渲染和更新组件的UI。在我们之前的文章介绍中,根组件是保存State的组件,一般的Web开发,都是将State数据作为属性,从根组件向下传递给子组件,当子组件触发事件时,数据再通过回调函数的属性沿着组件树向上回到了根组件。这种数据在组件树中向上和向下传递的过程增加了程序的复杂性,于是乎,类似Redux的库就是为此问题而生,它通过直接从子组件分发Action来达到更新应用程序State的目的,摒弃了通过双向函数绑定实现组件树的数据传递的方式。本章的目的就是讲如何把Redux中构建的Store和UI组件整合起来,即React Redux应用。现在对比一下传统的数据流在组件树中的传递方式和采用Redux管理State的方式,流程图和代码表示大概分别如下:

 

          图一                                  图二

图一对应的代码:根组件将state数据作为子组件的属性向下传递。

//根组件文件:App.jsimport React, { Component } from ‘react‘;

import NameList from ‘./redux/component/NameList‘
import NameForm from "./redux/component/NameForm";

export default class App extends Component {

    constructor(props){
        super(props);

        //初始化state数据
        this.state = {
            names:[
                {
                    "name_id":"1",
                    "name":"张三",
                },
                {
                    "name_id":"2",
                    "name":"李四",
                }
            ],
            subjects:[
                {
                    "subject_id":"1",
                    "subject":"数学",
                },
                {
                    "subject_id":"2",
                    "subject":"语文",
                }
            ],
            scores:[
                {
                    "score_id":"1",
                    "score": 90,
                },
                {
                    "score_id":"2",
                    "score": 95,
                }
            ]
        };

        //绑定事件
        this.addName = this.addName.bind(this);
        this.deleteName = this.deleteName.bind(this);
        this.updateName = this.updateName.bind(this);
    }

    addName(new_name_id, name){
        this.setState({
        ...
        });
    };

    deleteName(name_id){
        this.setState({
        ...
        });
    };

    updateName(name_id, name){
        this.setState({
        ...
        });
    };

    render() {
        const {names} = this.state;
        const {addName,deleteName,updateName} = this;
        return (
            <div className="app">
                <NameList names={names}/>
                <NameForm onAddName={addName} onDeleteName={deleteName} onUpdateName={updateName}/>
            </div>
        )
    }
}

图二对应的代码:根组件和子组件都是通过store获取state数据。

//入口文件:index.js
//-------------  React Redux 显示传递Store-------------------//
import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import ‘./index.css‘;

//通过类方法创建store
import storeFactory from "./redux/store_factory";
const store = storeFactory();

const render = () =>
        ReactDOM.render(
            <App store={store}/>,
            document.getElementById(‘root‘)
        );

store.subscribe(render);
render();

//根组件文件:App.js
import React  from ‘react‘;

import NameList from ‘./redux/component/NameList‘
import NameForm from "./redux/component/NameForm";

const App = ({store}) =>
            <div className="app">
                <NameList store={store}/>
                <NameForm store={store}/>
            </div>;

export default App;  

二、传统方式的应用

上面图一代码举例了传统的数据流在组件树中的传递方式,从中大略地可以看到State数据在根组件和子组件间双向流动的关系。具体的实现交互,完整代码如下:

App.js

import React, { Component } from ‘react‘;

import NameList from ‘./redux/component/NameList‘
import NameForm from "./redux/component/NameForm";

//---------------------- 传统方式 -----------------------------------//
export default class App extends Component {

    constructor(props){
        super(props);

        //初始化state数据
        this.state = {
            names:[
                {
                    "name_id":"1",
                    "name":"张三",
                },
                {
                    "name_id":"2",
                    "name":"李四",
                }
            ],
            subjects:[
                {
                    "subject_id":"1",
                    "subject":"数学",
                },
                {
                    "subject_id":"2",
                    "subject":"语文",
                }
            ],
            scores:[
                {
                    "score_id":"1",
                    "score": 90,
                },
                {
                    "score_id":"2",
                    "score": 95,
                }
            ]
        };

        //绑定事件
        this.addName = this.addName.bind(this);
        this.deleteName = this.deleteName.bind(this);
        this.updateName = this.updateName.bind(this);
    }

    addName(new_name_id, name){
        this.setState({
            names:[...this.state.names, {"name_id":new_name_id,"name":name}],
            subjects:this.state.subjects,
            scores:this.state.scores
        });
    };

    deleteName(name_id){
        this.setState({
            names:this.state.names.filter(item => item.name_id !== name_id),
            subjects:this.state.subjects,
            scores:this.state.scores
        });
    };

    updateName(name_id, name){
        this.setState({
            names:this.state.names.map(item => (item.name_id === name_id) ? ({...item, name}) : item),
            subjects:this.state.subjects,
            scores:this.state.scores
        });
    };

    render() {
        const {names} = this.state;
        const {addName,deleteName,updateName} = this;
        return (
            <div className="app">
                <NameList names={names}/>
                <NameForm onAddName={addName} onDeleteName={deleteName} onUpdateName={updateName}/>
            </div>
        )
    }
}

NameList.js

import React, { Component } from ‘react‘;

export default class NameList extends Component{

    render(){
        const {names} = this.props;
        return (
            <div>
                <table border="1" cellPadding="5" cellSpacing="0" bgcolor="F2F2F2" width="50%">
                    <tbody>
                        <tr id="infoTr">
                            <td>ID</td>
                        <td>姓名</td>
                        </tr>
                    </tbody>
                    {
                        names.map((item,key) => (
                            <tbody key={key}>
                                <tr id="infoTr">
                                    <td>{item.name_id}</td>
                                    <td>{item.name}</td>
                                </tr>
                            </tbody>
                        ))
                    }
                </table>
            </div>
        );
    }
}

NameForm.js

import React, { Component} from ‘react‘;
import PropTypes from ‘react-dom‘

export default class NameForm extends Component{

    static propsTypes = {
        onAddName: PropTypes.func,
        onDeleteName: PropTypes.func,
        onUpdateName: PropTypes.func
    };

    addName(){
        this.props.onAddName("3","王五");
    };

    deleteName(){
        this.props.onDeleteName("1");
    };

    updateName(){
        this.props.onUpdateName("2","赵六");
    };

    render(){
        const divStyle = {marginTop:10};
        const spanStyle = {padding:10,margin:10};
        return (
            <div style={divStyle}>
                <span style={spanStyle}><button onClick={this.addName.bind(this)}>添加</button></span>
                <span style={spanStyle}><button onClick={this.deleteName.bind(this)}>删除</button></span>
                <span style={spanStyle}><button onClick={this.updateName.bind(this)}>更新</button></span>
            </div>
        );
    }
}

演示结果

三、React Redux的应用

1、显式传递Store

在React Redux中,将Store集成到UI中最合乎逻辑的做法是显式地将它作为属性在组件树中向下传递。上面图二代码中传递Store的方式就是显式传递的。这种方法很简单,对于只包含少量嵌套组件的小型应用程序效果非常好。如代码所示,APP组件作为根组件,它通过属性获取了Store,然后显式地向下传递给了子组件NameList组件和NameForm组件。此时,所有子组件可以使用store.getState从store中获取State数据了,并且可以使用store.dispatch将Action分发到Store。在子组件中可以引入之前创建的Action生成器。具体代码如下所示:

index.js

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import ‘./index.css‘;

//通过类方法创建store
import storeFactory from "./redux/store_factory";
const store = storeFactory();

const render = () =>
        ReactDOM.render(
            <App store={store}/>,
            document.getElementById(‘root‘)
        );

store.subscribe(render);
render();

App.js

import React, { Component } from ‘react‘;

import NameList from ‘./redux/component/NameList‘
import NameForm from "./redux/component/NameForm";

const App = ( {store}) =>
            <div className="app">
                <NameList store={store}/>
                <NameForm store={store}/>
            </div>;

export default App;

NameList.js

import React, { Component } from ‘react‘;

const NameList = ({store}) => {

    //通过store获取state数据
    const {names} = store.getState();
    return (
        <div>
            <table border="1" cellPadding="5" cellSpacing="0" bgcolor="F2F2F2" width="50%">
                <tbody>
                <tr id="infoTr">
                    <td>ID</td>
                    <td>姓名</td>
                </tr>
                </tbody>
                {
                    names.map((item,key) => (
                        <tbody key={key}>
                        <tr id="infoTr">
                            <td>{item.name_id}</td>
                            <td>{item.name}</td>
                        </tr>
                        </tbody>
                    ))
                }
            </table>
        </div>
    )
};

export default NameList;

NameForm.js

import React, { Component} from ‘react‘;

//导入前篇文章中写的action生成器
import {addName,deleteName,updateName} from "../action_builder";

const NameForm = ({store}) => {

    const add_name = e => {
        e.preventDefault();
        store.dispatch(addName("3","王五"))
    };

    const delete_name = e => {
        e.preventDefault();
        store.dispatch(deleteName("2"))
    };

    const update_name = e => {
        e.preventDefault();
        store.dispatch(updateName("1","赵六"))
    };

    const divStyle = {marginTop:10};
    const spanStyle = {padding:10,margin:10};
    return (
        <div style={divStyle}>
            <span style={spanStyle}><button onClick={add_name}>添加</button></span>
            <span style={spanStyle}><button onClick={delete_name}>删除</button></span>
            <span style={spanStyle}><button onClick={update_name}>更新</button></span>
        </div>
    );
};

export default NameForm;

演示结果:

2、通过上下文传递Store

在组件间除了可以显式地传递Store外,还有其他获取Store的方式,例如通过上下文的方式传递Store。它允许在组件树中不显式地向下传递属性的情况下将变量传递给组件。任意子组件都可以访问这些上下文变量。一般的操作是index文件保持基本的渲染入口,同时传递store时去掉订阅,然后需要在根组件App中保存上下文,并监听Store以便及时刷新UI。注意,需要在组件中引入类型验证来确定上下文类型,否则组件无法从上下文中获取Store,若在使用‘react‘中的PropTypes时出现depredcated,说明这种导入方式已经过期,推荐的正确安装如下:

//1.安装PropTypes
npm install -S prop-types

//2.导入PropTypes
import PropTypes from ‘prop-types‘;

//而不是这样做:
import { PropTypes } from ‘react‘;

在根组件中完成了相关的上下文设置后,在内嵌子组件时就不用给子组件传递props或者store了,子组件完全自己可以从上下文中获取store。具体完整的代码示例如下所示:

index.js

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import ‘./index.css‘;

import storeFactory from "./redux/store_factory";

//通过类方法创建store
const store = storeFactory();

ReactDOM.render(
    <App store={store}/>,
    document.getElementById(‘root‘)
);

App.js

import React, { Component } from ‘react‘;

import NameList from ‘./redux/component/NameList‘
import NameForm from "./redux/component/NameForm";

import PropTypes from ‘prop-types‘;

export default class App extends Component{

    //从上下文获取store
    getChildContext(){
        return {
            store: this.props.store
        }
    }

    //添加订阅任务
    componentWillMount() {
        this.unsubscribe = this.props.store.subscribe(
            () => this.forceUpdate()
        )
    }

    //退订监听者
    componentWillUnmount() {
        this.unsubscribe();
    }

   //内嵌子组件的数据不用再由根组件向下传递
    render() {
        return (
            <div className="app">
                <NameList />
                <NameForm />
            </div>
        )
    }
}

//属性类型验证
App.propTypes = {
    store: PropTypes.object.isRequired
};

//上下文类型验证
App.childContextTypes = {
    store: PropTypes.object.isRequired
};

//注意类型验证必不可少

NameList.js

import React, { Component } from ‘react‘;

import PropTypes from "prop-types";

//上下文会排在props后面,作为第二个参数传递给无状态函数式组件。
//我们可以通过对象解构直接从参数中的对象获取Store。为了使用Store,我们可以在NameList示例上定义contextTypes 。
//这是为了告知React该组件将会使用的上下文变量类型。这是一个必需的步骤。如果没有它,用于将无法从上下文中读取Store。

const NameList = (props, {store}) => {

    //通过store获取state数据
    const {names} = store.getState();
    return (
        <div>
            <table border="1" cellPadding="5" cellSpacing="0" bgcolor="F2F2F2" width="50%">
                <tbody>
                <tr id="infoTr">
                    <td>ID</td>
                    <td>姓名</td>
                </tr>
                </tbody>
                {
                    names.map((item,key) => (
                        <tbody key={key}>
                        <tr id="infoTr">
                            <td>{item.name_id}</td>
                            <td>{item.name}</td>
                        </tr>
                        </tbody>
                    ))
                }
            </table>
        </div>
    )
};

//上下文中store类型验证
NameList.contextTypes = {
    store: PropTypes.object
};

export default NameList;

NameForm.js

import React, { Component} from ‘react‘;

import {addName,deleteName,updateName} from "../action_builder";
import PropTypes from "prop-types";

//同样地,NameForm组件也必须定义contextTypes。然后才能从上下文中获取store。

export default class NameForm extends Component{

    constructor(props){
        super(props);
        this.addName = this.addName.bind(this);
        this.deleteName = this.deleteName.bind(this);
        this.updateName = this.updateName.bind(this);
    }

    addName(){
        const {store} = this.context;   //从上下文中获取store
        store.dispatch(addName("3","陈七"))
    };

    deleteName(){
        const {store} = this.context;  //从上下文中获取store
        store.dispatch(deleteName("2"))
    };

    updateName(){
        const {store} = this.context;  //从上下文中获取store
        store.dispatch(updateName("3","李八"))
    };

    render(){
        const divStyle = {marginTop:10};
        const spanStyle = {padding:10,margin:10};
        return (
            <div style={divStyle}>
                <span style={spanStyle}><button onClick={this.addName}>添加</button></span>
                <span style={spanStyle}><button onClick={this.deleteName}>删除</button></span>
                <span style={spanStyle}><button onClick={this.updateName}>更新</button></span>
            </div>
        );
    }
}

//上下文中store类型验证
NameForm.contextTypes = {
    store: PropTypes.object
};

演示结果:

3、表现层和容器组件

在上面的示例中,我们既采用了显式地的方式传递Store,还采用了上下文的方式传递Store,然后通过Store来获取State数据。这些组件都是直接和Redux的Store交互来渲染UI元素的。其实,开发者还可以将Store和渲染UI组件的关系进行脱离,进一步来优化应用程序的架构。在上面示例中的NameList、NameForm都是表现层组件,它们是直接负责渲染UI元素的组件,并没有和任何数据结构紧密地耦合在一起。它们只是通过属性接收数据,并且通过回调函数将数据回传到父组件。可以说,它们就是纯粹地聚焦于UI,可以达到不同数据亦可复用的目的。在新型架构中,表现层作为其中的一部分,同时还有一个部分就是容器组件。容器组件就是将表现层和数据关联起来的组件,容器组件将通过上下文访问Store,负责通过Store管理交互。容器组件通过映射属性到State和将回调函数属性传递给Store的dispatch方法,以此完成渲染表现层组件的工作。也就是说,容器组件聚焦于数据,并将表现层与其关联。这种架构的优势是明显的,表现层组件和容器组件都可复用,易替换,易测试。现在我们在同一个文件中给NameList和NameForm定义容器组件,当然App组件大致会保持原样,仍然在上下文对象中定义Store,以便子组件可以访问它,它唯一变动的地方就是嵌入的子组件从表现层组件修改为容器组件。如下所示:

index.js

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import ‘./index.css‘;

import storeFactory from "./redux/store_factory";

//通过类方法创建store
const store = storeFactory();

ReactDOM.render(
    <App store={store}/>,
    document.getElementById(‘root‘)
);

App.js

import React, { Component } from ‘react‘;

import PropTypes from ‘prop-types‘;

import { NameListProvider, NameFormProvider } from ‘./redux/component/NameProvider‘

//此时App的子组件不再是NameList和NameForm表现层组件
//而是都是容器组件NameListProvider、NameFormProvider
export default class App extends Component{

    //从上下文获取store
    getChildContext(){
        return {
            store: this.props.store
        }
    }

    //添加订阅任务
    componentWillMount() {
        this.unsubscribe = this.props.store.subscribe(
            () => this.forceUpdate()
        )
    }

    //退订监听者
    componentWillUnmount() {
        this.unsubscribe();
    }

    render() {
        return (
            <div className="app">
                <NameListProvider />
                <NameFormProvider />
            </div>
        )
    }
}

//属性中store类型验证
App.propTypes = {
    store: PropTypes.object.isRequired
};

//上下文中store类型验证
App.childContextTypes = {
    store: PropTypes.object.isRequired
};

NameList.js

import React, { Component } from ‘react‘;

export default class NameList extends Component{

    render(){
        const {names} = this.props;
        return (
            <div>
                <table border="1" cellPadding="5" cellSpacing="0" bgcolor="F2F2F2" width="50%">
                    <tbody>
                    <tr id="infoTr">
                        <td>ID</td>
                        <td>姓名</td>
                    </tr>
                    </tbody>
                    {
                        names.map((item,key) => (
                            <tbody key={key}>
                            <tr id="infoTr">
                                <td>{item.name_id}</td>
                                <td>{item.name}</td>
                            </tr>
                            </tbody>
                        ))
                    }
                </table>
            </div>
        );
    }
}

NameForm.js

import React, { Component} from ‘react‘;

import PropTypes from "prop-types";

//按钮事件中,直接调用容器组件传递过来的属性函数
//这些属性函数会在Provider组件中调用dispatch函数分发action
export default class NameForm extends Component{

    static propsTypes = {
        onAddName: PropTypes.func,
        onDeleteName: PropTypes.func,
        onUpdateName: PropTypes.func
    };

    render(){
        const divStyle = {marginTop:10};
        const spanStyle = {padding:10,margin:10};
        const {onAddName,onDeleteName,onUpdateName} = this.props;
        return (
            <div style={divStyle}>
                <span style={spanStyle}><button onClick={() => onAddName()}>添加</button></span>
                <span style={spanStyle}><button onClick={() => onDeleteName()}>删除</button></span>
                <span style={spanStyle}><button onClick={() => onUpdateName()}>更新</button></span>
            </div>
        );
    }
}

NameProvider.js

import NameList from ‘./NameList‘
import NameForm from "./NameForm";
import PropTypes from "prop-types";
import React, { Component } from ‘react‘;
import {addName,deleteName,updateName} from "../action_builder";

//姓名列表容器组件
export const NameListProvider = (props, {store}) => {
    const {names} = store.getState();
    return <NameList names={names}/>
};

NameListProvider.contextTypes = {
    store: PropTypes.object
};

//姓名操作容器列表
//在回调函数中调用dispatch函数分发action
export const NameFormProvider = (props, {store}) => {
    return (
        <NameForm
            onAddName={ () => store.dispatch(addName("4","猪八戒")) }
            onDeleteName={ () => store.dispatch(deleteName("1")) }
            onUpdateName={ ()=> store.dispatch(updateName("2","孙悟空")) }
        />
    )
};

NameFormProvider.contextTypes = {
    store: PropTypes.object
};

演示结果:

4、React Redux的Provider容器组件和connect函数

通过将UI组件和容器分离的方式将它们与数据连接是一个不错的优化方案,但是,这对于小型的项目、概念验证性或者原型项目来说是大材小用了。React Redux是一个脚本库,它包含的一些工具可以显著降低显式通过上下文传递Store的复杂性。React Redux为开发者提供了一个默认的Provider容器组件,开发者通过它在上下文中配置属于自己的Store,它可以包装任意的React元素,该元素的所有子元素都将能够通过上下文访问Store,该组件去掉了类型验证这一操作,实现更简单了。也即是说在Provider中配置一次Store后,它会把Store作为属性进行传递,它的子组件皆可访问。 React Redux还为开发者提供了另一种配合Provider快速创建容器组件的方式,即connect函数。connect函数是一个高阶函数,它既可以通过将Redux的Store中当前State映射为表现层组件的属性来创建容器组件,还可以将Store的dispatch函数映射成回调函数。具体的代码如下所示:

index.js

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;
import ‘./index.css‘;

import storeFactory from "./redux/store_factory";
import {Provider} from ‘react-redux‘

//通过类方法创建store
//直接把Store作为容器组件Provider的属性,向下传递
//App以及它的所有组件均可访问
const store = storeFactory();
ReactDOM.render(
    <Provider store={store}>
        <App/>
    </Provider>,
    document.getElementById(‘root‘)
);

App.js

import React, { Component } from ‘react‘;
import { NameListProvider, NameFormProvider } from ‘./redux/component/NameProvider‘

//去掉了类型验证这步操作
const App = () =>
    <div className="app">
           <NameListProvider />
           <NameFormProvider />
    </div>;
export default App;

NameList.js

import React, { Component } from ‘react‘;

export default class NameList extends Component{

    render(){
        const {names} = this.props;
        return (
            <div>
                <table border="1" cellPadding="5" cellSpacing="0" bgcolor="F2F2F2" width="50%">
                    <tbody>
                    <tr id="infoTr">
                        <td>ID</td>
                        <td>姓名</td>
                    </tr>
                    </tbody>
                    {
                        names.map((item,key) => (
                            <tbody key={key}>
                            <tr id="infoTr">
                                <td>{item.name_id}</td>
                                <td>{item.name}</td>
                            </tr>
                            </tbody>
                        ))
                    }
                </table>
            </div>
        );
    }
}

NameForm.js

import React, { Component} from ‘react‘;

import PropTypes from "prop-types";

export default class NameForm extends Component{

    static propsTypes = {
        onAddName: PropTypes.func,
        onDeleteName: PropTypes.func,
        onUpdateName: PropTypes.func
    };

    render(){
        const divStyle = {marginTop:10};
        const spanStyle = {padding:10,margin:10};
        const {onAddName,onDeleteName,onUpdateName} = this.props;
        return (
            <div style={divStyle}>
                <span style={spanStyle}><button onClick={() => onAddName()}>添加</button></span>
                <span style={spanStyle}><button onClick={() => onDeleteName()}>删除</button></span>
                <span style={spanStyle}><button onClick={() => onUpdateName()}>更新</button></span>
            </div>
        );
    }
}

NameProvider.js

import NameList from ‘./NameList‘
import NameForm from "./NameForm";
import React, { Component } from ‘react‘;
import {addName,deleteName,updateName} from "../action_builder";
import {connect} from "react-redux";

// connect函数: function connect(mapStateToProps, mapDispatchToProps, mergeProps, _ref2){...}
// connect函数是一个高阶函数,它的返回值是一个表现层组件,该组件被一个容器组件包装,可以通过属性发送数据。
// connect函数接收函数作为参数,第1个参数是传递State的函数,第2个参数是dispatch函数, 第三个是合并属性的函数。根据需要,传入参数。
// connect函数与Provider一起协同工作。Provider将Store添加到上下文对象中,connect函数创建组件访问Store,开发者无需过多关心上下文对象。

//姓名列表容器组件
export const NameListProvider = connect(
    state =>
        ({
            names:[...state.names]
        }),
    null
)(NameList);

//姓名操作容器列表
export const NameFormProvider = connect(
    null,
    dispatch => ({
        onAddName(){
            dispatch(addName("4","XXX"));
        },
        onDeleteName(){
            dispatch(deleteName("1"));
        },
        onUpdateName(){
            dispatch(updateName("2","YYY"));
        }
    }),
)(NameForm);

演示结果

四、总结

在本文中,介绍了将Redux连接到React的多种方法。既有显式地将Store当做属性沿着组件树向下传递给了子组件,也有通过上下文对象将Store直接传递给了需要访问它的组件。既有通过容器组件将Store的功能从表现层组件中剥离出来,也有通过react-redux库的上下文对象和容器组件Provider帮助开发者快速地将Store和表现层连接起来。不论哪一种方式,都为Web应用程序的开发提供了极大的方便,也为架构的优化提供了优秀的方案。

原文地址:https://www.cnblogs.com/XYQ-208910/p/12083729.html

时间: 2024-08-08 22:31:22

React: 研究React Redux的使用的相关文章

React,关于redux的一点小见解

最近项目做多页面应用使用到了,react + webpack + redux + antd去构建多页面的应用,本地开发用express去模拟服务端程序(个人觉得可以换成dva).所以在这里吐槽一下我自己对于redux的一些见解. Redux是状态管理的服务,可以当作是mvc中的controller层,你也可以把它认为是mvvm中vm层.虽然它本身受到Flux的影响很大,但是它的核心概念缺很简单,就是Redue也就是ES5中Array.prototype.reduce,这个reduce用于合并数组

react系列(五)在React中使用Redux

上一篇展示了Redux的基本使用,可以看到Redux非常简单易用,不限于React,也可以在Angular.Vue等框架中使用,只要需要Redux的设计思想的地方,就可以使用它. 这篇主要讲解在React中使用Redux,首先是安装. 安装React Redux yarn add redux yarn add react-redux 有两个概念: 1.容器组件(Container Components) 2.展示组件(Presentational Components) 展示组件 更关注数据展示

重谈react优势——react技术栈回顾

react刚刚推出的时候,讲react优势搜索结果是几十页. 现在,react已经慢慢退火,该用用react技术栈的已经使用上,填过多少坑,加过多少班,血泪控诉也不下千文. 今天,再谈一遍react优势,WTF? React的收益有哪些?React的优势是什么?react和vue.angularJS等其它框架对比优势? 而作为总结回顾.react在工程实践中,带来哪些思想上的质变? virtual dom虚拟DOM概念 它并不直接对DOM进行操作,引入了一个叫做virtual dom的概念,安插

[React] Remove React PropTypes by using Flow Annotations (in CRA)

Starting from v15.5 if we wanted to use React's PropTypes we had to change our code to use a separate node module, now we can go one step further and get rid of that extra dependency just by using flow type annotations in our create-react-app project

React的React Native

React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了React Native,前端的边界似乎广阔无边.而Webpack凭借它异步加载和可分离打包等优秀的特性,走在取代Grunt和Gulp的路上.而面向未来的ES6,模块化的支持似乎已成定局. 我们现在就可以打造自己的Webpack+React+ES6环境并且开始探索起来. 这篇文章就给还没走在这条路上的前端一

[深入剖析React Native]React 初探

认识React React是一个用于构建用户界面的JavaScript库. React主要用于构建UI,很多人认为React是MVC中的V,即视图. React起源于Facebook的内部项目,用来架设Instagram的网站,并于2013年5月开源. React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和实用它. React特点 声明式设计 - React**采用声明范式**,可以轻松描述应用. 高效 - React通过对DOM的模拟,最大限度地减少与DOM的交互. 灵活 - R

小谈React、React Native、React Web

React有三个东西,React JS 前端Web框架,React Native 移动终端Hybrid框架,React Web是一个源码转换工具(React Native 转 Web,并之所以特别提出,是觉得还有些用处). React.React Native共同特点 起源 Facebook 的内部项目 理念 Learn once, write anywhere,而不是Write once, run anywhere.简单说就是,让你在Web.Mobile原生的开发套路一样,但你还是需要写两套代

从 React到React Native

React简介 RN基于React设计,了解React有利于我们开发RN应用.React希望功能分解化,让开发像搭积木一样,快速而且可维护. React的3个特点 作为UI(Just the UI) 虚拟DOM(Virtual DOM)这是亮点,是React最重要的一个特性更新View很快,放进内存,最小更新的视图差异部分更新 diff算法 数据(Data Flow)单向数据流 学习React要掌握的只是: JSX语法 类似XML ES6相关 前端基础 CSS+DIV JS 举例说明React的

React学习笔记-1-什么是react,react环境搭建以及第一个react实例

什么是react?react的官方网站:https://facebook.github.io/react/下图这个就是就是react的标志,非常巧合的是他和我们的github的编辑器Atom非常相似.react是Facebook官方推出的一个javascript的库,现在已经有了非常多的库和框架Facebook为什么还要开发一款新的框架呢?原因就是 Facebook遇到了一些新的问题.Facebook需要解决的问题是构建数据不断变化的大型应用.大型应用是什么意思?数据不断变化带来什么问题呢?