如何使用react显示bootstrap的下拉列表

时间:2017-02-12 06:02:53

标签: twitter-bootstrap reactjs

我在my React.js project中有一个Twitter bootstrap导航栏,我想显示一个下拉列表,就像this codepen中的下拉列表一样。但是,当我点击导航栏中的下拉列表时,我没有看到下拉菜单显示。

Main.js

import React from 'react';
import ReactDOM from 'react-dom'; //Note: when this line is commented out the navbar does not display ???
import { render } from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import './styles/styles.css'; //Webpack can import CSS files too.
// Note: the below import was causing a syntax error.
// import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import { Link } from 'react-router'

render(
    <Router history={browserHistory} routes={routes} />,
    document.getElementById('app')
);

App.js

// This component handles the App template used on every page.
import React, {PropTypes} from 'react';
import Header from './common/Header';
import NavBar from './common/navbar';
import Router from 'react-router';

var navbar = {};
navbar.brand = {linkTo: "#", text: "chrisrjones.com"};
navbar.links = [
    {linkTo: "#", text: "About Me"},
    {linkTo: "#", text: "Contact"},
    {dropdown: true, text: "Contribute", links: [
        {linkTo: "#", text: "Dropdown Link 1"},
        {linkTo: "#", text: "Dropdown Link 2", active: true}
    ]}
];

class App extends React.Component {
    render() {
        return (
            <div className="container-fluid">
                <NavBar {...navbar}/>
                <Header/>
                {this.props.children}
            </div>
        );
    }
}

App.propTypes = {
    children: PropTypes.object.isRequired
};

export default App;

navbar.js

import React, {PropTypes} from 'react';
import { Link, IndexLink } from 'react-router';
import { browserHistory, Router, Route } from 'react-router'
var ReactDOM = require('react-dom');
// import React, { PropTypes } from 'react';

// create classes
var NavBar = React.createClass({
  render: function(){
    return(
      <nav className="navbar navbar-inverse navbar-static-top">
        <div className="container-fluid">
          <div className="navbar-header">
            <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
              <span className="sr-only">Toggle navigation</span>
              <span className="icon-bar"></span>
              <span className="icon-bar"></span>
              <span className="icon-bar"></span>
            </button>
            <NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
          </div>
          <div className="collapse navbar-collapse" id="navbar-collapse">
            <NavMenu links={this.props.links} />
          </div>
        </div>
      </nav>
    );
  }
});

var NavBrand = React.createClass({
  render: function(){
    return (
      <a className="navbar-brand" href={this.props.linkTo}>{this.props.text}</a>
    );
  }
});

var NavMenu = React.createClass({
  render: function(){
    var links = this.props.links.map(function(link){
      if(link.dropdown) {
        return (
          <NavLinkDropdown key={link.text} links={link.links} text={link.text} active={link.active} />
        );
      }
      else {
        return (
          <NavLink key={link.text} linkTo={link.linkTo} text={link.text} active={link.active} />
        );
      }
    });
    return (
      <ul className="nav navbar-nav">
        {links}
      </ul>
    );
  }
});

var NavLinkDropdown = React.createClass({
  render: function(){
    var active = false;
    var links = this.props.links.map(function(link){
      if(link.active){
        active = true;
      }
      return (
        <NavLink key={link.text} linkTo={link.linkTo} text={link.text} active={link.active} />
      );
    });
    return (
      <li className={"dropdown " + (active ? "active" : "")}>
        <a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
          {this.props.text}
          <span className="caret"></span>
        </a>
        <ul className="dropdown-menu">
          {links}
        </ul>
      </li>
    );
  }
});

var NavLink = React.createClass({
  render: function(){
    return(
      <li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text}</a></li>
    );
  }
});

// set data
// var navbar = {};
// navbar.brand =
//   {linkTo: "#", text: "React Bootstrap Navbar"};
// navbar.links = [
//   {linkTo: "#", text: "Link 1"},
//   {linkTo: "#", text: "Link 2"},
//   {dropdown: true, text: "Dropdown", links: [
//     {linkTo: "#", text: "Dropdown Link 1"},
//     {linkTo: "#", text: "Dropdown Link 2", active: true}
//   ]}
// ];

// render NavBar
// ReactDOM.render(
//   // <NavBar {...navbar} />,
//   <NavBar/>
//   document.getElementById("navbar")
// );

module.exports = NavBar;

的package.json

{
  "name": "crj-frontend",
  "version": "1.0.0",
  "description": "This repo will hopefully be the frontend for the new chrisrjones.com website.",
  "main": "index.js",
  "scripts": {
    "start": "babel-node server.js",
    "compile": "webpack",
    "test": "mocha --reporter progress testSetup.js \"src/**/*.test.js\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bootstrap": "^3.3.7",
    "jquery": "^3.1.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-redux": "^5.0.2",
    "react-router": "^3.0.2",
    "react-router-redux": "^4.0.8",
    "redux": "^3.6.0"
  },
  "devDependencies": {
    "babel-core": "^6.22.1",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "babel-preset-react-hmre": "^1.1.1",
    "babel-preset-stage-0": "^6.22.0",
    "css-loader": "^0.26.1",
    "expect": "^1.20.2",
    "express": "^4.14.1",
    "jsdom": "^9.10.0",
    "mocha": "^3.2.0",
    "open": "0.0.5",
    "style-loader": "^0.13.1",
    "webpack": "^2.2.1",
    "webpack-dev-middleware": "^1.10.0",
    "webpack-hot-middleware": "^2.16.1",
    "webpack-node-externals": "^1.5.4",
    "whatwg-fetch": "^2.0.2"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/ipatch/crj-frontend"
  }
}

1 个答案:

答案 0 :(得分:0)

您只需要将jQuery和Bootstrap的Javascript文件添加/加载到您的项目中。解决这个问题的一种方法是添加:

new webpack.ProvidePlugin({
    jQuery: 'jquery',
    $: 'jquery',
    jquery: 'jquery'
})

到您插件内的webpack.config.dev.js

然后导入main.js

import 'jquery';
import 'bootstrap/dist/js/bootstrap';

<强> webpack.config.js

// webpack.config.js
const webpack = require('webpack');
var path = require('path');

module.exports = {
    target: 'web',
    context: path.join(__dirname, 'src'),
    entry: [
        'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
        './main',
    ],
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        new webpack.ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            jquery: 'jquery'
        })
    ],
    module: {
        rules: [{
                loader: 'babel-loader',
                query: {
                    presets: ['es2015', 'react', 'stage-0'],
                },
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
            }
        ]
    },
    devtool: 'source-map',
};

<强> main.js

// main.js
import React from 'react';
import ReactDOM from 'react-dom';
import { render } from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import './styles/styles.css';
import { Link } from 'react-router';
import 'jquery';
import 'bootstrap/dist/js/bootstrap';

render(
    <Router history={browserHistory} routes={routes} />,
    document.getElementById('app')
);

*旁注:就像仅供参考,#app的CSS已应用min-width: 550px;,这可能会对提供的图片中所示的较小视口的导航栏产生负面影响:

#app {
  font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
  color: #4d4d4d;
  min-width: 550px;
  max-width: 850px;
  margin: 0 auto;
}

由于设置了最小宽度,导航栏切换处于屏幕外。

enter image description here

如果您无法删除最小宽度,则可以使用媒体查询。

@media (min-width: 768px) {
  #app {
    min-width: 550px;
  }
}

enter image description here