前言
在讲解 react-hot-loader 之前,我们先把 react 大致的框架搭建好。包括 react-router、redux、react-redux、redux-saga 等。
本篇主要介绍 react-router-v4 搭建。
正文
项目结构调整
如图,目前所有新增目录并没有内容,仅调整了入口文件 index.js
路径,以及删除了用处不大的 main.js
。
*调整后,请修改 webpack.config.js
的入口文件(entry
)路径,以及修改 CSS 的导入路径等,否则会编译失败。
react-router 搭建
首先,我们的项目是单页 Web 应用(simple-page web application,SPA
),它跟我们传统的一个页面对应一个 HTML 不太一样。
单页应用的路由跳转:
- 浏览器的 url 发生改变,但其实并没有发送请求,也没有刷新整个页面。
- 根据我们配置的路由信息,每次切换路由,会根据配置来加载不同的组件,同时 url 地址也会发送变化。
- 主要有
HashRouter
和BrowserRouter
两种模式。 - 原理其实就是使用 HTML5 history API 来使你的内容随着 url 动态改变。
主要路线是:
index.html → index.js → App.js → router 配置 → 加载所匹配的组件 xxxComponent.js
我们的模板 HTML 里面有个 <div id="app"></div>
标签作为容器,接着我们在入口文件 index.js
通过 react-dom
的 render
函数将我们的 App.js
组件插入到其中。而 App.js
就是我们路由的根组件,然后我们的路由,又根据配置加载对应的 xxxComponent.js
子组件。
1. 安装 react-router-dom
react-router-dom
基于 react-router
,加入了在浏览器运行环境下的一些功能。我们无需再安装 react-router
了,因为在 yarn add react-router-dom
时,它就会帮我们安装了。
$ yarn add react-router-dom@5.2.0
2. 创建 App、Home、About、404 组件
App 组件
// App.js import React, { Component } from 'react' import { BrowserRouter, HashRouter as Router, Route, Switch, Link } from 'react-router-dom' import { Home, About, NotFound } from './index' class App extends Component { render() { return ( <Router> <Switch> <Route path="/" exact component={Home} /> <Route path="/about" exact component={About} /> <Route component={NotFound} /> </Switch> </Router> ) } } export default App
Home 组件
// pages/home/index.js import React, { Component } from 'react' class Home extends Component { constructor(props) { super(props) this.state = {} } render() { return <div>Home Component!</div> } } export default Home
About 组件
// pages/about/index.js import React, { Component } from 'react' class About extends Component { constructor(props) { super(props) this.state = {} } render() { return <div>About Component!</div> } } export default About
404 组件
// pages/404.js import React, { Component } from 'react' import { Link } from 'react-router-dom' class NotFound extends Component { constructor(props) { super(props) this.state = {} } render() { return <div>Page not found! <br /> <Link to="/">Go back</Link></div> } } export default NotFound
// pages/index.js export { default as Home } from './home' export { default as About } from './about' export { default as NotFound } from './404'
3. 修改 src/index.js,以及新增 src/Root.js
// Root.js import React from 'react' import App from './pages/App' const Root = () => { return <App /> } export default Root
// index.js import React from 'react' import { render } from 'react-dom' import '../styles/style.css' import Root from './Root' // 最简单的 React 示例 const rootElem = document.getElementById('app') render(<Root />, rootElem)
这里设计多一层 Root
是为了后面引入 Redux 抽离代码,看起来更加简洁一些。
最终目录结构如下:
至此,效果出来了
好了,我们的 react-router 基本搭建好了。
切换路由,http://localhost:8080/#/about 就能看到页面加载了 About Component!
。
关于 react-router 相关的补充说明
- react-router 相关 API 导入问题:
// 1️⃣ 写法一(推荐) import { Swtich, Route, Router, HashHistory, Link } from 'react-router-dom' // 2️⃣ 写法二,二者是等价的 import { Switch, Route, Router } from 'react-router' import { HashHistory, Link } from 'react-router-dom' // ************************************************************************ // Why? // 我们从源码里面可以看到类似以下的这一段代码(截取), // 比如 Switch,它实际上就是引用了 react-router 的 Switch. // 所以我们直接用“写法一”即可 Object.defineProperty(exports, 'Switch', { enumerable: true, get: function () { return reactRouter.Switch; } }); exports.BrowserRouter = BrowserRouter; exports.HashRouter = HashRouter; exports.Link = Link; exports.NavLink = NavLink;