1.单页面(spa)应用的特点
顾名思义,整个应用中只有一个页面,Vue和React都是典型的SPA。
优点:只有在第一次加载时会完整的加载整个页面(由此也就有了spa首次加载慢的性能问题),其他时候都是仅仅更新必要的数据。故用户体验更好,运行更流畅
缺点:不利于SEO优化,简单理解SEO优化:因为爬虫只爬取HTML页面中的文本内容,不会执行Js代码。对于这个问题我们的解决方式一般是:通过SSR(服务端渲染),即先在服务端把内容渲染出来,然后返回给浏览器的就是纯HTML内容。
2.react/vue路由核心原理
前端路由是一套映射规则,是 URL路径 与 组件 的对应关系
使用 React 路由简单来说就是:配置路径和组件(配对)
核心:监听hashChange事件
hash值: localhost:3000/#/page1
#之后的部分就是hash值,它有两个特点:
- hash值的变化(地址栏中改了hash值再回车)不会重新发请求。它不是请求路径的一部分。
- hash值的变化会触发hashChange事件。
举例:
维护一个状态curHash。
- 当hash变化(hashchange事件)时修改它;
- 根据curHash的值来决定显示哪个组件
举例代码
目录结构
pages/Comment.jsx pages/Home.jsx pages/Search.jsx index.js
index.js
import React, { useEffect, useState } from 'react' import Home from './pages/Home.jsx' import Search from './pages/Search.jsx' import Comment from './pages/Comment.jsx' import ReactDom from 'react-dom' export default function App () { const [curHash, setCurHash] = useState('') useEffect(() => { const onChange = () => { // console.log(window.location.hash) setCurHash(window.location.hash.slice(1)) } onChange() window.addEventListener('hashchange', onChange) return () => { window.removeEventListener('hashchange', onChange) } }, []) return ( <div> <ul> <li> <a href="#/home">首页</a> </li> <li> <a href="#/comment">评论</a> </li> <li> <a href="#/search">搜索</a> </li> </ul> <hr /> {curHash === '/home' && <Home />} {curHash === '/search' && <Search />} {curHash === '/comment' && <Comment />} </div> ) } ReactDom.render(<App />, document.getElementById('root'))
3.React路由使用的基本
安装包。npm i react-router-dom@5.3.
这个包提供了三个核心的组件:HashRouter, Route, Link
导入包,并使用。import { HashRouter, Route, Link } from 'react-router-dom'
使用HashRouter包裹整个应用,一个项目中只会有一个Router
使用Link指定导航链接
使用Route指定路由规则(哪个路径展示哪个组件)
代码举例:
import React from 'react' import ReactDom from 'react-dom' import { HashRouter, Route, Link } from 'react-router-dom' import Search from './pages/Search.jsx' import Comment from './pages/Comment.jsx' export default function App () { return ( <div> <h1>react路由基本使用</h1> <HashRouter> <Link to="/comment">评论</Link> <Link to="/search">搜索</Link> <Route path="/comment" component={Comment} /> <Route path="/search" component={Search} /> </HashRouter> </div> ) } ReactDom.render(<App />, document.getElementById('root'))
4.路由三大对象之-Router
目标
了解两种路由
HashRouter :hash模式
BrowserRouter: history模式
内容
Router 组件:包裹整个应用,一个 React 应用只需要使用一次
两种常用 Router:HashRouter
和 BrowserRouter
HashRouter:使用 URL 的哈希值实现(http://localhost:3000/#/first)
原理:监听 window 的 hashchange 事件来实现的
(推荐)BrowserRouter:使用 H5 的 history.pushState() API 实现(http://localhost:3000/first)
原理:监听 window 的 popstate 事件来实现的
举例:
使用es6的导入重命名来统一名字: 无论导入的是哪个路由对象,都叫Router
import { BrowserRouter as Router, Route, Link } from 'react-router-dom' import { HashRouter as Router, Route, Link } from 'react-router-dom' <Router>
5.路由三大对象之-Link
目标
掌握Link和NavLink的区别;
能使用NavLink设置高亮效果;
import { Link, NavLink } from 'react-router-dom'
Link
Link组件最终会渲染成a标签,用于指定路由导航
- to属性,将来会渲染成a标签的href属性
Link
组件无法展示哪个link处于选中的效果
NavLink
NavLink
组件,一个更特殊的Link
组件,可以用用于指定当前导航高亮
格式:
<NavLink to="/xxx" activeClassName="active">链接</NavLink>
说明:
- to属性,用于指定地址,会渲染成a标签的href属性
- activeClassName: 用于指定高亮的类名,默认
active
。一般不去修改。 - exact: 精确匹配,表示必须地址栏和to的属性值 精确匹配类名才生效
测试代码
import React from 'react' import ReactDom from 'react-dom' import { BrowserRouter as Router, Route, Link, NavLink } from 'react-router-dom' import Search from './pages/Search.jsx' import Comment from './pages/Comment.jsx' export default function App () { return ( <div> <h1>react路由基本使用-Link</h1> <Router> <div> Link: <Link to="/search">搜索</Link> <Link to="/comment">评论</Link> </div> <div> NavLink: 自带高亮类 <NavLink to="/" exact>主页</NavLink> <NavLink to="/search">搜索</NavLink> <NavLink to="/comment">评论</NavLink> </div> <Route path="/comment" component={Comment} /> <Route path="/search" component={Search} /> </Router> </div> ) } ReactDom.render(<App />, document.getElementById('root'))
小结
- link和NavLink都用来做路由跳转。它们都用属性来指定跳转地址
- link和NavLink的区别是,NavLink指向的路径会自带一个名为____的css类名
6.路由三大对象之-Route
目标
掌握配置路由规则
浏览器的路径和path的匹配成功,就会显示组件
route的作用和格式
- 作用: 决定路由匹配规则
- 格式:
<Route path="/xx/xx" component={组件}></Route>
匹配规则
名词约定:
- path: Route组件中path属性的值
- pathname: 指的如下格式
- link组件中to的属性值
- 地址栏中的地址
模糊匹配规则
- 只要pathname以path开头就算匹配成功
- 匹配成功就加载对应组件;
- 整个匹配过程是逐一匹配,一个匹配成功了,并不会停止匹配。
模糊匹配和精确匹配
- 默认是模糊匹配的
- 补充exact可以设置成精确匹配
示例
import React from 'react' import ReactDom from 'react-dom' import { BrowserRouter as Router, Route, NavLink } from 'react-router-dom' const Home = () => <div>主页</div> const Article = () => <div>文章列表页</div> const ArticleDetail = () => <div>文章详情页</div> export default function App () { return ( <div> <h1>react路由基本使用</h1> <Router> <NavLink to="/">主页</NavLink> <NavLink to="/article">文章列表页</NavLink> <NavLink to="/article/123">文章详情页-123</NavLink> <hr /> <Route path="/" component={Home} /> <Route path="/article" component={Article} /> <Route path="/article/123" component={ArticleDetail} /> </Router> </div> ) } ReactDom.render(<App />, document.getElementById('root'))
exact
<Route path="/" exact component={Home} />
小结
- path 的说明
- 默认情况下,/能够匹配任意/开始的路径
- 如果 path 的路径匹配上了,那么就可以对应的组件就会被 render
- exact , exact 表示精确匹配某个路径
- 一般来说,如果路径配置了 /, 都需要配置 exact 属性