全部源代码、文档和图片都在 github 的仓库里,点击进入仓库javascript
npm i react-router-dom -S
// containers/News/index.js import React, { Component } from 'react'; class News extends Component { render() { return ( <div> <h1>News Page</h1> </div> ); } } export default News;
<></>
标签和 <Fragment><Fragment/>
标签是同样的,都是一个聚合子元素的一个标签,不增长真实的 DOM 节点// src/routes.js import React from 'react'; import { Route } from 'react-router-dom'; import Home from './containers/Home'; import News from './containers/News'; export default ( <> <Route path='/' exact component={Home}/> <Route path='/news' component={News}/> </> );
import React from 'react' import { hydrate } from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import routes from '../routes'; hydrate( <BrowserRouter> {routes} </BrowserRouter>, window.root);
,由于服务端并不知道请求是经过什么模式,并且服务端也无需知道,服务端只须要根据客户端发送的请求,作相应的处理便可css
import routes from '../routes'; app.get('*', (req, res) => { let context = {}; let domContent = renderToString( <StaticRouter context={context} location={req.path}> {routes} </StaticRouter> ); // html 的内容不改变 res.send(html); });
app.get('/')
为 app.get('*')
,由于咱们服务端不只仅是接收同一个路由地址,咱们还有 /news 路由,因此咱们要把根路径匹配修改成全局匹配。若是不修改成全局匹配呢,也能够,只不过咱们若是有 100 个路由,咱们就要写 100 个 app.get('/xxx'),若是你愿意的话,也是能够的原理就是html
http://localhost:3000/hello
路由,那么咱们的 routes 是匹配不到的,既然匹配不到,那么 renderToString 渲染的结果就是空,domContent 做为空值插入 HTML 模板,获得的就是一个空白页面// /components/Header/index.js import React, { Component } from 'react'; import { Link } from 'react-router-dom'; class Header extends Component { render() { return ( <nav className="navbar navbar-inverse navbar-fixed-top"> <div className="container-fluid"> <div className="navbar-header"> <a className="navbar-brand">REACT-SSR</a> </div> <div> <ul className="nav navbar-nav"> <li><Link to="/">首页</Link></li> <li><Link to="/news">新闻</Link></li> </ul> </div> </div> </nav> ); } } export default Header;
// src/client/index.js import React from 'react' import { hydrate } from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import routes from '../routes'; import Header from '../components/Header'; hydrate( <BrowserRouter> <> <Header/> <div className="container" style={{marginTop: 70}}> {routes} </div> </> </BrowserRouter>, window.root);
// src/server/index.js import Header from '../compoents/Header'; let domContent = renderToString( <StaticRouter context={context} location={req.path}> <> <Header/> <div className="container" style={{marginTop: 70}}> {routes} </div> </> </StaticRouter> );