在普通的旧HTML中,我有DIV

<div class="movie" id="my_movie">

下面是javascript代码

var myMovie = document.getElementById('my_movie');
myMovie.addEventListener('nv-enter', function (event) {
     console.log('change scope');
});

现在我有了一个React组件,在这个组件中,在render方法中,我将返回我的div.如何为我的自定义事件添加一个事件侦听器?(我正在使用此库制作电视应用程序-navigation)

import React, { Component } from 'react';

class MovieItem extends Component {

  render() {

    if(this.props.index === 0) {
      return (
        <div aria-nv-el aria-nv-el-current className="menu_item nv-default">
            <div className="indicator selected"></div>
            <div className="category">
                <span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
            </div>
        </div>
      );
    }
    else {
      return (
        <div aria-nv-el className="menu_item nv-default">
            <div className="indicator selected"></div>
            <div className="category">
                <span className="title">{this.props.movieItem.caption.toUpperCase()}</span>
            </div>
        </div>
      );
    }
  }

}

export default MovieItem;

更新#1:

enter image description here

我应用了答案中提供的所有 idea .我将导航库设置为调试模式,我只能根据键盘在菜单项上导航(正如你在屏幕截图中看到的,我可以导航到电影4),但当我聚焦菜单中的一个项目或按enter键时,我在控制台中看不到任何东西.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class MenuItem extends Component {

  constructor(props) {
    super(props);
    // Pre-bind your event handler, or define it as a fat arrow in ES7/TS
    this.handleNVFocus = this.handleNVFocus.bind(this);
    this.handleNVEnter = this.handleNVEnter.bind(this);
    this.handleNVRight = this.handleNVRight.bind(this);
  }

  handleNVFocus = event => {
      console.log('Focused: ' + this.props.menuItem.caption.toUpperCase());
  }

  handleNVEnter = event => {
      console.log('Enter: ' + this.props.menuItem.caption.toUpperCase());
  }

  handleNVRight = event => {
      console.log('Right: ' + this.props.menuItem.caption.toUpperCase());
  }

  componentDidMount() {
    ReactDOM.findDOMNode(this).addEventListener('nv-focus', this.handleNVFocus);
    ReactDOM.findDOMNode(this).addEventListener('nv-enter', this.handleNVEnter);
    ReactDOM.findDOMNode(this).addEventListener('nv-right', this.handleNVEnter);
    //this.refs.nv.addEventListener('nv-focus', this.handleNVFocus);
    //this.refs.nv.addEventListener('nv-enter', this.handleNVEnter);
    //this.refs.nv.addEventListener('nv-right', this.handleNVEnter);
  }

  componentWillUnmount() {
    ReactDOM.findDOMNode(this).removeEventListener('nv-focus', this.handleNVFocus);
    ReactDOM.findDOMNode(this).removeEventListener('nv-enter', this.handleNVEnter);
    ReactDOM.findDOMNode(this).removeEventListener('nv-right', this.handleNVRight);
    //this.refs.nv.removeEventListener('nv-focus', this.handleNVFocus);
    //this.refs.nv.removeEventListener('nv-enter', this.handleNVEnter);
    //this.refs.nv.removeEventListener('nv-right', this.handleNVEnter);
  }

  render() {
    var attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {};
    return (
      <div ref="nv" aria-nv-el {...attrs} className="menu_item nv-default">
          <div className="indicator selected"></div>
          <div className="category">
              <span className="title">{this.props.menuItem.caption.toUpperCase()}</span>
          </div>
      </div>
    )
  }

}

export default MenuItem;

我留下了一些行注释,因为在这两种情况下,我都无法记录控制台行.

更新#2:这个导航库不能很好地使用React及其原始Html标记,因此我必须设置选项并重命名标记以使用aria-*这样它就不会影响React.

navigation.setOption('prefix','aria-nv-el');
navigation.setOption('attrScope','aria-nv-scope');
navigation.setOption('attrScopeFOV','aria-nv-scope-fov');
navigation.setOption('attrScopeCurrent','aria-nv-scope-current');
navigation.setOption('attrElement','aria-nv-el');
navigation.setOption('attrElementFOV','aria-nv-el-fov');
navigation.setOption('attrElementCurrent','aria-nv-el-current');

推荐答案

如果需要handle DOM events not already provided by React,则必须在安装组件后添加DOM侦听器:

101 Between React 13, 14, and 15 changes were made to the API that affect my answer. Below is the latest way using React 15 and ES7. See 100 for older versions.

class MovieItem extends React.Component {

  componentDidMount() {
    // When the component is mounted, add your DOM listener to the "nv" elem.
    // (The "nv" elem is assigned in the render function.)
    this.nv.addEventListener("nv-enter", this.handleNvEnter);
  }

  componentWillUnmount() {
    // Make sure to remove the DOM listener when the component is unmounted.
    this.nv.removeEventListener("nv-enter", this.handleNvEnter);
  }

  // Use a class arrow function (ES7) for the handler. In ES6 you could bind()
  // a handler in the constructor.
  handleNvEnter = (event) => {
    console.log("Nv Enter:", event);
  }

  render() {
    // Here we render a single <div> and toggle the "aria-nv-el-current" attribute
    // using the attribute spread operator. This way only a single <div>
    // is ever mounted and we don't have to worry about adding/removing
    // a DOM listener every time the current index changes. The attrs 
    // are "spread" onto the <div> in the render function: {...attrs}
    const attrs = this.props.index === 0 ? {"aria-nv-el-current": true} : {};

    // Finally, render the div using a "ref" callback which assigns the mounted 
    // elem to a class property "nv" used to add the DOM listener to.
    return (
      <div ref={elem => this.nv = elem} aria-nv-el {...attrs} className="menu_item nv-default">
        ...
      </div>
    );
  }

}

Example on Codepen.io

Reactjs相关问答推荐

为什么安装FLOBIT后,所有的输入FIELD现在都有一个蓝色的轮廓?

Redux Store未触发React组件中的重新呈现

如何通过回调函数获取多个值?

React Router:在没有手动页面刷新的情况下,路由不会更新内容

使用以Jest 的方式返回 Promise 的方法来模拟可构造的 API 类时出现问题

.populate() 方法在 mongodb 中不起作用

生产部署:控制台中 Firebase 无效 api 密钥错误

使用获取的数据更新状态,但在try console.log 时它给出未定义

Syncfusion:带有 TabItemsDirective 的选项卡组件不显示任何内容

useEffect内部的RETURN语句在首次按钮点击事件中似乎无效的原因是什么?

ReactJS on AWS Amplify与EC2上的Spring boot服务之间的混合内容错误

如何在next.js 13中仅在主页导航栏上隐藏组件?

如何在Next.js应用程序中为路由[slug]生成.html文件?

Zod 验证模式根据另一个数组字段使字段成为必需字段

如何测试使用 React.createportal 呈现的组件?

useEffect 渲染没有依赖数组的组件

仅在重新渲染后设置状态

为什么 state redux-toolkit 是代理?

如何将本地视频文件上传到 Google Cloud

为什么这两个 div 的渲染方式不同?