zoukankan      html  css  js  c++  java
  • 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. createRef API生成的Refs(React V16.3+)

    将ref自动的通过组件传递到子组件。然后通过ref获取子组件的DOM。

    1. Refs应用场景

    1. 对于那些高可复用的,诸如<Button><SelectInput>等“叶”组件,经常会需要获取

    DOM节点,实现管理焦点、文本选择、播放动画等。

    2. 对于触发强制动画。

    3.对于集成第三方DOM库。

    注意: 高级组件不能通过属性转发ref

    2. 访问ref的current属性

    1. 对于HTML元素,current属性指向底层的DOM元素。

    2.对于class组件元素,current属性指向组件的实例对象(即this)。

     这样可以在父组件中,通过this.ref.current调用子组件的实例方法

    class App extends React.Component {
       constructor(props) {
          super(props);
          this.ref = React.createRef();
       }
       componnetDidMount() {
          // this.ref.current指向子组件的实例对象this
          this.ref.current.resetData()
       }
       render() {
          // 只能是类子组件
          return <Child ref={this.ref}>
       }
    }
    
    class Child extends React.Component {
       resetData = () => {
          // TODO
       }
       render() {
          return <div></div>
       }
    }

    3. 不能在函数组件上使用ref,因为它没有实例。

    function FunComponent(props) {
      return <div></div>
    }
    // 错误!函数组件上不能使用ref属性
    <FunComponent ref={this.myref}/>

    但是可以在函数组件内部使用,只要它指向DOM或者类组件。

    function CustomTextInput(props) {
      // 这里必须声明 textInput,这样 ref 才可以引用它
      let textInput = React.createRef();
      function handleClick() {
        textInput.current.focus();
      }
      return (
        <div>
          <input
            type="text"
            ref={textInput} />
          <input
            type="button"
            value="Focus the text input"
            onClick={handleClick}
          />
        </div>
      );
    }

    3. Refs转发方法

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

     4. 回调函数Refs

    ref还可以接收一个回调函数,作为ref的属性内容。

    <div ref={(element) => this.ref = element}></div>

    使用回调函数也ref可以获取子组件的DOM节点。

    function FunComponent(props) {
      return <div ref={props.funRef}>函数组件</div>
    }
    class App extends React.Component {
      componentDidMount() {
        // 获取到函数子组件的DOM节点
        console.log(this.ref); //<div>函数组件</div>
      }
      render() {
        return(
          <FunComponent funRef={(element) => {this.ref = element}} />
        )
      }
    }
  • 相关阅读:
    Windows Vista 桌面窗口管理器(1)
    Thinking in Java读书笔记――数组
    php图片上传存储源码,可实现预览
    php at(@)符号的用法简介
    Apache如何添加虚拟目录
    也发个PHP人民币金额数字转中文大写
    PHP Get Current URL
    Zend Studio下的PHP代码调试
    PHP url 加密解密函数
    使用新浪微博php SDK的一点记录
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11946996.html
Copyright © 2011-2022 走看看