按 Enter 反应组件

React component with pressing Enter

我有一些 React 组件,需要使用 "Enter" 函数。

class MyComponent extends Component {
    componentDidMount() {
        console.log('componentDidMount');
        document.removeEventListener('keypress', this.enter);
        document.addEventListener('keypress', this.enter.bind(this));
    }

    componentWillUnmount() {
        console.log('componentWillUnmount');
        document.removeEventListener('keypress', this.enter);
    }

    render() {
        return (...);
    }

    enter(target) {
        if (target.charCode === 13) {
            console.log('fired');
            /* after that component unmounted */
        }
    }
}

控制台日志显示:

componentDidMount
fired
componentWillUnmount

,但当按下 Enter 时,控制台再次显示 fired

您永远不会取消绑定事件处理程序。问题是 this.enter.bind(this)this.enter 是不同的函数,因为 Function.prototype.bind 从原始函数创建了新的 "wrapper" 函数。

尝试这样的事情:

class MyComponent extends Component {
    constructor () {
        this.enter = this.enter.bind(this)
    }

    componentDidMount() {
        console.log('componentDidMount');
        document.removeEventListener('keypress', this.enter);
        document.addEventListener('keypress', this.enter);
    }

    componentWillUnmount() {
        console.log('componentWillUnmount');
        document.removeEventListener('keypress', this.enter);
    }

    render() {
        return (...);
    }

    enter(target) {
        if (target.charCode === 13) {
            console.log('fired');
            /* after that component unmounted */
        }
    }
}

注意,您需要为addEventListenerremoveEventListener提供相同的功能。

this.enter.bind(this) returns 一个 new 函数,与 this.enter 不同的函数。所以您的 removeEventListener 被忽略了,因为该特定函数不在事件列表中。

记住 this.enter.bind(this) 的结果并在删除时使用它。

componentDidMount() {
    console.log('componentDidMount');
    this.boundEnter = this.enter.bind(this);
    document.addEventListener('keypress', this.boundEnter);
}

componentWillUnmount() {
    console.log('componentWillUnmount');
    document.removeEventListener('keypress', this.boundEnter);
}

componentDidMount 中也不需要您的 removeEventListener。)

由于您使用的是 ES2015+ 语法,我假设您正在转译。如果是,则可以使用箭头函数而不是 enter:

的方法
class MyComponent extends Component {
    componentDidMount() {
        console.log('componentDidMount');
        document.addEventListener('keypress', this.enter);
    }

    componentWillUnmount() {
        console.log('componentWillUnmount');
        document.removeEventListener('keypress', this.enter);
    }

    render() {
        return (...);
    }

    enter = target => {
        if (target.charCode === 13) {
            console.log('fired');
            /* after that component unmounted */
        }
    };
}

这需要您在转译器中启用对 class properties 的处理(在 Babel 中,它们目前是 stage-2 预设的一部分)。