URL的hash
URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新;
实际截图
HTML5的history
history接口是HTML5新增的, 它有l六种模式改变URL而不刷新页面:
--replaceState:替换原来的路径;
--pushState:使用新的路径;
--popState:路径的回退;
--go:向前或向后改变路径;
--forward:向前改变路径;
--back:向后改变路径;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<a href="//www.greatytc.com/home">首页</a>
<a href="/about">关于</a>
<div class="router-view"></div>
<script>
// 获取所有的a 元素,自己来监听a元素的改变
const aEls = document.querySelectorAll('a');
const routerViewEl = document.querySelector('.router-view')
for (let el of aEls) {
el.addEventListener('click', e => {
console.log(e);
e.preventDefault();
const href = el.getAttribute('href')
history.pushState({}, "哈哈哈", href)
urlChange()
})
}
// 执行返回操作时,依然来到URLChange
window.addEventListener('popstate', urlChange)
window.addEventListener("go", urlChange)
function urlChange() {
console.log(location.pathname);
switch (location.pathname) {
case "//www.greatytc.com/home":
routerViewEl.innerHTML = "首页";
break;
case "/about":
routerViewEl.innerHTML = "关于";
break;
default: routerViewEl.innerHTML = "default"
}
}
</script>
</body>
</html>
实际截图
安装react-router:
安装react-router-dom会自动帮助我们安装react-router的依赖;
yarn add react-router-dom
react-router最主要的API是给我们提供的一些组件:
1.BrowserRouter或HashRouter
--Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;
--BrowserRouter使用history模式;
--HashRouter使用hash模式;
2.Link和NavLink:
--通常路径的跳转是使用Link组件,最终会被渲染成a元素;
--NavLink是在Link基础之上增加了一些样式属性(后续学习);
--to属性:Link中最重要的属性,用于设置跳转到的路径;
3.Route:
Route用于路径的匹配;
--path属性:用于设置匹配到的路径;
--component属性:设置匹配到路径后,渲染的组件;
--exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;
如果模糊匹配的话就需要加exact
路由最基本的使用-实际代码如下:
import React, { PureComponent } from 'react';
import { BrowserRouter,Link,Route } from "react-router-dom"
import './App.css';
import About from './pages/about';
import Home from './pages//www.greatytc.com/home';
import Profile from './pages/profile';
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div>
<BrowserRouter>
{/* 1.跳转路径的方式 */}
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/profile">我的</Link>
{/* 2.跳转之后要显示渲染的页面 exact: 当你写path:"/" 的时候 这个就是一个模糊匹配,所以加exact 是一个严格匹配切记*/}
<Route path="/" exact component={Home}/>
<Route path="/about" component={About}/>
<Route path="/profile" component={Profile}/>
</BrowserRouter>
</div>
)
}
}
export default App;
NavLink的使用:
需求:路径选中时,对应的a元素变为红色
这个时候,我们要使用NavLink组件来替代Link组件:
--activeStyle:活跃时(匹配时)的样式;
--activeClassName:活跃时添加的class;
--exact:是否精准匹配;
--但是,我们会发现在选中about或profile时,第一个也会变成红色:
--原因是/路径也匹配到了/about或/profile;
--这个时候,我们可以在第一个NavLink中添加上exact属性;
默认的activeClassName:
--事实上在默认匹配成功时,NavLink就会添加上一个动态的active class;
--所以我们也可以直接编写样式
--当然,如果你担心这个class在其他地方被使用了,出现样式的层叠,也可以自定义class
NavLink的代码
import React, { PureComponent } from "react";
import { BrowserRouter, NavLink, Link, Route } from "react-router-dom";
import "./App.css";
import About from "./pages/about";
import Home from "./pages//www.greatytc.com/home";
import Profile from "./pages/profile";
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
links: [
{ to: "/", title: "首页" },
{ to: "/about", title: "关于" },
{ to: "/profile", title: "我的" },
],
};
}
render() {
return (
<div>
<BrowserRouter>
{/* 1.跳转路径的方式 */}
{/* <Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/profile">我的</Link> */}
{/* 1.2 需求:路径选中时,对应的a元素变为红色 NAVLink*/}
{/* <NavLink to="/" exact activeStyle={{ color:'red' }}>首页</NavLink>
<NavLink to="/about" activeStyle={{ color:'red' }}>关于</NavLink>
<NavLink to="/profile" activeStyle={{ color:'red' }}>我的</NavLink> */}
<NavLink to="/" exact activeClassName = "link-active">首页</NavLink>
<NavLink to="/about" activeClassName = "link-active">关于</NavLink>
<NavLink to="/profile" activeClassName = "link-active">我的</NavLink>
{/* 2.跳转之后要显示渲染的页面 exact: 当你写path:"/" 的时候 这个就是一个模糊匹配,所以加exact 是一个严格匹配切记*/}
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
</BrowserRouter>
</div>
);
}
}
export default App;
Switch的作用
当我们匹配到某一个路径时,我们会发现有一些问题;
--比如/about路径匹配到的同时,/:userid也被匹配到了,并且最后的一个NoMatch组件总是被匹配到;
原因是什么呢?默认情况下,react-router中只要是路径被匹配到的Route对应的组件都会被渲染;
--但是实际开发中,我们往往希望有一种排他的思想:
--只要匹配到了第一个,那么后面的就不应该继续匹配了;
--这个时候我们可以使用Switch来将所有的Route进行包裹即可;
Redirect
路由的嵌套