1. props属性
典型的React应用,数据通过props按照自上而下(父->子)的顺序传递数据。
2. Context传值
1. 应用场景
对于一些应用中全局性的属性(如UI主题、语言、登陆用户等),通过props传递会很繁琐。
Context的出现可以在组件之间(父->子)共享这些属性。
2. 使用方法
1. 创建Context对象(写入一个单独的文件)
const ThemeContext = React.createContext(defaultValue)
const ThemeContext = React.createContext({ theme: themes.dark, changeTheme: () => {} });
2. 使用Provider提供数据,数据可以是原始类型,也可以是对象;
可以是常量也可以是变量;
注意: 如果是对象,通过state值传入,否则每次渲染都是新的对象。
<ThemeContext.Provider value={this.state}> <Toolbar /> </ThemeContext.Provider>
3. 使用Consumer获取数据
<ThemeContext.Consumer> {({theme, changeTheme}) => <div style={{background: theme.backgroundColor}}> <button onClick={changeTheme}>切换主题</button> </div>} </ThemeContext.Consumer>
4. 也可以通过赋值静态属性contextType后,通过this.context获取值
static contextType = ThemeContext; render() { return ( <div style={{background: this.context.theme.backgroundColor}}> <button onClick={this.context.changeTheme}>切换主题</button> </div>
3. Refs转发
将ref自动的通过组件传递到子组件。然后通过ref获取子组件的DOM。
1. 应用场景
对于那些高可复用的,诸如<Button><SelectInput>等“叶”组件,经常会需要获取
DOM节点,实现管理焦点、选中、实现动画等。
注意: 高级组件不能通过属性转发ref
2. 使用方法
1. 普通转发
class App extends React.Component{ constructor(props) { super(props); this.ref = React.createRef(); //初始化一个变量 } componentDidMount() { console.log(this.ref.current); // <div id="toolbar">Toolbar</div> } render() { return ( <div> <Toolbar ref={this.ref} /> <div>App</div> </div> ) } } // 传递到子组件后给其赋值 const Toolbar = React.forwardRef((props, ref) => ( <div ref={ref} id="toolbar"> Toolbar </div> ));
2. 高阶组件转发refs
当使用{...this.props}进行透传时,因为ref不是属性,所以不能通过其透传。
但是可以在高阶组件内部,通过React.forwardRef()进行转发。
// 高阶组件代码 function logProps(WrappedComponent) { class LogProps extends React.Component { componentDidUpdate(prevProps, prevState, snapshot) { console.log('prevProps-->',prevProps) console.log('this.props-->',this.props) } render() { const {forwardRef, ...rest} = this.props; // ref指向被包裹的组件 return <WrappedComponent {...rest} ref={forwardRef} /> } } return React.forwardRef((props, ref) => { return <LogProps {...props} forwardRef={ref} /> }); } export default logProps; // 被包裹组件代码 import React from 'react'; import logProps from './logProps'; class Toolbar extends React.Component { render() { return ( <div>Toolbar</div> ) } } export default logProps(Toolbar) // 父组件代码 import Toolbar from './toolbar'; class App extends React.Component{ constructor(props) { super(props); this.ref = React.createRef(); this.state = {num: 1} } componentDidMount() { console.log(this.ref.current); //Toolbar } add = () => { this.setState(state => ({ num: state.num + 1 })) } render() { return ( <div> <Toolbar ref={this.ref} /> <div onClick={this.add}>{this.state.num}</div> </div> ) } }