在事件处理程序内调用方法是未定义的

时间:2016-10-17 00:06:36

标签: javascript reactjs react-native es6-class

当不需要参数时,handleButtonPress函数在以下示例中起作用...

import React, { Component } from 'react';
import {View, Text, TouchableOpacity} from 'react-native';

export default class MyComponent extends Component {
  constructor(props){
    super(props)
    this.state = {message:"HELLO"}
    this.myFunc = this.myFunc.bind(this)
    this.handleButtonPress = this.handleButtonPress.bind(this)
  }

  render(){
    return (
      <View>
        <Text>{this.state.message}</Text>
        <TouchableOpacity onPress={this.handleButtonPress}>
          <Text>Press Me</Text>
        </TouchableOpacity>
      </View>
    )
  }

  handleButtonPress(){
    console.log("BUTTON WAS PRESSED")
    this.myFunc()
  }

  myFunc(){
    console.log("MY FUNCTION WAS CALLED")
    this.setState({message:"GOODBYE"})
  }

}

但在需要参数时,在以下示例中不起作用:

render(){
    return (
      <View>
        <Text>{this.state.message}</Text>
        <TouchableOpacity onPress={function(){ this.handleButtonPress("GOODBYE") }}>
          <Text>Press Me</Text>
        </TouchableOpacity>
      </View>
    )
  }

  handleButtonPress(message){
    console.log("BUTTON WAS PRESSED WITH MESSAGE: " + message)
    this.myFunc(message)
  }

  myFunc(message){
    console.log("MY FUNCTION WAS CALLED")
    this.setState({message:message})
  }

抛出:undefined is not a function (evaluating 'this.handleButtonPress("GOODBYE")')

我一直在使用的一种策略是在handleButtonPress函数中再次引用render函数,如下所示:

render(){
    handlePress = this.handleButtonPress;

    return (
      <View>
        <Text>{this.state.message}</Text>
        <TouchableOpacity onPress={function(){ handlePress("GOODBYE") }}>
          <Text>Press Me</Text>
        </TouchableOpacity>
      </View>
    )
  }

但还有其他/更好的方法吗?

1 个答案:

答案 0 :(得分:2)

由于存在匿名函数,因此内部的this上下文是全局window对象。由于不存在handleButtonPress,因此会抛出undefined不是函数的错误。您的解决方法有效,因为this仍然引用匿名函数之外的类,因此允许您将其引用分配给handlePress并调用它。

要解决这个问题,您可以使用Function.prototype.bind来补充this上下文功能。从链接的文档:

  

bind()方法会创建一个新函数,在调用时,将this关键字设置为提供的值...

你可以像这样申请:

<TouchableOpacity onPress={function() { this.handleButtonPress("GOODBYE") }.bind(this)}>

这会将匿名函数的this上下文设置为类,而不是全局window对象,从而允许您调用this.handleButtonPress。然后,如文档中所述,可以再次压缩上述内容:

  

bind()方法创建一个新函数,在调用时,将其this关键字设置为提供的值,并在调用新函数时提供任何前面提供的给定参数序列。(强调我的)

     

<强>语法

     

fun.bind(thisArg[, arg1[, arg2[, ...]]])

其中arg1, arg2等是可以绑定到函数的bind的可选参数。这可以这样应用:

<TouchableOpacity onPress={this.handleButtonPress.bind(this, "GOODBYE")}>

这完全摆脱了匿名函数,但this仍然必须在bind方法中传递handleButtonPress