真正吃透React知识链路与底层逻辑, Part3

目前正在学习深入浅出React【真正吃透React知识链路与底层逻辑】共23讲_哔哩哔哩_bilibili

目录

问题集

知识点

父-子通信

子-父通信

兄弟通信

全局通信

订阅-发布模式

React.Context

Redux


问题集

  1. redux的真正用法
  2. 父组件re-render的时候,子组件会一起渲染吗,即使props没有发生变化
  3. 订阅发布模式导致的多个state一起更新,会合成还是分开执行
  4. 同样一个context生成的多个provider,他们会共享数据吗
  5. context的rerender逻辑是什么样的,如果一个context的state发生了变化,整个被context包住的组件都会rerender吗?有什么方法可以规避rerender如果子组件没有变化?这个规避方法对于consumer也管用吗?
  6. 如何在class component里面使用context

知识点

父-子通信

  • 一般用例:父组件控制state的更新,子组件负责根据父组件的state更新视图
  • 数据通过props,将父组件的state/props传入子组件

子-父通信

  • 一般用例:子组件负责state更新,父组件需要用到更新的state
  • 父组件定义一个改变state的method,讲这个method作为props传入子组件,子组件的会调用这个method,来改变父组件的状态

兄弟通信

  • 一般用例:同一父组件的直系兄弟之间,一个兄弟负责state的更新,另外一个组件负责更新视图
  • 可以转换为:子-父通信 + 父-子通信
  • 父组件定义一个改变state的method,将这个method传递给负责改变状态的子组件。将state,传入控制视图的子组件

全局通信

  • 问题:数据需要隔很多层级之间共享,但是通过props,setState的传递,很多中间层的component会变成单纯的数据传递者,他们的I/O会被污染

订阅-发布模式

// 事件容器
const globalEventHandler = { // 定义为全局变量
    events: {},
    on: (eventKey, subscriberName, handler)=>{events[eventKey][subscriberName] = handler}
    emit: (eventKey, params)=>{events[evnetKey].forEach((handler)=>handler(params))}
    off: (eventKey, subscriberName)=>{events[eventKey].pop(subscriberName)}
}

// 订阅组件
class subscriber1 extends Component {
    state = {a:1}

    updateAFromB(b){
        this.setState({a: b * 5 - 1})
    }
    
    componentDidMount(){
        globalEventHandler.on('changeB', 'subscriber1',(newB)=>updateAFromB(newB))
    }
    
    componentWillUmmount(){
        globalEventHandler.off('changeB', 'subscriber1')
    }
}

// 发布组件
class emitter1 extends Compoennt {
    render(){
        return <input onBlur={(event)=>globalEventHandler.emit('changeB', event.target.value)}/>
    }
}
  • 一般用例:当一个事件需要同时引发很多组件state的更新
  • 所有需要更新的组件都会添加一个改变state的函数到全局事件管理器里面。在会触发改变的组建中我们会根据事件的名字(key)触发所有的相关事件,同时提供一些数据,这些数据在执行所有handler的时候,就从这个发布组件传播到全部的订阅组件中去了

React.Context

// 创建一个Context,可以提供初始值
const ExampleContext = createContext(initialValue);

// 创建一个Context的Provider,在里面定义需要被全局共享的数据
const ExampleContextProvider = (props)=>{
    const {children, ...rest} = props;
    // 定义需要共享的数据,有时候我们会使用从外传进来的props来做初始化的定义,或者生成derivedState
    const [a, setA] = useState(1);
    // ...
    // 把需要共享的数据放入一个object
    contextObj = {
        a,
        setA
    }
    return <ExampleContext.Provider value={contextObj}>{children}</ExampleContext.Provider>

}

// 使用ContextProvider将子组件包起来,Children里面的所有component,都能直接使用Context里面的数据并且更新视图
const ExampleContainer = (props)=>{
    const {providerProps, childrenProps}
    return <ExampleContextProvider {...providerProps}>
               <Children {...childrenProps}/>
           </ExampleContextProvider>
    
}

// 在子组件里面使用context的数据, consume这个context
const ExampleConsumer = (props)=>{
    const {a, setA} = useContext(ExampleContext);
    // 之后可以做任何事
}
  • 一般用例:大量的组件都需要共享数据,并且希望数据的更新会直接影响到视图效果

  • 创建一个context,之后定义contextProvider来提供数据,所有的子组件都可以直接通过useContext直接获取contextProvider的value

Redux

不理解,超出了react的范围,未来有空在研究

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值