• 详解react中的state,props,refs


    state

     state顾名思义就是状态,它只是用来控制这个组件本身自己的状态,我们可以用state来完成对行为的控制、数据的更新、界面的渲染,由于组件不能修改传入的props,所以需要记录自身的数据变化。

     那么,我们要如何修改state中的值呢?

    setState  时react用来修改state状态中的值的方法

    如何使用

    this.setState({

      key:value

    })  

    这样就行了。

    props

     react中说的单向数据流值说的就是props,根据这一特点它还有一个作用:组件之间的通信。props本身是不可变的,但是有一种情形它貌似可变,即是将父组件的state作为子组件的props,当父组件的state改变,子组件的props也跟着改变,其实它仍旧遵循了这一定律:props是不可更改的。

    props一定来源于默认属性或者通过父组件传递而来,以下是这个写法:

    1  static propProps = {
    2          val:PropTypes.string.isRequired
    3  }
    4  static defaultProps = {
    5          val:0
    6 }

    如果你觉得还是搞不清 state 和 props 的使用场景,那么请记住一个简单的规则:尽量少地用 state,尽量多地用 props。

    没有 state 的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。函数式组件就只有props没有state,而react也非常鼓励我们编写函数式组件。

    以下给props和state做一个总结:

    • props用于定义外部接口,state用于记录内部状态

    • props的赋值在于外部世界使用组件,state的赋值在于组件内部

    • 组件不应该改变props的值,而state存在的目的就是让组件来修改的

    组件的state相当于组件的记忆,其存在的意义就是被修改,每一次通过setState函数修改state就改变了组件的状态,然后通过把渲染过程体现出来。但是组件的props绝不应该被修改,我们可以想象一个场景,一个父组件将同一个props传给几个子组件,若有一个子组件将props修改,那么其他的组件就不一定能得到自己想到的值,此时的情况将混乱不堪。

    refs

    某些情况下需要直接修改元素,要修改的子代可以是 React 组件实例,也可以是 DOM 元素。这时就要用到refs来操作DOM。
    [注意] 如果可以通过声明式实现,则尽量避免使用 refs。

    ref

      React 支持给任意组件添加特殊属性ref ,ref可以是一个字符串,也可以是一个属性接受一个回调函数,它在组件被加载或卸载时会立即执行。
    [注意]在组件mount之后再去获取refcomponentWillMount和第一次render时都获取不到,在componentDidMount才能获取到。

    新ref

      版本16.3 之前,React 有两种提供 ref的方式:字符串和回调,因为字符串的方式有些问题,所以官方建议使用回调来使用 ref。而现在引入的createRef API,据官方说是一种零缺点的使用ref的方式,回调方式也可以让让路了。

    1 class MyComponent extends React.Component {
    2   constructor(props) {
    3     super(props);
    4     this.myRef = React.createRef();
    5   }
    6   render() {
    7     return <div ref={this.myRef} />;
    8   }
    9 }

    然后使用current属性,即可获得当前元素

     this.myRef.current

    [注意]使用styledComponents样式化的元素暴露的接口是innerRef,而不是ref

    <Wrap innerRef={this.itemRef}>

    ref传递原理

      当给 HTML 元素添加ref 属性时,ref 回调接收了底层的 DOM 元素作为参数。
      React 组件在加载时将 DOM 元素传入 ref 的回调函数,在卸载时则会传入 null。ref 回调会在componentDidMount或 componentDidUpdate这些生命周期回调之前执行。

    class CustomTextInput extends React.Component {
      constructor(props) {
        super(props);
        this.focus = this.focus.bind(this);
      }
      focus() {
        this.textInput.focus();
      }
      render() {
        return (
          <div>
            <input
              type="text"
              ref={(input) => { this.textInput = input; }} />
            <input
              type="button"
              value="Focus the text input"
              onClick={this.focus}
            />
          </div>
        );
      }
    }
    

      更简短的写法如下:

    ref={input => this.textInput = input}

    类组件

      当·ref属性用于使用 class声明的自定义组件时,ref的回调接收的是已经加载的 React 实例。

    class AutoFocusTextInput extends React.Component {
      componentDidMount() {
        this.textInput.focusTextInput();
      }
    
      render() {
        return (
          <CustomTextInput
            ref={(input) => { this.textInput = input; }} />
        );
      }
    }

    [注意]这种方法仅对 class 声明的 CustomTextInput有效

    函数式组件

    不能在函数式组件上使用 ref 属性,因为它们没有实例。

    对父组件暴露DOM节点

      在子节点上暴露一个特殊的属性。子节点将会获得一个函数属性,并将其作为 ref 属性附加到 DOM 节点。这允许父代通过中间件将 ref 回调给子代的 DOM 节点。
    该方法适用于类组件和函数式组件:

    function CustomTextInput(props) {
      return (
        <div>
          <input ref={props.inputRef} />
        </div>
      );
    }
    
    class Parent extends React.Component {
      render() {
        return (
          <CustomTextInput
            inputRef={el => this.inputElement = el}
          />
        );
      }
    }

    在上面的例子中,Parent 将它的 ref 回调作为一个特殊的 inputRef 传递给CustomTextInput,然后 CustomTextInput 通过ref 属性将其传递给 <input>。最终,Parent 中的 this.inputElement将被设置为与 CustomTextInput中的<input>元素相对应的 DOM 节点。

    参考链接 :https://www.jianshu.com/p/2f6d81a15d81

          https://www.jianshu.com/p/628d5514b145

  • 相关阅读:
    以您熟悉的编程语言为例完成一个hello/hi的简单的网络聊天程序——网络程序设计课第二次作业
    逆波兰表达式改写(C++)
    侯捷老师的C++代码:基于对象的类别之二带指针的成员函数 Mystring实现
    侯捷老师的C++代码: 基于对象之一 无指针类型 复数类实现
    雇员记录系统(C++)
    设计模式-Interpreter(行为模式) 使用解释器给用户提供一个一门定义语言的语法表示的解释器,通过该解释器解释语言中的句子。
    设计模式-Iterator(行为模式) 将聚合的遍历封装到一个类中
    设计模式-Chain of Responsibility (行为模式) 降低系统的耦合性
    设计模式-Visitor(行为模式) 一个类在不修改自己的同时增加了新的操作,存在问题是 1:破坏了封装性 2:扩展困难
    设计模式-Command(行为模式) 将一个请求封装到一个Command类中,提供一个处理对象Receiver,将Command由Invoker激活。
  • 原文地址:https://www.cnblogs.com/bokeyanghao/p/11469737.html
Copyright © 2020-2023  润新知