React应用数据传递的方式

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>
    )
  }
}

猜你喜欢

转载自www.cnblogs.com/lyraLee/p/11946996.html
今日推荐