reactstrap 和 react-bootstrap 有什么区别?

72

我发现了两种不同的ReactJS引导程序:

  1. 通过运行"npm install --save reactstrap react react-dom"来安装reactstrap库。
  2. 通过运行"npm install react-bootstrap bootstrap"来安装react-bootstrap库。

这两者之间的基本和主要区别是什么?


1
从Github的统计数据来看,react-bootstrap似乎更活跃。我有一些使用react-bootstrap的经验,但我不能说我很喜欢它 - 我仍然使用很多类而不是在组件上使用props,因为它们缺少很多东西,并且文档在某些情况下不清楚或缺少示例。但是,在查看了reactstrap之后,我认为我将继续使用react-bootstrap,因为他们的文档看起来甚至更糟糕,但代码还不确定。 - llamerr
5个回答

41

我自己一直在苦苦挣扎,正如@Besart Marku所说,这是高度基于个人意见的。

对我有所帮助的一件事是,reactstrap的文档在许多代码示例中使用了state:

import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';

class ModalExample extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      modal: false
    };

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

  toggle() {
    this.setState(prevState => ({
      modal: !prevState.modal
    }));
  }

  render() {
    return (
      <div>
        <Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
        <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
          <ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
          <ModalBody>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </ModalBody>
          <ModalFooter>
            <Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
            <Button color="secondary" onClick={this.toggle}>Cancel</Button>
          </ModalFooter>
        </Modal>
      </div>
    );
  }
}

export default ModalExample; 

vs react-bootstrap 使用函数和 Hooks:

function MyVerticallyCenteredModal(props) {
  return (
    <Modal
      {...props}
      size="lg"
      aria-labelledby="contained-modal-title-vcenter"
      centered
    >
      <Modal.Header closeButton>
        <Modal.Title id="contained-modal-title-vcenter">
          Modal heading
        </Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <h4>Centered Modal</h4>
        <p>
          Cras mattis consectetur purus sit amet fermentum. Cras justo odio,
          dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac
          consectetur ac, vestibulum at eros.
        </p>
      </Modal.Body>
      <Modal.Footer>
        <Button onClick={props.onHide}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
}

function App() {
  const [modalShow, setModalShow] = React.useState(false);

  return (
    <ButtonToolbar>
      <Button variant="primary" onClick={() => setModalShow(true)}>
        Launch vertically centered modal
      </Button>

      <MyVerticallyCenteredModal
        show={modalShow}
        onHide={() => setModalShow(false)}
      />
    </ButtonToolbar>
  );
}

render(<App />);

我不会给出答案说这两种方法哪一个更好,这是一种偏好,对于我个人而言,我选择使用reactstrap,因为我倾向于使用类组件而不是Hooks,所以有成品示例可以轻松调整符合我的需求。


2
Reactstrap现在也在他们的文档中使用Hooks。看起来他们当时只是没有时间用Hook重写那些示例。 - Hikariztw
当我选择使用reactstrap作为我的项目框架时,是因为reactstrap能够正确地支持嵌套模态框。而React-Bootstrap没有合理的方法来渲染一个模态框内部的另一个模态框。不过现在可能已经有所改变了。 - TKoL

31

1
谢谢您的快速回复。但我仍然对它们的用例感到困惑,哪一个更好,为什么?正如您提供的链接所示,它显示了它们的下载比率,但为什么人们会选择其中任何一个呢? - Pallav Raj
2
这个问题没有标准答案,因为它有些主观性。也有很多材料设计库,只是不同的作者而已。你应该阅读他们的文档,找到哪个更容易、更漂亮,然后选择使用。 - Besart Marku

10

官方文档:

从使用角度来看,两者的工作方式相同:

  • 它们需要 npm install bootstrap 以在 index.js 或 App.js 中导入 Bootstrap 样式表文件,从而使用 import 'bootstrap/dist/css/bootstrap.min.css'; 来启用 Bootstrap 的默认样式。ReactJS 默认会将所有的 Bootstrap CSS 代码添加到 HTML 页面的 head 标签内的 style 标签中。
import { StrictMode } from "react";
import ReactDOM from "react-dom";

import "bootstrap/dist/css/bootstrap.min.css";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);

  • 提供已经重新设计的Bootstrap组件,以JSX的形式呈现,无需使用JQuery或Javascript进行直接DOM操作(使用虚拟DOM,因为React已默认工作);
  • 在幕后使用React.createElement来呈现组件;

Props属性

传递给组件的Props属性可以根据包的不同具有不同的名称。请参见按钮颜色的用法:https://codesandbox.io/s/reactbootstrapvsreactstrap-7y87c-7y87c?file=/src/App.js

import React from "react";

import { Button as ReactBootstrapButton } from "react-bootstrap";
import { Button as ReactstrapButton } from "reactstrap";

const App = () => (
  <>
    <ReactBootstrapButton variant="danger">React BootStrap</ReactBootstrapButton>
    <ReactstrapButton color="danger">Reactstrap</ReactstrapButton>
  </>
);

export default App;

道具名称不同,一个是color,另一个是variant,但呈现的HTML基本相同,可以在DevTools中看到: Alt Text 幕后花絮
您可以查看两个实现,比较包中基本组件Button的源代码:
- node_modules\react-bootstrap\cjs\Button.js(React Bootstrap ^1.6.0); - node_modules\reactstrap\dist\reactstrap.cjs.js第930行(Reactstrap v^8.9.0);
React Bootstrap
var Button = /*#__PURE__*/_react.default.forwardRef(function (_ref, ref) {
  var bsPrefix = _ref.bsPrefix,
      variant = _ref.variant,
      size = _ref.size,
      active = _ref.active,
      className = _ref.className,
      block = _ref.block,
      type = _ref.type,
      as = _ref.as,
      props = (0, _objectWithoutPropertiesLoose2.default)(_ref, ["bsPrefix", "variant", "size", "active", "className", "block", "type", "as"]);
  var prefix = (0, _ThemeProvider.useBootstrapPrefix)(bsPrefix, 'btn');
  var classes = (0, _classnames.default)(className, prefix, active && 'active', variant && prefix + "-" + variant, block && prefix + "-block", size && prefix + "-" + size);

  if (props.href) {
    return /*#__PURE__*/_react.default.createElement(_SafeAnchor.default, (0, _extends2.default)({}, props, {
      as: as,
      ref: ref,
      className: (0, _classnames.default)(classes, props.disabled && 'disabled')
    }));
  }

  if (ref) {
    props.ref = ref;
  }

  if (type) {
    props.type = type;
  } else if (!as) {
    props.type = 'button';
  }

  var Component = as || 'button';
  return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({}, props, {
    className: classes
  }));
});

Button.displayName = 'Button';
Button.defaultProps = defaultProps;
var _default = Button;
exports.default = _default;
module.exports = exports["default"];

Reactstrap

var Button = /*#__PURE__*/function (_React$Component) {
  _inheritsLoose(Button, _React$Component);

  function Button(props) {
    var _this;

    _this = _React$Component.call(this, props) || this;
    _this.onClick = _this.onClick.bind(_assertThisInitialized(_this));
    return _this;
  }

  var _proto = Button.prototype;

  _proto.onClick = function onClick(e) {
    if (this.props.disabled) {
      e.preventDefault();
      return;
    }

    if (this.props.onClick) {
      return this.props.onClick(e);
    }
  };

  _proto.render = function render() {
    var _this$props = this.props,
        active = _this$props.active,
        ariaLabel = _this$props['aria-label'],
        block = _this$props.block,
        className = _this$props.className,
        close = _this$props.close,
        cssModule = _this$props.cssModule,
        color = _this$props.color,
        outline = _this$props.outline,
        size = _this$props.size,
        Tag = _this$props.tag,
        innerRef = _this$props.innerRef,
        attributes = _objectWithoutPropertiesLoose(_this$props, ["active", "aria-label", "block", "className", "close", "cssModule", "color", "outline", "size", "tag", "innerRef"]);

    if (close && typeof attributes.children === 'undefined') {
      attributes.children = /*#__PURE__*/React__default.createElement("span", {
        "aria-hidden": true
      }, "\xD7");
    }

    var btnOutlineColor = "btn" + (outline ? '-outline' : '') + "-" + color;
    var classes = mapToCssModules(classNames(className, {
      close: close
    }, close || 'btn', close || btnOutlineColor, size ? "btn-" + size : false, block ? 'btn-block' : false, {
      active: active,
      disabled: this.props.disabled
    }), cssModule);

    if (attributes.href && Tag === 'button') {
      Tag = 'a';
    }

    var defaultAriaLabel = close ? 'Close' : null;
    return /*#__PURE__*/React__default.createElement(Tag, _extends({
      type: Tag === 'button' && attributes.onClick ? 'button' : undefined
    }, attributes, {
      className: classes,
      ref: innerRef,
      onClick: this.onClick,
      "aria-label": ariaLabel || defaultAriaLabel
    }));
  };

  return Button;
}(React__default.Component);

尽管在使用原型的方法和特别是在处理一些额外属性的组件中,reactstrap实现了一些不同之处,但总体上它们之间没有显著的区别。

组件列表

可用组件有80%至90%相同,其中一些仅具有不同的名称。

React Bootstrap:警报(Alerts)、手风琴(Accordion)、徽章(Badge)、面包屑(Breadcrumb)、按钮(Buttons)、按钮组(Button Group)、卡片(Cards)、轮播(Carousel)、下拉菜单(Dropdowns)、图(Figures)、表单(Forms)、输入组(Input Group)、图片(Images)、巨幕(Jumbotron)、列表组(List Group)、模态框(Modal)、导航(Navs)、导航栏(Navbar)、覆盖物(Overlays)、分页(Pagination)、弹出框(Popovers)、进度条(Progress)、旋转器(Spinners)、表格(Table)、选项卡(Tabs)、工具提示(Tooltips)、吐司(Toasts)。

Reactstrap:警报(Alerts)、徽章(Badge)、面包屑(Breadcrumbs)、按钮下拉菜单(Button Dropdown)、按钮组(Button Group)、按钮(Buttons)、卡片(Card)、轮播(Carousel)、折叠(Collapse)、下拉菜单(Dropdowns)、淡入淡出(Fade)、表单(Form)、输入组(Input Group)、巨幕(Jumbotron)、布局(Layout)、列表(List)、列表组(List Group)、媒体(Media)、模态框(Modals)、导航栏(Navbar)、导航(Navs)、分页(Pagination)、弹出框(Popovers)、进度条(Progress)、旋转器(Spinners)、表格(Tables)、选项卡(Tabs)、吐司(Toasts)、工具提示(Tooltips)。

基准测试

您可以在这里查看有关此内容的完整原始帖子


10

我想要补充我的看法。我是从学习React Native和Android开发开始,然后才转向React。

使用Reactstrap的前一种方法更接近于我们在Web开发和Bootstrap中使用的方式,而后者更接近于我在React Native中使用的组件化开发方式。

这真的取决于用例,两者都有意义,但是如果您有一个有许多移动部分的动态页面,我建议使用React-Bootstrap库,因为其实现更接近于组件模型,将允许您使页面元素可重用(当然您也可以使用前面的Reactstrap库实现这一点)。

目前我选择Reactstrap,仅仅因为它默认提供了Bootstrap 4,这正是我需要的而且非常方便。


3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接