目前正在学习深入浅出React【真正吃透React知识链路与底层逻辑】共23讲_哔哩哔哩_bilibili
目录
问题集
知识点
父-子通信
子-父通信
兄弟通信
全局通信
订阅-发布模式
React.Context
Redux
问题集
- redux的真正用法
- 父组件re-render的时候,子组件会一起渲染吗,即使props没有发生变化
- 订阅发布模式导致的多个state一起更新,会合成还是分开执行
- 同样一个context生成的多个provider,他们会共享数据吗
- context的rerender逻辑是什么样的,如果一个context的state发生了变化,整个被context包住的组件都会rerender吗?有什么方法可以规避rerender如果子组件没有变化?这个规避方法对于consumer也管用吗?
- 如何在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);
// 之后可以做任何事
}
Redux
不理解,超出了react的范围,未来有空在研究
|