【问题标题】:How to make the images a button?如何使图像成为按钮?
【发布时间】:2016-11-12 02:06:54
【问题描述】:

我正在开发一个 react native 应用程序,我试图让一些图像像一个按钮一样,这样当你按下它们时,它们会在控制台中打印一条语句。

图像显示如下:

我的代码是:

class ImageList extends Component {
componentWillMount(){
const ds = new ListView.DataSource({
  rowHasChanged: (r1, r2) => r1 !== r2
});
this.dataSource = ds.cloneWithRows(this.props.images);
}

imageTouched(){
 console.log('pressed');
}

renderRow(rowData){
 const {uri} = rowData;

 return(
<View style={{padding: 1, alignSelf: 'flex-start'}}>
  <TouchableHighlight onPress={this.imageTouched}>
   <Image style={styles.imageSize} source={{uri: uri}} />
  </TouchableHighlight>
</View>


 )
}

  render() {
    return (
      <View>
        <ListView
          contentContainerStyle={styles.list}
          dataSource={this.dataSource}
          renderRow={this.renderRow}
        />
      </View>
    );
  }
}

var styles = StyleSheet.create({
  imageSize: {

//newWidth is the width of the device divided by 4. 
//This is so that four images will display in each row. 
    width: newWidth,
    height: newWidth,
    padding: 2
  },
  list: {
        flexDirection: 'row',
        flexWrap: 'wrap'
    }
});

当我运行它时没有错误,但是当我触摸图像时没有任何反应。我检查了控制台,但没有打印任何内容。

如何让每张图片都充当按钮?

【问题讨论】:

  • 如果将this.imageTouched 替换为函数中的console.log() 语句,是否可以记录?我相信当您调用 imageTouched() 函数时,您的作用域是错误的。 This post 应该有助于澄清。

标签: image button react-native


【解决方案1】:

就像其他人提到的那样,问题是this 没有绑定在renderRow() 方法中。我认为解决此问题的最简单方法是将renderRow() 更改为箭头函数:

renderRow = (rowData) => {
  const {uri} = rowData;
  return (
    <View style={{padding: 1, alignSelf: 'flex-start'}}>
      <TouchableHighlight onPress={this.imageTouched}>
        <Image style={styles.imageSize} source={{uri: uri}} />
      </TouchableHighlight>
    </View>
  );
}

箭头函数在调用时总是将 this 设置为其包含范围,因此现在 this.imageTouched 将解析。

请注意,您不必对 imageTouched()-函数或调用执行任何操作,因为它没有引用 this

PS。此语法依赖于 Public Class Fields,这是撰写本文时语言标准的第 2 阶段提案(可能已包含在内,已在内部 React 代码中使用)。此功能可以与在 React Native 项目中默认启用的 babel-plugin 一起使用。

PS2。请注意,在调用中使用箭头函数而不是使用箭头函数声明方法将为每个组件实例创建一个方法实例,而不是每个渲染一个实例。这在性能方面应该真的很好。

【讨论】:

    【解决方案2】:

    定义为 ES6 类的 React 组件不会将方法的 this 上下文自动绑定到组件实例。在这种特殊情况下,renderRow 回调未绑定,上下文引用的是全局应用程序上下文,因此对 this.imageTouched 的引用未定义。

    您经常看到的一种常见模式是在您的渲染方法中绑定回调:

    <ListView
      renderRow={this.renderRow.bind(this)}
    />
    

    然而,这会在每次渲染时创建一个新的函数实例,这会给垃圾收集器带来不必要的工作。

    另一种选择是使用(词法范围)箭头函数并显式调用方法:

    <ListView
      renderRow={(data) => this.renderRow(data);
    />
    

    但这会产生同样的不良影响,即在每次渲染时都不必要地创建函数。

    一种稍微冗长但更“正确”的方法是在类构造函数中绑定回调:

    constructor(props) {
      super(props);
      this.renderRow = this.renderRow.bind(this);
    }
    

    【讨论】:

      【解决方案3】:

      试试这个

      <TouchableHighlight onPress={() => this.imageTouched()}>
      

      一定要绑定renderRow

      renderRow={this.renderRow.bind(this)}
      

      【讨论】:

      • 在这种情况下,这将导致空指针异常,因为 renderRow 中的 this 不包含 imageTouched 方法 - 除非以类似方式传递 renderRow 回调。请参阅我的答案以获得更长的解释。
      猜你喜欢
      • 2018-10-04
      • 2016-05-01
      • 2014-07-12
      • 2021-02-03
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      相关资源
      最近更新 更多