【问题标题】:React pass all events to child componentReact 将所有事件传递给子组件
【发布时间】:2016-09-08 20:50:49
【问题描述】:

是否可以在 React 中将所有事件传递给子元素。

作为一个例子,我有一个自定义按钮类,它(简化)看起来像这样:

class Button extends Component {
  
  constructor (props) {
    super(props);

    this.onClick      = this.onClick.bind(this);
  }
  
  /* .... */
  
  onClick (ev) {
    const { disabled, onClick } = this.props;
    if (!disabled) {
      onClick(ev);
    }
  }
  
  render () {
     const {
      children,
      disabled,
      type
     } = this.props;
    
    return (
      <button
        disabled={disabled}
        onClick={this.onClick}
        ref="button"
        type={type}
      >{children}</button>
  }
  
  
}

我不知道我将来可能想要使用哪些事件(onMouseDown、onMouseUp、onBlur、onKeyDown、onTouchStart 等等...)

是否可以将所有可能的事件传递给按钮元素而不为每个可能的事件写出一个道具?

将 {...this.props} 添加到按钮元素不是我想要的,因为它传递了所有道具,并且某些道具(如本例中省略的 className)不应直接传递。

我想过克隆 props 对象并删除不应该直接传递的 props,但这感觉就像是 hack。有人知道更清洁的方法吗?

【问题讨论】:

  • 为您的活动命名空间? {...this.props.events}
  • 感谢您的评论@RobM。我已经考虑过您的建议,但我宁愿尽可能接近默认的 React Api。现在我已经编写了一个函数来过滤掉以“on”开头的属性。这是我迄今为止最接近的。我会将这个函数发布为任何有兴趣的人的答案。

标签: javascript reactjs


【解决方案1】:

我编写了一个函数来迭代道具并过滤掉所有以“on”开头的属性,这是我迄今为止最接近的。如果它对其他人有帮助:

/* helpers.js */

export function filterEvents (props, ignore = []) {
  let events = {};
  for (let property in props) {
    if (props.hasOwnProperty(property)) {
      if (property.startsWith('on') && ignore.indexOf(property) === -1) {
        events[property] = props[property];
      }
    }
  }

  return events;
}

/* Tests for the filterEvents */
  
import { expect } from 'chai';

import { filterEvents } from './helpers';

describe('filterEvents', () => {

  const props = {
    className: 'someClass',
    disabled: true,
    onBlur: 'onBlur',
    onClick: 'onClick',
    onMouseDown: 'onMouseDown',
    onMouseUp: 'onMouseUp'
  };

  it('only returns keys starting with on', () => {
    const expected = {
      onBlur: 'onBlur',
      onClick: 'onClick',
      onMouseDown: 'onMouseDown',
      onMouseUp: 'onMouseUp'
    };

    expect(filterEvents(props)).to.deep.equal(expected);
  });

  it('only returns keys starting with on minus the ones in the ignore array', () => {
    const expected = {
      onBlur: 'onBlur',
      onMouseUp: 'onMouseUp'
    };

    const ignore = ['onClick', 'onMouseDown'];
    expect(filterEvents(props, ignore)).to.deep.equal(expected);
  });

});


/* Using the function inside a component */

import { filterEvents } from './helpers'; //at the top of the components file

//Inside the render method:

const events = filterEvents(this.props, ['onClick']); //don't include onClick it's handled like the questions example

return (
  <button
    disabled={this.props.disabled}
    onClick={this.onClick}
    {...events}
  >
    {this.props.children}
  </button>
);

【讨论】:

    猜你喜欢
    • 2019-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多