React Redux

来源:互联网 发布:尼泊尔弯刀数据图纸 编辑:程序博客网 时间:2024/05/18 00:17

React

React有两个重点props和state。

props

可以获取组件的属性,例如

class App extends Component{    render(){        return (            <h1>hello {this.props.name}</h1>        )    }   }ReactDom.render(    <App name="小明"/>,    mountDom);

这样标签的name属性可以通过props传入到App这个class中进行相关操作。他可以用来做数据的显示,例如想要封装一个Table组件则可以规定一个dataSource属性来传入数据源,内部通过解析这个数组进行遍历展示,封装好后的写法类似于这样就可以完成展示:

let ds=[    {name:'张三',age:22},    {name:'李四',age:25}]<Table dataSource={ds}/>

由此我们可以看出props用来传递一些展示的数据是非常好用的。

state

state是react的一个核心,我们知道组件都是调用render函数渲染的,在初次加载页面的时候会渲染一次。之后如果想要重新渲染,则需要组件的state发生改变的时候才会再次渲染。

class App extends Component{    getInitialState(){        return {num:0};    }    render(){        return (            <h1>{this.state.num}</h1>            <button onClick={e=>this.handleClick(e)}>add</button>        )    }       handleClick(e){        this.setState({num:this.state.num+1})    }}

上面例子是点击按钮使state产生了变化,而state变化后会重新调用render函数进行渲染,进而显示的数产生了变化。

我们发现如果是需要变化的数据展示页面,需要用state来存这些数据,数据的变化才会导致重新渲染,结合之前的props所以最后一般的解决方案是这样:单纯的展示组件就用props存储数据,而需要产生动态变化的时候就在这个组件外面套一个组件。

class Show extends Component{    render(){        return <h1>{this.props.num}</h1>;    }}class App extends Component{    getInitialState(){        return {num:0};    }    render(){        return (            <Show num={this.state.num}>            <button onClick={e=>this.handleClick(e)}>add</button>        )    }       handleClick(e){        this.setState({num:this.state.num+1})    }}

Redux

react中的state在任何一个内部的函数中都可以通过调用this.setState()方法进行改动,也就意味着这些地方都能进行重新渲染。这使得渲染产生的时机不好把握。另外每个组件都有一个state嵌套增多的时候,会搞得自己晕头转向。当这个组件功能变多的时候问题变得更严重。
Redux就提出了一种想法:把整个应用的所有state都存到一个地方,通过在特定入口触发事件才能引起state的改变。

action

这个事件叫做action他就是一个json对象规定了必须有个字段叫type,例如一个增加用户的事件可能是这样:

{    type:"USER_ADD",    user:{name:"张三",age:33}}

reducer

处理事件的第一步就是更新state,这一步处理叫做reduce,reducer就是一个函数规定了必须有俩参数一个是当前的state,一个是action;并且规定了返回值是因为这个action导致的变化后的state,例如增加用户对应的reducer大致如下:

function myReducer(state={users:[]},action){    if(action.type == "USER_ADD")        let newstate =Object.assign({}, state);        newstate.users.push(action.user);        return newstate;    return state;}

注意这里参数中state={users:[]}的意思是如果没有传state参数只传了action这一个参数,state默认值是{users:[]}。这是规定state初始值的一种写法。
Object.assign这里本来可以直接写成state.users.push(action.user)但是是改变了原来的state,可能在同时操作的时候出现问题,这里的写法是复制了一份state,不影响原state。

store

我们上面说了事件action以及处理action更新state用的reducer,不过state到底存在哪里呢?我们每次触发事件都要人为调用reducer函数么?答案是不用,store帮我们来做这些事情。
通过reducer来创建store,创建后就能直接获取state通过getState方法,之前的[]被设为初始值了,会被返回。
触发事件则通过dispatch(action)函数,事件触发后会 自动调用reducer更新state,然后触发回调函数。回调函数通过subscribe(callback)函数进行设置,改函数的返回值是注销这个回调函数的函数。

import { createStore } from 'redux'let store = createStore(myReducer);console.log(store.getState()); //[]let unsubscribe = store.subscribe(() =>  console.log(store.getState()))let addAction={    type:"USER_ADD",    user:{name:"张三",age:33}}store.dispatch(addAction); //事件触发后state更新然后触发回调函数,打印了state的值unsubscribe();

通过上面这个例子,我们大体明白了redux的工作流程,通过这样的写法,我们能够将state汇总起来,所有的事件触发例如点击按钮,都通过store.dispatch(action)进行触发。不用再在每个组件中写处理函数,只需要在一个文件中集中写好 多个reducer。

React-Redux

Redux是一种集中处理集中存储state的思想,他并不是react的扩展,他也可以用在angularjs vue等。如果要在React中使用还需要安装react-redux,上面的例子中是手动调用store.dispatch触发事件的,react中则可能是在某个onClick函数中触发事件。上述的监听state的变化是用了store.subscribe进行订阅的state的变化,而react中需要将store中的state绑定到组件的state上,这些工作都交给react-redux帮我们来做:

import { Provider,connect } from 'react-redux'import { createStore } from 'redux'import { render } from 'react-dom'//声明storelet store = createStore(myReducer);//展示Users的组件class App extends Component{    render(){        //在调用connect之后,会自动绑定一个dispatch和自定义绑定过来的users        const { dispatch,users } = this.props        let content =users.map(it=>{return <tr>{it.name}</tr><tr>it.age</tr>})        return (            <table>                <tr><th>name</th><th>age</th></tr>                {content}            </table>            <button onClick={e=>dispatch(addAction)}>add</button>        )    }   }//将state的users绑定到props中function select(state) {  return {    users: state.users  };}//调用connect函数完成dispatch和users的绑定,绑定后的组件名为Conlet Con = connect(select)(App)//通过Provider将store注入进来,此时所有react组件的state都存放在这里render(    <Provider store={store}>        <Con />    </Provider>,    document.getElementById("main"))

整个流程是首先完成了store.state和react中state的联系;
渲染Con组件,因为初始状态的users是[],所以表格有0行数据;
点击add按钮,触发了添加用户的action;
reducer中处理,在users属性中追加了这个user;
store.state状态发生了变化,自动绑定到react,认为需要重新渲染了,然后重新渲染了Don;
Don中的users属性更新,并显示在表格中,多了一行。

原创粉丝点击