创建React SyntheticEvent以隐藏/显示div onClick和onTouchEnd?

时间:2017-07-26 10:35:12

标签: javascript reactjs events javascript-events event-handling

我有一个通知组件,如下所示: enter image description here

当我点击铃声按钮时,会弹出一个通知容器,如下所示: enter image description here

我已设置功能,以便当用户点击或触摸通知容器外部时,该框将关闭。但是,我不想直接向DOM添加事件。我宁愿利用React的SyntheticEvent wrapper。有谁知道我如何使用SyntheticEvent,而不是我目前拥有的DOM事件?

到目前为止,这是我的代码:

import React from 'react';
import { PropTypes } from 'prop-types';
import './Notification.scss';

export default class Notification extends React.Component {
  constructor(props) {
    super(props);

    this.setNotificationWrapper = this.setNotificationWrapper.bind(this);
    this.handleClickOutside = this.handleClickOutside.bind(this);

    this.state = {
      visible: false,
      hasNotifications: false,
      expanded: false,
    };

    this.toggleNotificationContainer = this.toggleNotificationContainer
    .bind(this);
  }

  componentDidMount() {
    document.addEventListener('touchend', this.handleClickOutside);
    document.addEventListener('mousedown', this.handleClickOutside);
  }

  componentWillUnmount() {
    document.removeEventListener('touchend', this.handleClickOutside);
    document.removeEventListener('mousedown', this.handleClickOutside);
  }

  setNotificationWrapper(node) {
    this.notificationWrapper = node;
  }

  handleClickOutside(event) {
    if (this.notificationWrapper &&
      !this.notificationWrapper.contains(event.target)) {
      this.toggleNotificationContainer();
      event.preventDefault();
    }
  }

  toggleNotificationContainer() {
    this.setState({
      visible: !this.state.visible,
      hasNotifications: this.state.hasNotifications,
      expanded: !this.state.expanded,
    });
  }

  createNotificationItems(option, index) {
    this.state.hasNotifications = true;

    return (
      <li
        key={index}
        value={index}
      >
        {option.label}
      </li>
    );
  }

  render() {
    // set up the details to show in the list.
    let notificationOptions = null;
    let optionCount = 0;
    let toggleDivDetails = null;
    let buttonStyleName = '';
    let buttonText = null;

    if (this.props.notificationButtonIcon) {
      buttonStyleName = 'notificationButton';
    } else {
      buttonText = this.props.notificationButtonText;
      buttonStyleName = 'notificationButtonWithText';
    }

    toggleDivDetails = (
      <button
        onClick={this.toggleNotificationContainer}
        styleName={this.state.expanded ? 'expanded' : buttonStyleName}
        disabled={this.state.expanded}
      >
        {buttonText}
      </button>
    );

    if (this.props.options) {
      optionCount = this.props.options.length;
      notificationOptions = this.props.options.map((option, index) =>
      this.createNotificationItems(option, index));
    }

    if (optionCount === 0) {
      this.state.hasNotifications = false;
    }

    return (
      <div styleName="notificationBar">
        {toggleDivDetails}
        <span
          styleName={
            this.state.hasNotifications ? 'notificationCount' : 'hidden'
          }
        >
          {optionCount}
        </span>
        {
          this.state.visible &&
          <div
            styleName="notificationContainer"
            ref={this.setNotificationWrapper}
          >
            <h3 styleName="notificationHeading">Notifications</h3>
            <h4 styleName="notificationSubHeading">
              {optionCount} notifications
            </h4>
            <ul styleName="notificationList">
              {notificationOptions}
            </ul>
          </div>
        }
      </div>
    );
  }
}

Notification.propTypes = {
  options: PropTypes.arrayOf(PropTypes.object),
  notificationButtonIcon: PropTypes.bool.isRequired,
  notificationButtonText: PropTypes.string.isRequired,
};

Notification.defaultProps = {
  options: [],
  NotificationButtonIcon: true,
  notificationButtonText: 'Toggle Notifications',
};

0 个答案:

没有答案