【问题标题】:Reusable modal in ReactJsReactJs 中的可重用模式
【发布时间】:2017-01-01 10:45:53
【问题描述】:

我正在尝试创建一个服务,该服务将显示一个确认对话框并捕获用户的操作(确认/取消),并且可以在任何组件中重复使用,并且尝试次数更少。

到目前为止我尝试了什么(使用React gateway 注入我的对话框)

我创建了一个类似的服务:

var createConfirm = function(options, onConfirm, onCancel) {
  options = options || {};
  var actions = [
    <FlatButton
      label="Cancel"
      primary={true}
      onClick={onCancel}
    />,
    <RaisedButton
      label="OK"
      primary={true}
      onClick={onConfirm}
    />,
  ];
  return (
    <Gateway into="confirm-modal">
      <Dialog
        title={options.title || 'Confirmation'}
        actions={actions}
        modal={true}
        open={true}
      >
        {options.content || 'Are you sure?'}
      </Dialog>
    </Gateway>
  )
}

export default createConfirm;

然后在我的组件中,我将其注入render() 函数:

...
{
   _this.state.isOpen && _this.confirmable
}

每当我需要显示确认模式时,我都会打电话

this.confirmable = createConfirm({
  title: 'CONFIRM',
  content: 'Are you sure to do that'
}, function() {
  console.log('user confirm')
  _this.setState({
    isOpen: false
  });
}, function() {
  console.log('user cancel')
  _this.setState({
    isOpen: false
  })
});
this.setState({isOpen: true});

我的问题

如您所见,我关闭该确认对话框的操作将isOpen 状态设置为false,因此不会呈现。这有点作弊,似乎不是关闭对话框的原生方式(失去离开动画,看起来很奇怪......)。

那么我该如何实现一个我可以完全控制对话框的服务呢?

谢谢!

【问题讨论】:

    标签: javascript reactjs modal-dialog


    【解决方案1】:

    var Modal = React.createClass({
      displayName: 'Modal',
      backdrop: function() {
        return <div className='modal-backdrop in' />;
      },
    
      modal: function() {
        var style = {display: 'block'};
        return (
          <div
            className='modal in'
            tabIndex='-1'
            role='dialog'
            aria-hidden='false'
            ref='modal'
            style={style}
          >
            <div className='modal-dialog'>
              <div className='modal-content'>
                {this.props.children}
              </div>
            </div>
          </div>
        );
      },
    
      render: function() {
        return (
          <div>
            {this.backdrop()}
            {this.modal()}
          </div>
        );
      }
    });
    
    var Confirm = React.createClass({
      displayName: 'Confirm',
      getDefaultProps: function() {
        return {
          confirmLabel: 'OK',
          abortLabel: 'Cancel'
        };
      },
    
      abort: function() {
        return this.promise.reject();
      },
    
      confirm: function() {
        return this.promise.resolve();
      },
    
      componentDidMount: function() {
        this.promise = new $.Deferred();
        return React.findDOMNode(this.refs.confirm).focus();
      },
    
      render: function() {
        var modalBody;
        if (this.props.description) {
          modalBody = (
            <div className='modal-body'>
              {this.props.description}
            </div>
          );
        }
    
        return (
          <Modal>
            <div className='modal-header'>
              <h4 className='modal-title'>
                {this.props.message}
              </h4>
            </div>
            {modalBody}
            <div className='modal-footer'>
              <div className='text-right'>
                <button
                  role='abort'
                  type='button'
                  className='btn btn-default'
                  onClick={this.abort}
                >
                  {this.props.abortLabel}
                </button>
                {' '}
                <button
                  role='confirm'
                  type='button'
                  className='btn btn-primary'
                  ref='confirm'
                  onClick={this.confirm}
                >
                  {this.props.confirmLabel}
                </button>
              </div>
            </div>
          </Modal>
        );
      }
    });
     
    var confirm = function(message, options) {
      var cleanup, component, props, wrapper;
      if (options == null) {
        options = {};
      }
      props = $.extend({
        message: message
      }, options);
      wrapper = document.body.appendChild(document.createElement('div'));
      component = React.render(<Confirm {...props}/>, wrapper);
      cleanup = function() {
        React.unmountComponentAtNode(wrapper);
        return setTimeout(function() {
          return wrapper.remove();
        });
      };
      return component.promise.always(cleanup).promise();
    };
    
    
    $(function() {
      return $('.removable').click(function() {
        return confirm('Are you sure?', {
          description: 'Would you like to remove this item from the list?',
          confirmLabel: 'Yes',
          abortLabel: 'No'
        }).then((function(_this) {
          return function() {
            return $(_this).parent().remove();
          };
        })(this));
      });
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    
    <div id="row">
        <div class="well">
            <ul>
                <li>Foo <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li>
                <li>Bar <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li>
                <li>Baz <a href="#" class="removable"><i class="glyphicon glyphicon-trash"></i></a></li>
            </ul>
        </div>
    </div>

    【讨论】:

    • 关闭对话框/模态的方式:wrapper.remove(); 也和我的方法一样,就是从DOM节点中移除模态,而不是真正关闭它。我想问的是一种完全控制模态的方法。
    猜你喜欢
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2018-05-09
    相关资源
    最近更新 更多