React Redux

React

React有两个重点props和state。

props

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

class App extends Component{
    render(){
        return (
            

hello {this.props.name}

) } } ReactDom.render( "小明"/>, mountDom );

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

let ds=[
    {name:'张三',age:22},
    {name:'李四',age:25}
]

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

state

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

class App extends Component{
    getInitialState(){
        return {num:0};
    }
    render(){
        return (
            

{this.state.num}

) } handleClick(e){ this.setState({num:this.state.num+1}) } }

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

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

class Show extends Component{
    render(){
        return 

{this.props.num}

; } } class App extends Component{ getInitialState(){ return {num:0}; } render(){ return ( this.state.num}> ) } 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'

//声明store
let store = createStore(myReducer);

//展示Users的组件
class App extends Component{
    render(){
        //在调用connect之后,会自动绑定一个dispatch和自定义绑定过来的users
        const { dispatch,users } = this.props
        let content =users.map(it=>{return 
{it.name}it.age}) return (
{content}
nameage
) } } //将state的users绑定到props中 function select(state) { return { users: state.users }; } //调用connect函数完成dispatch和users的绑定,绑定后的组件名为Con let Con = connect(select)(App) //通过Provider将store注入进来,此时所有react组件的state都存放在这里 render( , document.getElementById("main") )

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

你可能感兴趣的:(前端)