React-Native基础(4):组件引用Ref

在典型的React数据流中,父组件与子组件的唯一交互方式就是通过Props。修改子组件,就需要使用新的Prop来重新渲染。但是在有些情况,需要在数据流之外,直接来执行子组件的修改操作。React提供了使用Ref方式来解决直接修改子组件或子DOM元素的问题。

1. 添加Ref到DOM元素

ref是React组件一个特殊属性,使用回调函数作为属性,函数的接收组件的基本DOM元素作为它的参数。

<Component ref={(el) => this.el = el }/>

定义的回调函数会在组件加载和卸载时立即调用。 在组件卸载时函数中元素的值为null。 一个简单的例子

...
class CustomTextInput extends React.Component{
   constructor(props){
       super(props);
       this.focus = this.focus.bind(this);
   }
   
   focus(){
       // 获取文字焦点
       this.textInput.focus();
   }
   
   render(){
       // 使用ref回调函数存储text input 元素的引用
       return (
        <div>
          <input 
            type="text" 
            ref={(input) => { this.textInput = input; }} />
          <input
            type="button"
            value="Focus the text input"
            onClick={this.focus} />
        </div>
       );
   }
}

// es6 箭头函数
ref={input => this.textInput = input}

2. 添加Ref到Class组件

当为组件添加Ref回调函数,回调函数将使用自定义的组件作为它的参数。 例如:

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

这个方式只能用于以class方式声明的CustomTextInput

class CustomTextInput extends React.Component {
    // ...
}

4. Ref和函数组件

因为函数式组件没有组件实例,所以不能够通过上面的方式来给函数组件添加ref。

通过两种方式来解决

1. 将函数组件转为Class组件。
2. 在函数组件内部使用`ref`,这种方式同样适应于class组件。
function CustomTextInput(props){
    // 需要声明引用的textInput
    let textInput = null;
    function handleClick(){
        textInput.focus();
    }
    
    return (
      <div>
        <input 
          text="text"
          ref={ (input) => { textInput = input; }}
          />
        <input 
          text="button"
          value="Focus the text input"
          onClick={ handleClick }
          />
      </div>
    );
}

4. 暴露DOM的Ref给父组件

在极少情况下,父组件需要访问子组件。因为破坏了组件的封装性,这种做法并不推荐,但是有时对于触发焦点和测量子DOM节点的位置或大小会有用。如果给子组件添加ref时,也并不是理想解决方案,因为ref回调函数的参数是子组件,而不是DOM节点元素,并且不适用函数式组件。 因此,在这些情况建议暴露子组件的特殊属性,子组件使用任意名称(如:inputRef)的函数类型的Prop,并把这个属性添加大DOM节点元素中,作为ref属性。就可以通过中间组件将父组件的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}
          />
      );
    )
}

上面代码中父组件使用inputRef属性将ref回调函数传递给中间组件CustomTextInputCustomTextInput又将函数传给<input />的ref属性。最终父组件获取到对<input />的引用。这种形式不仅适用于Class组件,同样也适用于函数组件。 这种形式的另一个好处就是:对于深层的DOM节点同样有效。假设父组件不需要DOM节点引用,但是祖父组件想要获取子组件中DOM节点元素的引用,可以通过让祖父组件指定inputRef属性,传递给父组件,父组件再把inputRef转给CustomTextInput

function CustomTextInput(props){
  return (
    <div>
      <input ref={props.inputRef}/>
    </div>
  );
}

class Parent extends React.Component{
    render (
      return (
        <div>
          My input: <CustomTextInput inputRef={props.inputRef} />
        </div>
      );
    )
}


class GrandParent extends React.Component{
  render() {
    return (
      <Parent
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

综合考虑下,不建议暴露DOM节点。 因为破坏了组件的封装,而且需要子节点添加额外的属性。

5. 说明

如果ref以内联函数形式定义,在更新时会被调用两次 - 第一次为函数的参数为null,第二次为DOM元素 因为每次render时,都要创建一个新的函数实例,建议通过组件bind函数来定义ref回调函数。

6. 适应场景

1. 管理输入焦点,文字选择或者媒体播放时;
2. 触发必要的动画时;
3. 与第三方DOM库交互时;

避免使用在可用声明方式的情景下。如:通过定义isOpen的方式,避免暴露Dialogopenclose的方法。

7. 避免过度使用

在使用ref时,一定要经过慎重思考,尤其是拥有State状态的组件。首先考虑使用Props

Refs and the DOM 公众号

转载于:https://my.oschina.net/alexwan/blog/906772

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是react-native-common-date-picker的介绍: react-native-common-date-picker是一个React Native的日期选择器组件,支持年月日格式的日期选择。该组件适用于iOS和Android平台,并且可以自定义样式和参数。 使用react-native-common-date-picker,你可以轻松地在你的React Native应用程序中添加日期选择器功能。该组件提供了多种可选参数,例如日期格式、最小日期、最大日期、默认日期等等,以便你根据自己的需求进行自定义。 以下是一个使用react-native-common-date-picker的例子: ```javascript import React, { useState } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import DatePicker from 'react-native-common-date-picker'; const App = () => { const [date, setDate] = useState(new Date()); const handleDateChange = (newDate) => { setDate(newDate); }; return ( <View> <TouchableOpacity onPress={() => this.datePicker.onPressDate()}> <Text>{date.toLocaleDateString()}</Text> </TouchableOpacity> <DatePicker ref={(picker) => { this.datePicker = picker; }} style={{ width: 0, height: 0 }} mode="date" date={date} onDateChange={handleDateChange} /> </View> ); }; export default App; ``` 在上面的例子中,我们首先导入了react-native-common-date-picker组件,并在组件中使用useState钩子来管理日期状态。然后,我们在TouchableOpacity组件中渲染了当前日期,并在用户点击该组件时打开了日期选择器。最后,我们将DatePicker组件添加到了视图中,并将其隐藏在了一个看不见的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值