簡體   English   中英

React.js 中的 Bootstrap 模式

[英]Bootstrap modal in React.js

我需要通過單擊 Bootstrap 導航欄中的按鈕和其他位置(以顯示組件實例的數據,即提供“編輯”功能)來打開 Bootstrap Modal,但我不知道如何完成此操作。 這是我的代碼:

編輯:代碼已更新。

ApplicationContainer = React.createClass({
    render: function() {
        return (
            <div className="container-fluid">
            <NavBar />
                <div className="row">
                    <div className="col-md-2">
                        <ScheduleEntryList />
                    </div>
                    <div className="col-md-10">
                    </div>
                </div>
                <ScheduleEntryModal />
            </div>
        );
    }
});

NavBar = React.createClass({
    render: function() {
        return (
            <nav className="navbar navbar-default navbar-fixed-top">
                <div className="container-fluid">
                    <div className="navbar-header">
                        <a className="navbar-brand" href="#">
                            <span className="glyphicon glyphicon-eye-open"></span>
                        </a>
                    </div>
                    <form className="navbar-form navbar-left">
                        <button className="btn btn-primary" type="button" data-toggle="modal" data-target="#scheduleentry-modal">
                            <span className="glyphicon glyphicon-plus">
                            </span>
                        </button>
                    </form>
                    <ul className="nav navbar-nav navbar-right">
                        <li><a href="#"><span className="glyphicon glyphicon-user"></span> Username</a></li>
                    </ul>
                </div>
            </nav>
        );
    }
});

ScheduleEntryList = React.createClass({
    getInitialState: function() {
        return {data: []}
    },

    loadData: function() {
        $.ajax({
            url: "/api/tasks",
            dataType: "json",

            success: function(data) {
                this.setState({data: data});
            }.bind(this),

            error: function(xhr, status, error) {
                console.error("/api/tasks", status, error.toString());
            }.bind(this)
        });
    },

    componentWillMount: function() {
        this.loadData();
        setInterval(this.loadData, 20000);
    },

    render: function() {
        items = this.state.data.map(function(item) {
            return <ScheduleEntryListItem item={item}></ScheduleEntryListItem>;
        });

        return (
            <div className="list-group">
                <a className="list-group-item active">
                    <h5 className="list-group-item-heading">Upcoming</h5>
                </a>
                {items}
            </div>
        );
    }
});

ScheduleEntryListItem = React.createClass({
    openModal: function() {
        $("#scheduleentry-modal").modal("show");
    },

    render: function() {
        deadline = moment(this.props.item.deadline).format("MMM Do YYYY, h:mm A");

        return (
            <a className="list-group-item" href="#" onClick={this.openModal}>
                <h5 className="list-group-item-heading">
                    {this.props.item.title}
                </h5>
                <small className="list-group-item-text">
                    {deadline}
                </small>
            </a>
        );
    }
});

Modal = React.createClass({
    componentDidMount: function() {
        $(this.getDOMNode())
            .modal({backdrop: "static", keyboard: true, show: false});
    },

    componentWillUnmount: function() {
        $(this.getDOMNode())
            .off("hidden", this.handleHidden);
    },

    open: function() {
        $(this.getDOMNode()).modal("show");
    },

    close: function() {
        $(this.getDOMNode()).modal("hide");
    },

    render: function() {
        return (
            <div id="scheduleentry-modal" className="modal fade" tabIndex="-1">
                <div className="modal-dialog">
                    <div className="modal-content">
                        <div className="modal-header">
                            <button type="button" className="close" data-dismiss="modal">
                                <span>&times;</span>
                            </button>
                            <h4 className="modal-title">{this.props.title}</h4>
                        </div>
                        <div className="modal-body">
                            {this.props.children}
                        </div>
                        <div className="modal-footer">
                            <button type="button" className="btn btn-danger pull-left" data-dismiss="modal">Delete</button>
                            <button type="button" className="btn btn-primary">Save</button>
                        </div>
                    </div>
                </div>
            </div>

        )
    }
});

ScheduleEntryModal = React.createClass({
    render: function() {
        var modal = null;
        modal = (
            <Modal title="Add Schedule Entry">
                    <form className="form-horizontal">
                        <div className="form-group">
                            <label htmlFor="title" className="col-sm-2 control-label">Title</label>
                            <div className="col-sm-10">
                                <input id="title" className="form-control" type="text" placeholder="Title" ref="title" name="title"/>
                            </div>
                        </div>
                        <div className="form-group">
                            <label htmlFor="deadline" className="col-sm-2 control-label">Deadline</label>
                            <div className="col-sm-10">
                                <input id="deadline" className="form-control" type="datetime-local" ref="deadline" name="deadline"/>
                            </div>
                        </div>
                        <div className="form-group">
                            <label htmlFor="completed" className="col-sm-2 control-label">Completed</label>
                            <div className="col-sm-10">
                                <input id="completed" className="form-control" type="checkbox" placeholder="completed" ref="completed" name="completed"/>
                            </div>
                        </div>
                        <div className="form-group">
                            <label htmlFor="description" className="col-sm-2 control-label">Description</label>
                            <div className="col-sm-10">
                                <textarea id="description" className="form-control" placeholder="Description" ref="description" name="description"/>
                            </div>
                        </div>
                    </form>
            </Modal>
        );

        return (
            <div className="scheduleentry-modal">
                {modal}
            </div>
        );
    }
});

對代碼的其他評論和改進表示贊賞。

我最近正在尋找一個很好的解決方案,而無需將 React-Bootstrap 添加到我的項目中(因為 Bootstrap 4 即將發布)。

這是我的解決方案: https : //jsfiddle.net/16j1se1q/1/

let Modal = React.createClass({
    componentDidMount(){
        $(this.getDOMNode()).modal('show');
        $(this.getDOMNode()).on('hidden.bs.modal', this.props.handleHideModal);
    },
    render(){
        return (
          <div className="modal fade">
            <div className="modal-dialog">
              <div className="modal-content">
                <div className="modal-header">
                  <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                  <h4 className="modal-title">Modal title</h4>
                </div>
                <div className="modal-body">
                  <p>One fine body&hellip;</p>
                </div>
                <div className="modal-footer">
                  <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
                  <button type="button" className="btn btn-primary">Save changes</button>
                </div>
              </div>
            </div>
          </div>
        )
    },
    propTypes:{
        handleHideModal: React.PropTypes.func.isRequired
    }
});



let App = React.createClass({
    getInitialState(){
        return {view: {showModal: false}}
    },
    handleHideModal(){
        this.setState({view: {showModal: false}})
    },
    handleShowModal(){
        this.setState({view: {showModal: true}})
    },
    render(){
    return(
        <div className="row">
            <button className="btn btn-default btn-block" onClick={this.handleShowModal}>Open Modal</button>
            {this.state.view.showModal ? <Modal handleHideModal={this.handleHideModal}/> : null}
        </div>
    );
  }
});

React.render(
   <App />,
    document.getElementById('container')
);

主要思想是僅在要顯示時將 Modal 組件渲染到 React DOM 中(在 App 組件渲染函數中)。 我保留一些“視圖”狀態,指示當前是否顯示模態。

'componentDidMount' 和 'componentWillUnmount' 回調通過 Bootstrap javascript 函數隱藏或顯示模式(一旦它被渲染到 React DOM 中)。

我認為這個解決方案很好地遵循了 React 精神,但歡迎提出建議!

您可以使用 React-Bootstrap ( https://react-bootstrap.github.io/components/modal )。 該鏈接上有一個模態示例。 加載 react-bootstrap 后,模態組件就可以用作反應組件:

var Modal = ReactBootstrap.Modal;

然后可以用作反應組件作為<Modal/>

對於 Bootstrap 4,有 react-strap ( https://reactstrap.github.io )。 React-Bootstrap 僅支持 Bootstrap 3。

getDOMNode()已棄用。 而是使用ref來訪問 DOM 元素。 這是工作模態組件(Bootstrap 4)。 決定是否在父組件中顯示 Modal 組件。

示例: https : //jsfiddle.net/sqfhkdcy/

class Modal extends Component {
    constructor(props) {
        super(props);
    }
    componentDidMount() {
        $(this.modal).modal('show');
        $(this.modal).on('hidden.bs.modal', handleModalCloseClick);
    }
    render() {
        return (
            <div>
                <div className="modal fade" ref={modal=> this.modal = modal} id="exampleModal" tabIndex="-1" role="dialog" aria- labelledby="exampleModalLabel" aria-hidden="true">
                    <div className="modal-dialog" role="document">
                        <div className="modal-content">
                            <div className="modal-header">
                                <h5 className="modal-title" id="exampleModalLabel">Modal title
                                </h5>
                                <button type="button" className="close" data- dismiss="modal" aria-label="Close">
                                    <span aria-hidden="true">&times;</span>
                                </button>
                            </div>
                            <div className="modal-body">
                                ...
                            </div>
                            <div className="modal-footer">
                                <button type="button" className="btn btn-secondary" data- dismiss="modal">Close</button>
                                <button type="button" className="btn btn-primary">Save changes</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

編輯:

以下是使其工作所需的導入:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;
global.jQuery = $;

我只使用 bootstrap cdn (css + js) 來實現類似“reactstrap”的解決方案。 我使用 props.children 將動態數據從父組件傳遞到子組件。 您可以在此處找到更多相關信息。 通過這種方式,您擁有三個獨立的組件:模態頁眉、模態正文和模態頁腳,它們彼此完全獨立。


//Modal component
import React, { Component } from 'react';

export const ModalHeader = props => {
  return <div className="modal-header">{props.children}</div>;
};

export const ModalBody = props => {
  return <div className="modal-body">{props.children}</div>;
};

export const ModalFooter = props => {
  return <div className="modal-footer">{props.children}</div>;
};

class Modal extends Component {
  constructor(props) {
    super(props);
    this.state = {
      modalShow: '',
      display: 'none'
    };
    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
  }

  openModal() {
    this.setState({
      modalShow: 'show',
      display: 'block'
    });
  }

  closeModal() {
    this.setState({
      modalShow: '',
      display: 'none'
    });
  }

  componentDidMount() {
    this.props.isOpen ? this.openModal() : this.closeModal();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.isOpen !== this.props.isOpen) {
      this.props.isOpen ? this.openModal() : this.closeModal();
    }
  }

  render() {
    return (
      <div
        className={'modal fade ' + this.state.modalShow}
        tabIndex="-1"
        role="dialog"
        aria-hidden="true"
        style={{ display: this.state.display }}
      >
        <div className="modal-dialog" role="document">
          <div className="modal-content">{this.props.children}</div>
        </div>
      </div>
    );
  }
}

export default Modal;

//App component
import React, { Component } from 'react';
import Modal, { ModalHeader, ModalBody, ModalFooter } from './components/Modal';

import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      modal: false
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle() {
    this.setState({ modal: !this.state.modal });
  }

  render() {
    return (
      <div className="App">
        <h1>Bootstrap Components</h1>

        <button
          type="button"
          className="btn btn-secondary"
          onClick={this.toggle}
        >
          Modal
        </button>

        <Modal isOpen={this.state.modal}>
          <ModalHeader>
            <h3>This is modal header</h3>
            <button
              type="button"
              className="close"
              aria-label="Close"
              onClick={this.toggle}
            >
              <span aria-hidden="true">&times;</span>
            </button>
          </ModalHeader>
          <ModalBody>
            <p>This is modal body</p>
          </ModalBody>
          <ModalFooter>
            <button
              type="button"
              className="btn btn-secondary"
              onClick={this.toggle}
            >
              Close
            </button>
            <button
              type="button"
              className="btn btn-primary"
              onClick={this.toggle}
            >
              Save changes
            </button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default App;

我創建了這個函數:

onAddListItem: function () {
    var Modal = ReactBootstrap.Modal;
    React.render((
        <Modal title='Modal title' onRequestHide={this.hideListItem}>
            <ul class="list-group">
                <li class="list-group-item">Cras justo odio</li>
                <li class="list-group-item">Dapibus ac facilisis in</li>
                <li class="list-group-item">Morbi leo risus</li>
                <li class="list-group-item">Porta ac consectetur ac</li>
                <li class="list-group-item">Vestibulum at eros</li>
            </ul>
        </Modal>
    ), document.querySelector('#modal-wrapper'));
}

然后在我的 Button 觸發器上使用它。

要“隱藏”模態:

hideListItem: function () {
    React.unmountComponentAtNode(document.querySelector('#modal-wrapper'));
},

您可以使用來自鏈接的 react-bootstrap 中的模型,它基本上是基於函數的

function Example() {
  const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);
  return (
    <>
      <Button variant="primary" onClick={handleShow}>
        Launch demo modal
      </Button>

      <Modal show={show} onHide={handleClose} animation={false}>
        <Modal.Header closeButton>
          <Modal.Title>Modal heading</Modal.Title>
        </Modal.Header>
        <Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            Close
          </Button>
          <Button variant="primary" onClick={handleClose}>
            Save Changes
          </Button>
        </Modal.Footer>
      </Modal>
    </>
  );
}

並且您可以將其轉換為類組件

import React, { Component } from "react";
import { Button, Modal } from "react-bootstrap";


export default class exampleextends Component {
  constructor(props) {
    super(props);
    this.state = {
      show: false,
      close: false,
    };
  } 
  render() {
    return (
      <div>
        <Button
          variant="none"
          onClick={() => this.setState({ show: true })}
        >
          Choose Profile
        </Button>
        <Modal
          show={this.state.show}
          animation={true}
          size="md" className="" shadow-lg border">
          <Modal.Header className="bg-danger text-white text-center py-1">
            <Modal.Title className="text-center">
              <h5>Delete</h5>
            </Modal.Title>
          </Modal.Header>
          <Modal.Body className="py-0 border">
            body   
          </Modal.Body>
<Modal.Footer className="py-1 d-flex justify-content-center">
              <div>
                <Button
                  variant="outline-dark" onClick={() => this.setState({ show: false })}>Cancel</Button>
              </div>
              <div>
                <Button variant="outline-danger" className="mx-2 px-3">Delete</Button>
              </div>
            </Modal.Footer>
        </Modal>
      </div>
    );
  }
}

你可以試試這個modal: https : //github.com/xue2han/react-dynamic-modal它是無狀態的,只在需要的時候才渲染,所以非常好用。就像這樣:

    class MyModal extends Component{
       render(){
          const { text } = this.props;
          return (
             <Modal
                onRequestClose={this.props.onRequestClose}
                openTimeoutMS={150}
                closeTimeoutMS={150}
                style={customStyle}>
                <h1>What you input : {text}</h1>
                <button onClick={ModalManager.close}>Close Modal</button>
             </Modal>
          );
       }
    }

    class App extends Component{
        openModal(){
           const text = this.refs.input.value;
           ModalManager.open(<MyModal text={text} onRequestClose={() => true}/>);
        }
        render(){
           return (
              <div>
                <div><input type="text" placeholder="input something" ref="input" /></div>
                <div><button type="button" onClick={this.openModal.bind(this)}>Open Modal </button> </div>
              </div>
           );
        }
    }

    ReactDOM.render(<App />,document.getElementById('main'));

感謝@tgrrr 提供了一個簡單的解決方案,尤其是當不需要 3rd 方庫時(例如 React-Bootstrap)。 然而,這個解決方案有一個問題:模態容器嵌入在反應組件內部,當外部反應組件(或其父元素)的位置樣式為固定/相對/絕對時,會導致模態背景問題 我遇到了這個問題並想出了一個新的解決方案:

"use strict";

var React = require('react');
var ReactDOM = require('react-dom');

var SampleModal = React.createClass({
  render: function() {
    return (
      <div className="modal fade" tabindex="-1" role="dialog">
        <div className="modal-dialog">
          <div className="modal-content">
            <div className="modal-header">
              <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
              <h4 className="modal-title">Title</h4>
            </div>
            <div className="modal-body">
              <p>Modal content</p>
            </div>
            <div className="modal-footer">
              <button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
              <button type="button" className="btn btn-primary">OK</button>
            </div>
          </div>
        </div>
      </div>
    );
  }
});

var sampleModalId = 'sample-modal-container';
var SampleApp = React.createClass({
  handleShowSampleModal: function() {
    var modal = React.cloneElement(<SampleModal></SampleModal>);
    var modalContainer = document.createElement('div');
    modalContainer.id = sampleModalId;
    document.body.appendChild(modalContainer);
    ReactDOM.render(modal, modalContainer, function() {
      var modalObj = $('#'+sampleModalId+'>.modal');
      modalObj.modal('show');
      modalObj.on('hidden.bs.modal', this.handleHideSampleModal);
    }.bind(this));
  },
  handleHideSampleModal: function() {
    $('#'+sampleModalId).remove();
  },
  render: function(){    
    return (
      <div>
        <a href="javascript:;" onClick={this.handleShowSampleModal}>show modal</a>
      </div>
    )
  }
});

module.exports = SampleApp;

主要思想是:

  1. 克隆模態元素(ReactElement 對象)。
  2. 創建一個 div 元素並將其插入到文檔正文中。
  3. 在新插入的 div 元素中呈現克隆的模態元素。
  4. 渲染完成后,顯示模態。 另外,附加一個事件偵聽器,以便當 modal 隱藏時,新插入的 div 元素將被刪除。

Reactstrap 在 React 中也有一個Bootstrap Modals實現 該庫面向 Bootstrap 版本 4,而 react-bootstrap 面向版本 3.X。

使用 React 功能組件的解決方案。

import React, { useState, useRef, useEffect } from 'react'

const Modal = ({ title, show, onButtonClick }) => {

    const dialog = useRef({})

    useEffect(() => { $(dialog.current).modal(show ? 'show' : 'hide') }, [show])
    useEffect(() => { $(dialog.current).on('hide.bs.modal', () =>
        onButtonClick('close')) }, [])

    return (
        <div className="modal fade" ref={dialog}
            id="modalDialog" tabIndex="-1" role="dialog"
            aria-labelledby="modalDialogLabel" aria-hidden="true"
        >
            <div className="modal-dialog" role="document">
                <div className="modal-content">
                    <div className="modal-header">
                        <h5 className="modal-title" id="modalDialogLabel">{title}</h5>
                        <button type="button" className="close" aria-label="Close"
                            onClick={() => onButtonClick('close')}
                        >
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div className="modal-body">
                        ...
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="btn btn-secondary"
                            onClick={() => onButtonClick('close')}>Close</button>
                        <button type="button" className="btn btn-primary"
                            onClick={() => onButtonClick('save')}>Save</button>
                    </div>
                </div>
            </div>
        </div>
    )
}

const App = () => {

    const [ showDialog, setShowDialog ] = useState(false)

    return (
        <div className="container">
            <Modal
                title="Modal Title"
                show={showDialog}
                onButtonClick={button => {
                    if(button == 'close') setShowDialog(false)
                    if(button == 'save') console.log('save button clicked')
                }}
            />
            <button className="btn btn-primary" onClick={() => {
                setShowDialog(true)
            }}>Show Dialog</button>
        </div>
    )
}

最快的解決方法是顯式使用全局上下文中的 jQuery $(已使用 $.modal() 擴展,因為您在執行時在腳本標記中引用了它):

  window.$('#scheduleentry-modal').modal('show') // to show 
  window.$('#scheduleentry-modal').modal('hide') // to hide

所以這就是你可以如何反應

import React, { Component } from 'react';

export default Modal extends Component {
    componentDidMount() {
        window.$('#Modal').modal('show');
    }

    handleClose() {
        window.$('#Modal').modal('hide');
    }

    render() {
        <
        div className = 'modal fade'
        id = 'ModalCenter'
        tabIndex = '-1'
        role = 'dialog'
        aria - labelledby = 'ModalCenterTitle'
        data - backdrop = 'static'
        aria - hidden = 'true' >
            <
            div className = 'modal-dialog modal-dialog-centered'
        role = 'document' >
            <
            div className = 'modal-content' >
            // ...your modal body
            <
            button
        type = 'button'
        className = 'btn btn-secondary'
        onClick = {
                this.handleClose
            } >
            Close <
            /button> < /
        div > <
            /div> < /
        div >
    }
}

只需將href='#scheduleentry-modal'到要打開模態的元素

或者使用 jQuery: $('#scheduleentry-modal').modal('show');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM