Direct Manipulation
Direct Manipulation
有时需要直接对组件进行更改,而不使用state / props来触发整个子树的重新渲染。例如,在浏览器中使用React时,您有时需要直接修改DOM节点,移动应用中的视图也是如此。setNativeProps
React Native相当于直接在DOM节点上设置属性。
频繁重新渲染时会使用
setNativeProps
创建性能瓶颈直接操作不会是您频繁使用的工具; 您通常只会使用它来创建连续的动画,以避免渲染组件层次结构和协调许多视图的开销。setNativeProps
是必不可少的,并在本地层(DOM,UIView等)中存储状态,而不是在您的React组件中,这会让您的代码更难以推理。在使用它之前,请尝试使用setState
和shouldComponentUpdate来解决您的问题。
setNativeProps与TouchableOpacity
TouchableOpacity使用setNativeProps
内部更新其子组件的不透明度:
setOpacityTo(value) {
// Redacted: animation related code
this.refs[CHILD_REF].setNativeProps{
opacity: value
}
},
这允许我们编写下面的代码,并且知道孩子将会响应点击而更新其不透明度,而没有孩子知道该事实或者需要对其实施进行任何改变:
<TouchableOpacity onPress={this._handlePress}>
<View style={styles.button}>
<Text>Press me!</Text>
</View>
</TouchableOpacity>
让我们来想象那setNativeProps
是不可用的。我们可以使用该约束来实现它的一种方式是将不透明度值存储在状态中,然后在每次onPress
触发时更新该值:
constructor(props) {
super(props
this.state = { myButtonOpacity: 1, };
}
render() {
return (
<TouchableOpacity onPress={() => this.setState{myButtonOpacity: 0.5})}
onPressOut={() => this.setState{myButtonOpacity: 1})}>
<View style={[styles.button, {opacity: this.state.myButtonOpacity}]}>
<Text>Press me!</Text>
</View>
</TouchableOpacity>
)
}
与原始示例相比,这是计算密集型--React需要在每次不透明度更改时重新呈现组件层次结构,即使视图及其子项的其他属性未更改。通常这种开销不是问题,但是当执行连续动画和响应手势时,明智地优化组件可以提高动画的保真度。
如果你看的执行setNativeProps
在NativeMethodsMixin.js你会发现,它是围绕着包装RCTUIManager.updateView
-这是完全相同的函数调用,从重新渲染结果-看receiveComponent在ReactNativeBaseComponent.js。
复合组件和setNativeProps
复合组件不支持本地视图,因此您无法调用setNativeProps
它们。考虑这个例子:
import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
class MyButton extends React.Component {
render() {
return (
<View>
<Text>{this.props.label}</Text>
</View>
)
}
}
export default class App extends React.Component {
render() {
return (
<TouchableOpacity>
<MyButton label="Press me!" />
</TouchableOpacity>
)
}
}
如果你运行这个,你会立即看到这个错误:Touchable child must either be native or forward setNativeProps to a native component
。发生这种情况是因为MyButton
不直接由应设置不透明度的本地视图支持。你可以这样想:如果你定义一个组件createReactClass
并不期望能够在其上设置一个样式道具并且完成这个工作 - 你需要将样式道具传递给一个孩子,除非你正在包装本地组件。同样,我们将转发setNativeProps
到本机支持的子组件。
将setNativeProps转发给一个子类
我们所需要做的就是setNativeProps
在组件上提供一个方法setNativeProps
,用相应的参数调用适当的孩子。
import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
class MyButton extends React.Component {
setNativeProps = (nativeProps) => {
this._root.setNativeProps(nativeProps
}
render() {
return (
<View ref={component => this._root = component} {...this.props}>
<Text>{this.props.label}</Text>
</View>
)
}
}
export default class App extends React.Component {
render() {
return (
<TouchableOpacity>
<MyButton label="Press me!" />
</TouchableOpacity>
)
}
}
您现在可以使用MyButton
里面TouchableOpacity
!为了清楚起见,我们使用了ref回调语法,而不是传统的基于字符串的ref。
您可能已经注意到我们将所有道具传递给了子视图{...this.props}
。其原因在于,TouchableOpacity
它实际上是一个复合组件,除了取决于setNativeProps
它的孩子之外,它还要求孩子执行触摸处理。要做到这一点,它会传递各种回调TouchableOpacity
组件的道具。TouchableHighlight
相比之下,它是由本地观点支持的,只需要我们实施setNativeProps
。
setNativeProps清除TextInput值
另一个非常常见的用例setNativeProps
是清除TextInput的值。controlled
TextInput 的道具有时可以在字符bufferDelay
不足的情况下删除字符,并且用户输入的速度非常快。有些开发人员喜欢完全跳过这个道具,而是setNativeProps
在必要时直接操作TextInput值。例如,下面的代码演示了当你点击一个按钮时清除输入:
import React from 'react';
import { TextInput, Text, TouchableOpacity, View } from 'react-native';
export default class App extends React.Component {
clearText = () => {
this._textInput.setNativeProps{text: ''}
}
render() {
return (
<View style={{flex: 1}}>
<TextInput
ref={component => this._textInput = component}
style={{height: 50, flex: 1, marginHorizontal: 20, borderWidth: 1, borderColor: '#ccc'}}
/>
<TouchableOpacity onPress={this.clearText}>
<Text>Clear text</Text>
</TouchableOpacity>
</View>
}
}
避免与渲染功能发生冲突
如果更新也由渲染函数管理的属性,最终可能会出现一些不可预知且令人困惑的错误,因为组件随时重新渲染并且该属性发生更改时,无论先前设置的值如何,都setNativeProps
将被完全忽略和覆盖。
setNativeProps&shouldComponentUpdate
通过智能地应用,shouldComponentUpdate
您可以避免调整未改变的组件子树所涉及的不必要的开销,直到它可能具有足够的性能setState
而不是使用setNativeProps
。
其他本地方法
这里描述的方法在React Native提供的大多数默认组件中都可用。但是,请注意,它们不可
用于不直接由本机视图支持的复合组件。这通常会包含您在自己的应用中定义的大多数组件。
措施(回调)
确定给定视图的屏幕位置,宽度和高度,并通过异步回调返回值。如果成功,将使用以下参数调用回调:
- x
- y
- width
- height
- pageX
- pageY
请注意,这些测量在本机渲染完成后才可用。如果您需要尽快进行测量,请考虑使用onLayout
道具。
measureInWindow(回调)
确定窗口中给定视图的位置,并通过异步回调返回值。如果React根视图嵌入在另一个本地视图中,则会给出绝对坐标。如果成功,将使用以下参数调用回调:
- x
- y
- width
- height
measureLayout(relativeToNativeNode,onSuccess,onFail)
像measure()
,但衡量视图相对祖先,指定为relativeToNativeNode
。这意味着返回的x,y相对于祖先视图的原点x,y。
与往常一样,要获取组件的本地节点句柄,可以使用ReactNative.findNodeHandle(component)
。
focus()
请求重点关注给定的输入或视图。确切的行为将取决于平台和视图的类型。
blur()
从输入或视图中移除焦点。这是相反的focus()
。