React Native - 组件的引用详解(附:setNativeProps、measure方法介绍)
作者:hangge | 2017-09-12 08:10
通常情况下,我们对组件的使用逻辑是:当某个组件出现需要处理的事件时,由这个组件自己上报该事件,然后在对应的事件处理代码对事件进行处理。
但有些情况下,我们也需要直接对组件进行操作。这个时候,我们就需要先得到组件引用,进而通过该引用对组件进行操作。
一、组件引用
1,普通组件的引用
在某个组件的 JSX 代码描述中加入 ref={某字符串},就可以定义一个组件的引用名称。
<TextInput ref="textInput1" />
上面的代码我们将一个 TextInput 组件的引用名称设置为 textInput1。当我们需要时,可以通过如下方式得到这个组件的引用:
this.refs.textInput1
2,动态生成的组件的引用
有时组件的定义是由代码完成的,比如:通过一个数组定义多个组件,生成的组件的个数等于数组的长度。这种情况下我们无法再一一对组件赋予引用名称。
这时就需要在代码运行时取得系统定义的每个组件的引用,并将这些引用保存在一个数组中。
下面样例演示如何得到系统定义的组件引用:
- aArray 中已经存放好了数据,按照他的长度将生成多个 ComponentA 这个自定义组件。
- 每一个 ComponentA 组件的 aPropName 属性都被赋值为 aArray 中一个元素的值。
- 同时每一个 ComponentA 组件的引用都存放在名为 componentRefNames 的数组中以备后用。
{ this.aArray.map((aValue, aIndex) => <ComponentA aPropName={aValue} ref={ (refName) => { this.componentRefNames[aIndex] = refName; }} key={aOption} /> ) }
3,调用组件的公开方法
当我们需要调用组件的公开成员函数时,就需要使用组件的引用来调用。
this.refs.textInput1.公开成员函数名()
二、使用 setNativeProps 方法设置组件的属性
1,方法介绍
每一个 React Native 组件都有一个公开的成员函数 setNativeProps,使用它可以增加或者修改 React Native 组件的属性。
2,使用建议
- 通常情况下,React Native 开发不建议使用 setNativeProps 函数。它是一个简单粗暴的方法,可以直接操作任何层面组件的属性,而不是使用 React Native 组件的状态机变量。这样会时代码逻辑混乱,有可以能打乱原来设计编写好的业务逻辑。
- 所以在使用 setNativeProps 之前,尽量先尝试用 setState 和 shouldComponentUpdate 方法来解决问题。
- 只有在不得不频繁刷新页面而又遇到性能瓶颈时,比如:创建连续的动画,而且还要避免渲染组件结构和同步太多的视图变化所带来的大量开销时,才考虑使用 setNativeProps 函数。
3,使用样例
(1)效果图
- 当用户按下“改变属性”按钮后,会通过 setNativeProps 函数修改文本标签和输入框的属性,让它们产生视觉上的变化。
- 注意:实际开发中这种变化应该是要通过状态机变量来完成的,这里只是为了演示如何使用组件的引用,以及如何调用 setNativeProps 函数修改组件属性。
(2)样例代码
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, TextInput, View, Text } from 'react-native'; class Main extends Component { constructor(props){ super(props); this.state = { textInputValue: '' }; } //按钮被按下时执行 buttonPressed() { let textInputValue = 'hangge.com'; this.setState({textInputValue}); //修改文本标签的属性值 this.refs.text1.setNativeProps({ style: { color: 'blue', fontSize: 30 } }); //修改文本输入框的属性值 this.refs.textInput.setNativeProps({ editable:false //使文本输入框变为不可编辑 }); } render() { return ( <View style={[styles.container]}> <Text style={styles.textPromptStyle} ref={'text1'}> 欢迎访问 </Text> <TextInput style={styles.textInputStyle} ref={'textInput'} value={this.state.textInputValue} onChangeText={(textInputValue) => this.setState({textInputValue}) } /> <Text style={styles.buttonStyle} onPress={this.buttonPressed.bind(this)}> 改变属性 </Text> </View> ); } } const styles = StyleSheet.create({ container:{ flex:1, paddingTop:15, paddingLeft:15 }, textPromptStyle:{ fontSize:20, marginBottom:15 }, textInputStyle:{ width:150, height:50, fontSize:20, marginBottom:15 }, buttonStyle:{ fontSize:20, color:'white', width:100, textAlign:'center', backgroundColor:'#4CA300' }, }); AppRegistry.registerComponent('HelloWorld', () => Main);
三、使用 measure 方法获得组件的位置
1,方法介绍
- 每一个 React Native 组件都有一个 measure 成员函数,调用它可以得到组件当前的宽、高与位置信息。
- 虽然使用 View 组件的 onLayout 回调函数时获取组件的宽、高与位置信息的好办法。但对于某些代码生成的组件,使用组件的 measure 成员函数获取组件的宽、高及位置信息是唯一的方法。
2,使用样例
(1)效果图
点击“获取位置”按钮后,得到文本输入框组件的宽、高以及坐标位置信息,并打印到控制台上。
(2)样例代码
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, TextInput, View, Text } from 'react-native'; class Main extends Component { //按钮被按下时执行 buttonPressed() { this.refs.textInput.measure(this.getTextInputPosition); } //位置信息通过回调函数传递 getTextInputPosition(fx, fy, width, height, px, py) { console.log("width:" + width); console.log("height:" + height); console.log("X offset to frame:" + fx); //这个值无用 console.log("Y offset to frame:" + fy); //这个值无用 console.log("X offset to page:" + px); console.log("Y offset to page:" + py); } render() { return ( <View style={[styles.container]}> <TextInput style={styles.textInputStyle} ref={'textInput'} defaultValue='hangge.com' /> <Text style={styles.buttonStyle} onPress={this.buttonPressed.bind(this)}> 获取位置 </Text> </View> ); } } const styles = StyleSheet.create({ container:{ flex:1, paddingTop:15, paddingLeft:15 }, textInputStyle:{ width:150, height:50, fontSize:20, marginBottom:15 }, buttonStyle:{ fontSize:20, color:'white', width:100, textAlign:'center', backgroundColor:'#4CA300' }, }); AppRegistry.registerComponent('HelloWorld', () => Main);
全部评论(0)