之前已经折腾了:
现在就有了两个html了:
之前的index.html,用于显示主页
和
新加的用于显示登录页面的login.html
现在需要去搞清楚,如何给index.html和login.html,加上一个统一的路由
react js router
搭配 React Router | Redux 中文文档 Join the chat at https://gitter.im/camsong/redux-in-chinese
ReactTraining/react-router: Declarative routing for React
Introduction | React Router 中文文档
react js multiple html page how route
javascript – How to create multiple page app using react – Stack Overflow
javascript – Using React in a multi-page app – Stack Overflow
multiple pages with multiple routers · Issue #2899 · ReactTraining/react-router
Multi-page website with React in 2017 – Krithika Muthukumar – Medium
或许是:
想办法把login页面整合到和index页面一起?
react js multiple html route
laravel – How to manage React Js to multiple page app not using routes? – Stack Overflow
react js add route for multiple html
How to use react router to navigate your first react application
貌似典型的login的做法是,保持和index是放在一个app内的?
react js login
Tutorial: Build a React.js Application with User Login & Authentication | Stormpath
ReactJS Authentication Tutorial
Sign Up/ Login Form with ReactJS
mxstbr/login-flow: A login/register flow built with React&Redux
Create basic login forms using create react app module in reactjs
react js 登录页
React使用笔记2–创建登录组件 | Here. There.
的确是:
还是统一使用同一个app的逻辑,然后对于login和index,内部用router去跳转
关键在于router的设置:
ReactDOM.render(<Router history={history}> <Route path="/"> <Route path="index" component={Index} /> <IndexRoute component={Login} /> </Route> </Router>, document.body); |
所以需要先去:
【已解决】React中合并login.html和index.html成单个app.js
然后再去加上router。
react.js – 登录之后react-router的跳转? – SegmentFault
【React.js模仿大众点评webapp】实战教程(11)开发登录页面_慕课手记
快速构建登录页的reactjs组件:neal-react – OPEN 开发经验库
dennybritz/neal-react: Startup Landing Page Components for React.js
用于构建登录页面的,有空的话 也可以去试试。
【React全家桶入门之十】登录与身份认证 – 一韬的React实验室 – CSDN博客
【总结】
最终和两个html页面合并为一个html,都属于app.js中。
然后独立出Main主页面和Login登录页面,点击登录按钮跳转到Main主页面,点击退出,返回登录页面。
webpack.config.js配置及项目的文件结构:
new HtmlWebpackPlugin({ template: ‘./src/app.template.ejs’, filename: ‘index.html’, // chunks: [‘vendor’, ‘index’], hash: true, assetsPrefix: isProd ? ” : `http://localhost:${wdsListenPort}/` }), module.exports = { entry: { // login: ‘./src/login.entry.js’, // index: ‘./src/index.entry.js’, index: ‘./src/app.entry.js’, vendor : [ ‘babel-polyfill’, // Set up an ES6-ish environment ‘react-hot-loader/patch’, ‘./src/lib/adminlte/adminlte_app.js’ ], }, output: { path: path.resolve(__dirname, ‘build’), filename: ‘[name].js’, publicPath: `/${curPublicPath}/` }, |
rse_web/rse_web/src/app.entry.js
import React from ‘react’; import ReactDOM from ‘react-dom’; import App from ‘./pages/app’; ReactDOM.render( <App />, document.getElementById(‘app_root’) ); |
rse_web/src/app.template.ejs
<!DOCTYPE html> <html> <head> <% for (var chunk in htmlWebpackPlugin.files.css) { %> <link rel="preload" href="<%= htmlWebpackPlugin.files.css[chunk] %>" as="style"> <% } %> <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> <link rel="preload" href="<%= htmlWebpackPlugin.files.chunks[chunk].entry %>" as="script"> <% } %> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>xxx后台管理系统</title> <!– Tell the browser to be responsive to screen width –> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <!– Bootstrap 3.3.7 –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/bootstrap/css/bootstrap.min.css"> <!– Font Awesome –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/font-awesome/css/font-awesome.css"> <!– Ionicons –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/css/ionicons/ionicons.min.css"> <!– DataTables –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/datatables/dataTables.bootstrap.min.css"> <!– Theme style –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/adminlte/AdminLTE.min.css"> <!– AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. –> <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/adminlte/_all-skins.min.css"> </head> <body> <div id=’app_root’> </div> <!– <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> –> <script src="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/jquery/jquery-3.1.1.min.js"></script> <script src="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/datatables/jquery.dataTables.min.js"></script> <script src="<%= htmlWebpackPlugin.options.assetsPrefix %>assets/lib/datatables/dataTables.bootstrap.min.js"></script> <!– HtmlWebpackPlugin will generated code include index.js and vendor.bundle.js here –> </body> </html> |
rse_web/src/pages/app.js
import React, { Component } from ‘react’; // import { Router, Route, IndexRoute } from ‘react-router’; // import { BrowserRouter } from ‘react-router-dom’; import { SLASH_PUBLIC_PATH } from ‘common/config’; import { ROUTE_PREFIX } from ‘common/define’; import { BrowserRouter as Router, Route, Link, Switch } from ‘react-router-dom’; import Main from ‘./main/main’; import Login from ‘./login/login’; export default class App extends Component { state = { curUserInfo : { isLogin: false, name: ” } }; constructor(props) { super(props); console.log(`App constructor`); console.log(this.state.curUserInfo); } render() { console.log(`App render`); // <IndexRoute component={Login}/> // <Router> // <Switch> // <Route exact path=’/rse_web/’ component={Login}/> // <Route path=’/rse_web/main’ component={Main}/> // </Switch> // </Router> // <Router basename={SLASH_PUBLIC_PATH}> // <Switch> // <Route exact path=’/’ component={Login}/> // <Route path=’/main’ component={Main}/> // </Switch> // </Router> return ( <Router basename={SLASH_PUBLIC_PATH}> <Switch> <Route exact path={ROUTE_PREFIX.ROOT} component={Login}/> <Route path={ROUTE_PREFIX.MAIN} component={Main}/> </Switch> </Router> ); } } |
rse_web/src/pages/login/login.js
import React, { Component } from ‘react’; import ‘./login.less’; import BodyClassName from ‘react-body-classname’; import { stopEventPropgation } from ‘lib/eventHelper’; import PropTypes from ‘prop-types’; import { ROUTE_PREFIX } from ‘common/define’; export default class Login extends Component { state = { }; constructor(props) { super(props); console.log(`Login constructor`); this.submitLogin = this.submitLogin.bind(this); } submitLogin(e){ //TODO: call API to login console.log(‘Login submitLogin’); stopEventPropgation(e); console.log(e); console.log(this); console.log(this.context); console.log(this.context.router); console.log(this.context.router.transitionTo); //undefined console.log(ROUTE_PREFIX.MAIN); console.log(this.context.router.history); console.log(this.context.router.history.go); if (this.context.router) { // this.context.router.history.push(‘/rse_web/main’); // this.context.router.history.push(‘/main’); this.context.router.history.push(ROUTE_PREFIX.MAIN); // this.context.router.history.go(ROUTE_PREFIX.MAIN); } } render() { console.log(`Login render`); let loginBodyClass = ‘hold-transition login-page’; // <form onSubmit={this.submitLogin}> // <div onClick={this.submitLogin}> // <a className="rse_help" href="https://shimo.im/doc/0kbgLWxVgQYQbjMi">RSE帮助</a> return ( <BodyClassName className={loginBodyClass}> <div className="login-box"> <div className="login-logo"> <a href="#"><b>xxx</b>RSE</a> </div> <div className="login-box-body"> <p className="login-box-msg">请登录</p> <form onSubmit={this.submitLogin}> <div className="form-group has-feedback"> <input type="text" className="form-control" placeholder="账号" /> <span className="glyphicon glyphicon-envelope form-control-feedback"></span> </div> <div className="form-group has-feedback"> <input type="password" className="form-control" placeholder="密码" /> <span className="glyphicon glyphicon-lock form-control-feedback"></span> </div> <div className="row"> <div className="col-xs-12"> <button type="submit" className="btn btn-primary btn-block btn-flat">登录</button> </div> </div> <br /> <a href="https://shimo.im/doc/0kbgLWxVgQYQbjMi" target=’_blank’> <p className="rse_help">RSE帮助</p> </a> </form> </div> </div> </BodyClassName> ); } } Login.contextTypes = { router: PropTypes.object.isRequired }; |
rse_web/src/pages/main/main.js
import React, { Component } from ‘react’; import adminlteReactjs from ‘adminlte-reactjs’; import ReactEcharts from ‘echarts-for-react’; // import style from ‘./main.css’; import ‘./main.css’; // import ‘./main.less’; import BodyClassName from ‘react-body-classname’; import HeaderBar from ‘components/header-bar/header-bar’; import NavigationMenu from ‘components/navigation-menu/navigation-menu’; import MonthPicker from ‘react-month-picker’; import ‘react-month-picker/css/month-picker.less’; 。。。 export default class Main extends Component { state = { isNaviBarCollapse: false, 。。。 }; constructor(props) { super(props); console.log(`Main constructor`); console.log(props); 。。。 this.handleAMonthChange = this.handleAMonthChange.bind(this); this.handleAMonthDissmis = this.handleAMonthDissmis.bind(this); this.handleClickMonthInput = this.handleClickMonthInput.bind(this); this.formatYearMonth = this.formatYearMonth.bind(this); this.toggleSideNaviBarCallback = this.toggleSideNaviBarCallback.bind(this); } 。。。 toggleSideNaviBarCallback(){ console.log(`toggleSideNaviBarCallback`); console.log(`toggleSideNaviBarCallback: before this.state.isNaviBarCollapse=${this.state.isNaviBarCollapse}`); let isCollapse = !this.state.isNaviBarCollapse; this.setState({isNaviBarCollapse : isCollapse}); console.log(`toggleSideNaviBarCallback: -> this.state.isNaviBarCollapse=${this.state.isNaviBarCollapse}`); } generateCurBodyClass(isCollapse) { let mainBodyClass = ‘skin-blue sidebar-mini wysihtml5-supported’; // let curBodyClass = document.body.className; let curBodyClass = mainBodyClass; console.log(`generateCurBodyClass: curBodyClass=${curBodyClass}`); let collapseName = ”; if (document.body.clientWidth > 768){ collapseName = ‘sidebar-collapse’; } else { collapseName = ‘sidebar-open’; } let spaceCollapseName = ‘ ‘ + collapseName; console.log(`collapseName=${collapseName},spaceCollapseName=${spaceCollapseName}`); // //remove previous if existed // if (curBodyClass.includes(spaceCollapseName)){ // curBodyClass = curBodyClass.replace(spaceCollapseName, ”); // console.log(`removed previous: curBodyClass=${curBodyClass}`); // } if (isCollapse) { curBodyClass += spaceCollapseName; console.log(`added: curBodyClass=${curBodyClass}`); } console.log(`isCollapse=${isCollapse} -> curBodyClass=${curBodyClass}`); return curBodyClass; } render() { // console.log(adminlteReactjs); // let ProfileCard = adminlteReactjs.ProfileCard; // let HeaderBar = adminlteReactjs.HeaderBar; // let NavigationMenu = adminlteReactjs.NavigationMenu; // console.log(ProfileCard); // <BodyClassName className={mainBodyClass}> return ( <BodyClassName className={this.generateCurBodyClass(this.state.isNaviBarCollapse)}> <div className="wrapper"> <HeaderBar toggleSideNaviBarCallback={this.toggleSideNaviBarCallback}/> <NavigationMenu /> <div className="content-wrapper"> <section className="content-header"> <h1> xxx <small>管理后台</small> </h1> </section> <section className="content"> 。。。 </div> </BodyClassName> ); } } |
/rse_web/src/common/define.js
export const ROUTE_PREFIX = { ROOT : `/`, MAIN : `/main` }; |
rse_web/src/common/config.js
export const PUBLIC_PATH = ‘rse_web’; export const SLASH_PUBLIC_PATH = `/${PUBLIC_PATH}`; |
最开始进入首页:
http://localhost:4000/rse_web/
加载的Login页面:
点击登录后,进去Main主页:
点击退出登录,回到登录页面: