ale*_*s84 1 react-native onpress
我在 React 上创建了一个游戏,我正在尝试将我的代码调整为 React Native。困扰我的一件事是如何翻译这三行,因为在 RN 中没有可依赖的 DOM 解决方案:
handleClick(e) {
this.props.change(e.currentTarget.id);
}
Run Code Online (Sandbox Code Playgroud)
这里发生的事情是一个无状态的孩子正在收集一个被点击的元素 id(currentTarget 的),并使用它来调用在父元素中定义的方法。e.currentTarget.id然而,这种公式在 RN 中不起作用。
有没有一种雄辩的方法可以在 RN 中重写这一行?
注意:这里和这里有两个与此类似的问题,但答案看起来更像是补丁而不是结构优雅的解决方案。如果您知道某些事情,请发布答案。
编辑:似乎不能绕过 ReactNativeComponentTree。
到目前为止,我有这么多,但这还不起作用:
handlePress(event) {
let number = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget)._currentElement.id;
this.props.change(number);
}
Run Code Online (Sandbox Code Playgroud)
第二次编辑:好吧,也许我应该添加一个我想要实现的简单示例。当我点击任何平面列表的元素时,它的 id 应该显示在 Child 的底部。单击重置将恢复默认状态。
下面的简单示例代码:
import React, { Component } from 'react';
import { AppRegistry, FlatList, StyleSheet, Text, View, Button } from 'react-native';
import ReactNativeComponentTree from 'react-native';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
quotes: ["a","bnaskdkahhahskkdk","c","d","e","a","b","c","d"],
size: [true, true, true, true, true, true, true, true, true],
color: [false, false, false, false, false, false, false, false, false],
progress: "me"
};
this.change = this.change.bind(this);
this.reset = this.reset.bind(this);
}
change(number) {
this.setState({color: [true, true, true, true, true, true, true, true, true], progress: number});
}
reset() {
this.setState({color: [false, false, false, false, false, false, false, false, false],
progress: "me"
});
}
render() {
return (
<View style={styles.container}>
<Child change={this.change} reset={this.reset} quotes={this.state.quotes}
size={this.state.size} color={this.state.color}
progress={this.state.progress} />
</View>
);
}
}
class Child extends Component {
constructor(props) {
super(props);
this.handlePress = this.handlePress.bind(this);
this.handleReset = this.handleReset.bind(this);
}
/*handlePress(e) {
let number = e.currentTarget.id;
this.props.change(number);
}*/
handlePress(event) {
let number = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget)._currentElement.id;
this.props.change(number);
}
handleReset() {
this.props.reset();
}
render() {
let ar = [];
for (let i=0; i<this.props.quotes.length; i++) {
let b = {key: `${i}`, id: i,
classSize: this.props.size[i] ? (i%2===0 ? styles.size : styles.oddsize) : "",
classColor: this.props.color[i] ? (i%2===0 ? styles.color : styles.oddcolor) : ""}
ar.push(b);
}
return (
<View style={styles.container}>
<Button onPress={this.handleReset} title="Reset" />
<FlatList
data={
ar
}
renderItem={({item}) => <Text onPress={this.handlePress}
style={[item.classSize, item.classColor]}> {item.id+1}
{this.props.quotes[item.id]} </Text> }
/>
<Text style={styles.size}>{this.props.progress}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
//justifyContent: "center",
alignItems: "center",
paddingTop: 22,
//backgroundColor: "purple"
},
size: {
flex: 1,
padding: 10,
fontSize: 18,
backgroundColor: "grey",
margin: 1,
height: 44,
color: 'gold',
borderColor: "white",
borderWidth: "1",
textAlign: "center"
},
oddsize: {
flex: 1,
padding: 10,
fontSize: 18,
backgroundColor: "white",
margin: 1,
height: 44,
color: 'gold',
borderColor: "white",
borderWidth: "1",
textAlign: "center"
},
color: {
flex: 1,
padding: 10,
backgroundColor: 'grey',
//borderRadius: "25%",
margin: 1,
fontSize: 18,
height: 44,
color: 'pink',
borderColor: "red",
borderWidth: "1"
},
oddcolor: {
flex: 1,
padding: 10,
backgroundColor: 'white',
//borderRadius: "25%",
margin: 1,
fontSize: 18,
height: 44,
color: 'pink',
borderColor: "red",
borderWidth: "1"
}
})
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => Parent);
Run Code Online (Sandbox Code Playgroud)
获取当前按下的元素属性(在本例中
为id )的更好方法(避免在每次渲染时创建事件回调)是将其包装在父组件中,仅传递数据
并绑定所有事件一次(在构造函数中)
要查看差异,这里有一个更高级的示例:
https : //snack.expo.io/ByTEKgEsZ(示例源代码)
class TouchableText extends React.PureComponent {
constructor(props) {
super(props);
this.textPressed = this.textPressed.bind(this);
}
textPressed(){
this.props.onPressItem(this.props.id);
}
render() {
return (
<Text style={styles.item} onPress={this.textPressed}>
{this.props.children}
</Text>
);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用 const JSX 对象(无状态功能组件),它可以工作但不是最佳的,每次渲染组件时都会创建事件回调,因为箭头函数实际上是渲染函数的快捷方式
const TouchableText = props => {
const textPressed = () => {
props.onPressItem(props.id);
};
return <Text onPress={textPressed} />;
};
Run Code Online (Sandbox Code Playgroud)
class Test extends React.Component {
constructor(props) {
super(props);
//event binding in constructor for performance (happens only once)
//see facebook advice:
//https://facebook.github.io/react/docs/handling-events.html
this.handlePress = this.handlePress.bind(this);
}
handlePress(id) {
//Do what you want with the id
}
render() {
return (
<View>
<FlatList
data={ar}
renderItem={({ item }) => (
<TouchableText
id={item.id}
onPressItem={this.handlePress}
>
{`Component with id ${item.id}`}
</TouchableText>
)}
/>
</View>
);
}
}
Run Code Online (Sandbox Code Playgroud)
正如React Native Handling Events Doc 中所写,还有另一种可能的语法可以避免在构造函数中绑定(虽然是实验性的:即将来可能支持也可能不支持!):
如果调用 bind 使您烦恼,有两种方法可以解决这个问题。如果您使用的是实验属性初始化器语法,则可以使用属性初始化器正确绑定回调
这意味着我们只能写
handlePress = (id) => {
//`this` is already bound!
}
Run Code Online (Sandbox Code Playgroud)
代替
constructor(props) {
super(props);
//manually bind `this` in the constructor
this.handlePress = this.handlePress.bind(this);
}
Run Code Online (Sandbox Code Playgroud)
handlePress(id) {
}
Run Code Online (Sandbox Code Playgroud)
一些参考资料:
事件处理程序和功能无状态组件
React 绑定模式:5 种处理此问题的方法
| 归档时间: |
|
| 查看次数: |
4316 次 |
| 最近记录: |