需要理解的概念有:
2) 整个应用只有一个完整的页面
3)点击页面中的链接不会刷新页面,只会做页面的局部更新
4)数据都需要通过Ajax请求获取,并在前端异步展现
上面大家已经对单页面有所了解了,下面来讲讲多页应用。
MPA(MultiPage-page application),翻译过来就是多页应用。
在MPA中,每个页面都是一个主页面,都是独立的。
当我们在访问另一个页面的时候,都需要重新加载html、css、js文件,公共文件则根据需求按需加载。
如下图
单页面应用(SPA) | 多页面应用(MPA) | |
---|---|---|
组成 | 一个主页面和多个页面片段 | 多个主页面 |
刷新方式 | 局部刷新 | 整页刷新 |
url模式 | 哈希模式 | 历史模式 |
SEO搜索引擎优化 | 难实现,可使用SSR方式改善 | 容易实现 |
数据传递 | 容易 | 通过url、cookie、localStorage等传递 |
页面切换 | 速度快,用户体验良好 | 切换加载资源,速度慢,用户体验差 |
维护成本 | 相对容易 | 相对复杂 |
优点:
不足:
原理
hash
变化驱动界面变化pushsate
记录浏览器的历史,驱动界面发送变化实现
hash
模式
核心通过监听url
中的hash
来进行路由跳转
// 定义 Router
class Router {
constructor () {
this.routes = {}; // 存放路由path及callback
this.currentUrl = '';
// 监听路由change调用相对应的路由回调
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
this.routes[path] && this.routes[path]()
}
}
// 使用 router
window.miniRouter = new Router();
miniRouter.route('/', () => console.log('page1'))
miniRouter.route('/page2', () => console.log('page2'))
miniRouter.push('/') // page1
history
模式
history 模式核心借用 HTML5 history api,api 提供了丰富的 router 相关属性
先了解一个几个相关的api history.pushState 浏览器历史纪录添加记录
history.replaceState修改浏览器历史纪录中当前纪录
history.popState 当 history 发生变化时触发
// 定义 Router
class Router {
constructor () {
this.routes = {};
this.listerPopState()
}
init(path) {
history.replaceState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
history.pushState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
listerPopState () {
window.addEventListener('popstate' , e => {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]()
})
}
}
// 使用 Router
window.miniRouter = new Router();
miniRouter.route('/', ()=> console.log('page1'))
miniRouter.route('/page2', ()=> console.log('page2'))
// 跳转
miniRouter.push('/page2')
面给出基于Vue的SPA如何实现SEO的三种方式:
将组件或页面通过服务器生成html,再返回给浏览器,如nuxt.js
目前主流的静态化主要有两种:
(1)一种是通过程序将动态页面抓取并保存为静态页面,这样的页面的实际存在于服务器的硬盘中
(2)另外一种是通过WEB服务器的 URL Rewrite的方式,它的原理是通过web服务器内部模块按一定规则将外部的URL请求转化为内部的文件地址,一句话来说就是把外部请求的静态地址转化为实际的动态页面地址,而静态页面实际是不存在的。这两种方法都达到了实现URL静态化的效果
原理是通过Nginx配置,判断访问来源是否为爬虫,如果是则搜索引擎的爬虫请求会转发到一个node server,再通过PhantomJS来解析完整的HTML,返回给爬虫。
SPA:www.qiniu.com、阿里云平台、腾讯云平台等
MPA:www.163.com
需要理解的概念有:
路由概念的核心词汇:静态路由表,分配地址,统一入口,寻址以及过滤
什么是路由:
1 一个路由就是一个映射关系(key.value)
2 key为路径,value可能是function或component
路由的分类
1 后端路由:
① 理解:value是function,用来处理客户端提交的请求
② 注册路由:router.get(path,function(req,res))
③ 工作过程:当node接受到一个请求时,根据请求路径找到匹配的路由,条用路由中的函数来处理请求,返回响应数据
2 前端路由:
① 浏览器路由:value是component,用于展示页面内容
② 注册路由:
③ 工作过程:当浏览器的path变成/test时,当前路由组件就会变成Test组件
对于路由的功能实现原理现在可以大致做个剖析,它其实是提供了一种方式给各个场景之间进行切换操作并且管理其导航历史,每个场景都像一图层,可以推送至其它场景的最后面,当然,如果你将它删除就无法实现该操作了。我们尝试以一种更容易理解的方式进行解释,就是将路由理解成翻书操作,所有的页面就是我们配置的路由模块,可以将书本翻至某一页,也就是其中某一模块,也可以翻到另一页,另一个模块内容,当然,如果需要,还是可以翻回到刚才的那一页的,前提是你不能把那页纸给撕了。
需要理解的概念有:
利用HTML+CSS实现的SPA:http://qn.chinavanes.com/anchor-router.zip
前端路由实现原理的核心模块:https://github.com/ReactTraining/history
前端路由实现原理核心模块的应用:http://qn.chinavanes.com/history-router.zip
需要理解的概念有:
react-router的github地址:https://github.com/ReactTraining/react-router
react-router的官网项目地址:https://reactrouter.com/
react-router的理解:
1、React-router与React-router-dom的功能对比
React-router:实现了路由的核心功能
React-router-dom:基于React-router,加入了一些在浏览器运行下的一些功能,
例如:Link组件会渲染一个a标签
BrowserRouter使用 HTML5 提供的 history API可以保证你的 UI 界面和 URL 保持同步
HashRouter使用 URL 的 hash 部分保证你的 UI 界面和 URL 保持同步
2、React-router与React-router-dom的API对比
React-router:提供了router的核心api。如Router、Route、Switch等,但没有提供有关dom操作进行路由跳转的API
React-router-dom:提供了BrowserRouter、Route、Link等API,可以通过dom操作触发事件控制路由
BrowserRouter | 浏览器模式路由,PC端 |
---|---|
HashRouter | Hash值模式路由,PC端 |
Link | 普通链接 |
NavLink | 导航链接 |
Prompt | 提示 |
MemoryRouter | 内存模式路由,ReactNative移动端 |
Redirect | 重定向 |
Route | 单个路由对象 |
Router | 整体路由对象 |
StaticRouter | 静态路由,SSR服务器端渲染使用 |
Switch | 选择路由 |
generatePath | 生成路由地址 |
history | 历史 |
location | 地址 |
match | 匹配 |
matchPath | 匹配路径 |
withRouter | 接收路由的HOC组件 |
src/components/Home/index.js
import React, { Component } from 'react';
export default class Home extends Component {
render() {
return 我是Home组件;
}
}
src/components/About/index.js
import React, { Component } from 'react';
export default class About extends Component {
render() {
return 我是About组件;
}
}
src/App.js 安装react-router-dom
目前报错:Error: Invariant failed: You should not use outside a
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
);
}
}
export default App;
Route是什么?Route是路由
BrowserRouter与Route的关系是什么?
Router代表的是一整个路由对象,它是数组
Route是整个路由对象中的其中一个而已,是单一的路由模块对象
import React, { Component } from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
);
}
}
export default App;
原生html中,靠跳转到不同的页面
1.A链接可以配合HashRouter进行路由的跳转以及SPA的实现,但是无法配合
BrowserRouter进行操作处理,在链接点击以后,整个页面将会进行刷新的操作
2.利用A链接不容易实现高亮的显示操作
import React, { Component } from 'react';
import { Route, BrowserRouter } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
);
}
}
export default App;
在react中靠路由链接实现切换组件
目前报错:Error: Invariant failed: You should not use outside a
import React, { Component } from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
React Router Demo
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
import React, { Component } from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
React Router Demo
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
将BrowserRotuer迁移至最顶层,也就是入口文件中
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
,
document.getElementById('root')
);
App.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
class App extends Component {
render() {
return (
React Router Demo
{/* 注册路由*/}
);
}
}
export default App;
需要理解的概念有:
1 普通组件:
1) 存放路径:components
2)属性内容:它是没有路由相关的属性对象的
3)操作方式:手动调用
4) 写法不同:
2 路由组件:
1)存放路径:pages
2)属性内容:有路由相关的属性对象的,包括history(go、goBack、goForward、 location、push、replace等),location、match等内容
3) 操作方式:切换
4) 写法不同:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AfmtzAjv-1624175919878)(C:\Users\angi\AppData\Roaming\Typora\typora-user-images\image-20210609204052191.png)]
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
class App extends Component {
render() {
return (
React Router Demo
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
import Home from './pages/Home'; // 路由组件
import About from './pages/About'; // 路由组件
import Header from './components/Header'; // 一般组件
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/components/Header/index.js
import React, { Component } from 'react';
export default class Header extends Component {
render() {
console.log('一般组件属性接收:', this.props);
return (
React Router Demo
);
}
}
import React, { Component } from 'react';
export default class Home extends Component {
render() {
console.log('路由组件属性接收:', this.props);
return 我是Home组件;
}
}
1.使用方式不同:
(1)一般组件:靠程序员亲自写组件标签去渲染,例如:
(2)路由组件:靠路由器进行路径的匹配,从而渲染的
2.存放文件夹不同:
(1)一般组件:components
(2)路由组件:pages
3.收到的props不同
(1)一般组件:程序员写组件标签时传入了什么,那么props中的内容就是什么,
例如:
(2)路由组件:会收到固定的几个props,如下:
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
location: {pathname: "/about", search: "",
hash: "", state: null, key: "1f5ocf"}
push: ƒ push(path, state) //控制路由跳转
replace: ƒ replace(path, state) //控制路由跳转
location:
pathname: "/about"
search: "" //专门用于接收路由search参数
state: null // 专门用于接收路由state参数
match:
params: {} //专门用于接收路由params参数
path: "/about"
url: "/about"
需要理解的概念有:
1 A标签:可以配合HashRouter不可以配合BrowserRouter,而且不容易实现高亮,如果想要实现高亮,就必须使用真实DOM选择操作处理
2 Link标签:可以配合HashRouter以及BrowserRouter进行路由的切换,但是无法实现高亮显示
3 NavLink标签:是一种特殊的Link,可以配合HashRouter以及BrowserRouter进行路由切换,Link所有的功能它都有,并且增加了高亮等操作内容
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
class App extends Component {
render() {
return (
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
public/index.html
权重:!important;
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React Apptitle>
<link rel="stylesheet" href="./css/bootstrap.css">
<style>
.atguigu {
background-color: orange !important;
color: white !important;
}
style>
head>
<body>
<div id="root">div>
body>
html>
需要理解的概念有:
1 保留静态代码
2 提取动态参数属性
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/components/MyNavLink/index.js
封装NavLink
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
export default class MyNavLink extends Component {
render() {
const { to, title } = this.props;
return (
{title}
);
}
}
src/components/MyNavLink/index.js
不定参数的传递
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
export default class MyNavLink extends Component {
render() {
const { title } = this.props;
return (
{title}
);
}
}
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/components/MyNavLink/index.js
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
export default class MyNavLink extends Component {
render() {
const { to, children } = this.props;
return (
{children}
);
}
}
需要理解的概念有:
1 通常情况下,path和component是一一对应关系
2 switch可以提高路由匹配效率(单一匹配)
src/pages/Test/index.js
import React, { Component } from 'react';
export default class Test extends Component {
render() {
return Test;
}
}
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Test from './pages/Test';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Test from './pages/Test';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
需要理解的概念有:
查看bootstrap.css样式的内容,会发现虽然没报404,但样式本质并没有引入正确,返回的是public/index.html,其本质是因为react脚手架项目,如果输入路径找不到都将返回public/index.html的代码内容。
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
{/* 在React中,则需要利用路由链接切换实现--编写路由链接 */} About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React Apptitle>
<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">
<style>
.atguigu {
background-color: orange !important;
color: white !important;
}
style>
head>
<body>
<div id="root">div>
body>
html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React Apptitle>
<link rel="stylesheet" href="/css/bootstrap.css">
<style>
.atguigu {
background-color: orange !important;
color: white !important;
}
style>
head>
<body>
<div id="root">div>
body>
html>
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { HashRouter } from 'react-router-dom';
ReactDOM.render(
,
document.getElementById('root')
);
需要理解的概念有:
匹配原则:
1.默认都是模糊匹配
2.可以利用exact属性进行精确匹配
1)路由的精确匹配
2)路由链接的精确匹配
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
{/* 以开头匹配,所以下面写法匹配的到 */}
Home
{/* 以开头匹配,所以下面写法匹配不到 */}
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
利用exact进行精确匹配处理
1.默认使用的是模糊匹配 2.开启严格匹配:
3.一定要谨慎开启严格匹配模式,因为一旦开启严格匹配会造成该路由的所有子路由全部失效
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
Home
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
);
}
}
export default App;
需要理解的概念有:
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch, Redirect } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
Home
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
{/* 路径都不匹配的情况下,执行以下重定向,一般写在所有路由最下方 */}
{/*
*/}
);
}
}
export default App;
需要理解的概念有:
嵌套路由页面地址:http://qn.chinavanes.com/route_page2.zip
src/pages/Home/Message/index.js
import React, { Component } from 'react';
export default class Message extends Component {
render() {
return (
);
}
}
src/pages/Home/Message/index.js
import React, { Component } from 'react';
export default class News extends Component {
render() {
return (
- news001
- news002
- news003
);
}
}
src/pages/Home/index.js
注册二级路由时,必须包含一级路由的路径
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch, Redirect } from 'react-router-dom';
import MyNavLink from '../../components/MyNavLink';
import Message from './Message';
import News from './News';
export default class Home extends Component {
render() {
return (
Home组件内容
-
News
-
Message
{/* 注册路由 */}
);
}
}
src/App.js
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch, Redirect } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Header from './components/Header';
import MyNavLink from './components/MyNavLink';
class App extends Component {
render() {
return (
About
Home
{/* 注册路由:设置静态路由表,并且分配路由地址 */}
{/* 路径都不匹配的情况下,执行以下重定向 */}
);
}
}
export default App;
src/pages/Home/index.js
重定向的应用
import React, { Component } from 'react';
import { Route, BrowserRouter, Link, NavLink, Switch, Redirect } from 'react-router-dom';
import MyNavLink from '../../components/MyNavLink';
import Message from './Message';
import News from './News';
export default class Home extends Component {
render() {
return (
Home组件内容
-
News
-
Message
{/* 注册路由 */}
);
}
}
需要理解的概念有:
src/pages/Home/Message/index.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';
export default class Message extends Component {
state = {
messageArr: [
{ id: '01', title: '消息1' },
{ id: '02', title: '消息2' },
{ id: '03', title: '消息3' },
],
};
render() {
const { messageArr } = this.state;
return (
<div>
<ul>
{messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
{/*传参在地址*/}
<Link
to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>
{msgObj.title}
</Link>
</li>
);
})}
</ul>
<hr />
{/*设参在路由*/}
<Route path='/home/message/detail/:id/:title'
component={Detail} />
</div>
);
}
}
src/pages/Home/Message/Detail/index.js
import React, { Component } from 'react';
const DetailData = [
{ id: '01', content: '你好,中国' },
{ id: '02', content: '你好,尚硅谷' },
{ id: '03', content: '你好,自己' },
];
export default class Detail extends Component {
render() {
// 查看参数内容
console.log(this.props);
// 接参在组件
const { id, title } = this.props.match.params;
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id;
});
return (
{/*用参在组件*/}
- id:{id}
- title:{title}
- content:{findResult.content}
);
}
}
1.params参数(在路径中拼接进去,即:to只能写字符串)
通过路由链接携带参数:详情
注册路由(一定要声明接收!!!):
接收参数:this.props.match.params
需要理解的概念有:
src/pages/Home/Message/index.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';
export default class Message extends Component {
state = {
messageArr: [
{ id: '01', title: '消息1' },
{ id: '02', title: '消息2' },
{ id: '03', title: '消息3' },
],
};
render() {
const { messageArr } = this.state;
return (
{messageArr.map((msgObj) => {
return (
-
{/*传参在地址*/}
{/*{msgObj.title}*/}
{msgObj.title}
{msgObj.title}
);
})}
{/*设参在路由*/}
{/*
*/}
);
}
}
src/pages/Home/Message/Detail/index.js
import React, { Component } from 'react';
import qs from 'querystring';
const DetailData = [
{ id: '01', content: '你好,中国' },
{ id: '02', content: '你好,尚硅谷' },
{ id: '03', content: '你好,自己' },
];
export default class Detail extends Component {
render() {
// 查看参数内容
console.log(this.props);
// 接参在组件
// const { id, title } = this.props.match.params;
const { search } = this.props.location;
const { id, title } = qs.parse(search.slice(1));
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id;
});
return (
{/*用参在组件*/}
- id:{id}
- title:{title}
- content:{findResult.content}
);
}
}
2.search参数(可以路径中拼接,或把to写成对象,靠search属性传递)
通过路由链接携带参数:详情
注册路由(无需声明接收):
接收参数:this.props.location.search
备注:需要借助querystring进行解析
需要理解的概念有:
src/pages/Home/Message/index.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';
export default class Message extends Component {
state = {
messageArr: [
{ id: '01', title: '消息1' },
{ id: '02', title: '消息2' },
{ id: '03', title: '消息3' },
],
};
render() {
const { messageArr } = this.state;
return (
{messageArr.map((msgObj) => {
return (
-
{/*传参在地址*/}
{/*{msgObj.title}
{msgObj.title}
*/}
{msgObj.title}
);
})}
{/*设参在路由*/}
{/*
*/}
);
}
}
src/pages/Home/Message/Detail/index.js
import React, { Component } from 'react';
import qs from 'querystring';
const DetailData = [
{ id: '01', content: '你好,中国' },
{ id: '02', content: '你好,尚硅谷' },
{ id: '03', content: '你好,自己' },
];
export default class Detail extends Component {
render() {
// 查看参数内容
console.log(this.props);
// 接参在组件
// const { id, title } = this.props.match.params;
// const { search } = this.props.location;
// const { id, title } = qs.parse(search.slice(1));
const { id, title } = this.props.location.state || {};
const findResult =
DetailData.find((detailObj) => {
return detailObj.id === id;
}) || {};
return (
{/*用参在组件*/}
- id:{id}
- title:{title}
- content:{findResult.content}
);
}
}
3.state参数(只能把to写成对象,靠state属性传递)
路由链接(携带参数):详情
注册路由(无需声明接收):
接收参数:this.props.location.state
需要理解的概念有:
1.params参数(在路径中拼接进去,即:to只能写字符串)
通过路由链接携带参数:详情
注册路由(一定要声明接收!!!):
接收参数:this.props.match.params
2.search参数(可以路径中拼接,或把to写成对象,靠search属性传递)
通过路由链接携带参数:详情
注册路由(无需声明接收):
接收参数:this.props.location.search
备注:需要借助querystring进行解析
3.state参数(只能把to写成对象,靠state属性传递)
路由链接(携带参数):详情
注册路由(无需声明接收):
接收参数:this.props.location.state
需要理解的概念有:
src/pages/Home/Message/index.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';
export default class Message extends Component {
state = {
messageArr: [
{ id: '01', title: '消息1' },
{ id: '02', title: '消息2' },
{ id: '03', title: '消息3' },
],
};
render() {
const { messageArr } = this.state;
return (
{messageArr.map((msgObj) => {
return (
-
{/*传参在地址*/}
{/*{msgObj.title}
{msgObj.title}
*/}
{msgObj.title}
);
})}
{/*设参在路由*/}
{/*
*/}
);
}
}
需要理解的概念有:
src/pages/Home/Message/index.js
import React, { Component } from 'react';
import { Link, Route } from 'react-router-dom';
import Detail from './Detail';
export default class Message extends Component {
state = {
messageArr: [
{ id: '01', title: '消息1' },
{ id: '02', title: '消息2' },
{ id: '03', title: '消息3' },
],
};
pushShow = (id, title) => {
// push跳转+params传参
// this.props.history.push(`/home/message/detail/${id}/${title}`);
// push跳转+search传参
// this.props.history.push(`/home/message/detail?id=${id}&title=${title}`);
// push跳转+state传参
this.props.history.push('/home/message/detail', { id, title });
};
replaceShow = (id, title) => {
// replace跳转+params传参
// this.props.history.replace(`/home/message/detail/${id}/${title}`);
// replace跳转+search传参
// this.props.history.replace(`/home/message/detail?id=${id}&title=${title}`);
// replace跳转+state传参
this.props.history.replace('/home/message/detail', { id, title });
};
forward = () => {
this.props.history.goForward();
};
back = () => {
this.props.history.goBack();
};
go = () => {
this.props.history.go(-2);
};
render() {
const { messageArr } = this.state;
return (
{messageArr.map((msgObj) => {
return (
-
{/*传参在地址*/}
{/*{msgObj.title}
{msgObj.title}
*/}
{msgObj.title}
);
})}
{/*设参在路由*/}
{/*
*/}
);
}
}
需要理解的概念有:
src/components/Header/index.js
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Header extends Component {
back = () => {
// 该组件属于一般组件,props属性中不带有路由相关内容
console.log(this.props);
this.props.history.goBack();
};
render() {
console.log('一般组件属性接收:', this.props);
return (
<div className='page-header'>
<h2>React Router Demo</h2>
<button className='btn btn-primary' onClick={this.back}>
返回
</button>
</div>
);
}
}
// 将普通组件转化成带路由功能的组件
export default withRouter(Header);
需要理解的概念有:
import React, { Component } from 'react';
import { Prompt } from 'react-router-dom';
export default class News extends Component {
state = { isBlocking: false };
blocking = () => {
this.setState({ isBlocking: !this.state.isBlocking });
};
render() {
const { isBlocking } = this.state;
return (
{isBlocking.toString()}
`你确认想要去 ${location.pathname}`} />
- news001
- news002
- news003
);
}
}
需要理解的概念有:
BrowserRouter没有任何影响,因为state保存在history对象中
HashRouter刷新后会导致由state参数的丢失
>
push查看
}
}
# 十九 withRouter的使用
需要理解的概念有:
- 一般组件与路由组件的差异与区别
- withRouter是一个HOC,也就是高阶段组件
- 什么是HOC高阶组件
src/components/Header/index.js
```js
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
class Header extends Component {
back = () => {
// 该组件属于一般组件,props属性中不带有路由相关内容
console.log(this.props);
this.props.history.goBack();
};
render() {
console.log('一般组件属性接收:', this.props);
return (
React Router Demo
);
}
}
// 将普通组件转化成带路由功能的组件
export default withRouter(Header);
需要理解的概念有:
import React, { Component } from 'react';
import { Prompt } from 'react-router-dom';
export default class News extends Component {
state = { isBlocking: false };
blocking = () => {
this.setState({ isBlocking: !this.state.isBlocking });
};
render() {
const { isBlocking } = this.state;
return (
{isBlocking.toString()}
`你确认想要去 ${location.pathname}`} />
- news001
- news002
- news003
);
}
}
需要理解的概念有: