You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importReactfrom"react";import{BrowserRouterasRouter,Route,Link}from"react-router-dom";constBasicExample=()=>(<Router><div><ul><li><Linkto="/">Home</Link></li><li><Linkto="/about">About</Link></li><li><Linkto="/topics">Topics</Link></li></ul><hr/><Routeexactpath="/"component={Home}/><Routepath="/about"component={About}/><Routepath="/topics"component={Topics}/></div></Router>);constHome=()=>(<div><h2>Home</h2></div>);constAbout=()=>(<div><h2>About</h2></div>);constTopics=({ match })=>(<div><h2>Topics</h2><ul><li><Linkto={`${match.url}/rendering`}>Rendering with React</Link></li><li><Linkto={`${match.url}/components`}>Components</Link></li><li><Linkto={`${match.url}/props-v-state`}>Props v. State</Link></li></ul><Routepath={`${match.url}/:topicId`}component={Topic}/><Routeexactpath={match.url}render={()=><h3>Please select a topic.</h3>}/></div>);constTopic=({ match })=>(<div><h3>{match.params.topicId}</h3></div>);exportdefaultBasicExample;
全文目录结构如下
<Route>
剖析<Link>
剖析<Route>
组件:pushState
和replaceState
不会触发onpopstate
事件matchPath
方法一、浏览器 history和hash
Hash
location.hash的值是url中#后面的内容
比如
https://www.google.com/#amandakelake
的hash值为amandakelake
hash发生变化的url都会被浏览器记录下来,所以浏览器的前进后退都可以用
特点:
1、改变 url 的同时,不刷新页面,hash是用来指导浏览器行为的,对服务端是无用的,所以不会包括在http请求中,所以可以随意刷新
2、浏览器提供了
onhashchange
事件来监听hash的变化history
Manipulating the browser history - Web API 接口 | MDN
HTML5中history对象上新的API
通过
pushState()
或replaceState()
可以修改url的地址两者区别在于:
pushState
会改变history.length
,而replaceState
不改变history.length
注意:无论是
replaceState()
方法还是pushState()
方法,其更新或添加会话历史记录后,改变的只是浏览器关于当前页面的标题和URL的记录情况,并不会刷新或改变页面展示,所以不会触发onpopstate
事件popstate事件
每当活动的历史记录项发生变化时, popstate 事件都会被传递给window对象,popstate 事件的状态属性 state 会包含一个当前历史记录状态对象的拷贝
注意:
pushState
和replaceState
不会触发onpopstate
事件,只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()
)history模式的问题
虽然丢掉了#,不怕浏览器的前进和后退,但是页面怕刷新,会把请求发送到服务器,但如果没有对应的资源,就会404。而hash则没有这个问题,因为浏览器请求不带它玩。
reload()、replace()、location直接赋值三者区别
location.reload()
会取客户端的缓存页面location.replace(url)
总是重新请求加载url指向的页面location.href = url
等效于使用pushState()
修改URL,会创建一条新会话记录二、简单hash router实现
三、简单 history 路由实现
hash 的改变可以触发
onhashchange
事件,而 history 的改变并不会触发任何事件,这让我们无法直接去监听 history 的改变从而做出相应的改变。换个思路
罗列出所有可能触发 history 改变的情况,并且将这些方式一一进行拦截,变相地监听 history 的改变
对于一个应用而言,url 的改变(不包括 hash 值得改变)只能由下面三种情况引起:
onpopstate
事件history.push(replace)State
函数history路由跟上面的hash类似,区别在于 init 初始化函数,首先需要获取所有特殊的链接标签,然后监听点击事件,并阻止其默认事件,触发 history.pushState 以及更新相应的视图
四、Build your own React Router v4
到目前为止,我们已经大概知道了hash路由和history路由的原理,以及如何构建简单的Router,下面让我们跟着一篇国外好文来尝试构建自己的react router v4
Build your own React Router v4这篇文章真的巨好,炒鸡推荐
1、React Router v4 基础使用
首先去React Router v4 官方文档熟悉一下API ,起码得先知道
<Route>
、<Link>
的概念这是官网的第一个例子
2、
<Route>
剖析首先看
<Route>
的使用这里有三个属性,那么这个组件的属性应该是这样的
如果不返回componnet,那么
<Route>
还有第二种用法,直接render UI那么,应该还有一个属性
render
然后还需要一个能匹配url的功能性函数
matchPath
,稍后再定义这个函数,先把<Route>
这个组件写出来,看注释应该很好理解在客户端,对用户来说,有两种方式更新url
onClick
劫持a标签,跟踪所有Route
并在路由改变的时候调用forceUpdate
更新页面<Route>
组件监听popstate
事件,调用forceUpdate
更新页面先看个简单的,点击前进后退按钮的处理,a标签稍后再说
在
componentWillMount
的时候添加事件监听即可,在上面的Route组件中增加如下代码即可到目前为止,
<Route>
组件已经解决了监听前进后退按钮的问题3、
<Link>
剖析再来看下a标签的处理,主要的做法是通过
onClick
劫持a标签,跟踪所有Route
并在路由改变的时候调用forceUpdate
更新页面而我们的
<Link>
组件其实就是包装过的a标签它有两个属性,to和replace,然后还得返回一个a标签,我们仿照上面的
<Route>
组件来写一下demo定义好
<Link>
的基础框架后,我们来考虑一下url如何跳转的问题这里直接用HTML5的原生API:
pushState
、replaceState
pushState 和 replaceState 都接收三个参数。
定义好两个方法
这时候的
<Link>
变成这样了如果有认真读上面第一部分基础内容的话,这里我们应该能发现一个问题
pushState
和replaceState
不会触发onpopstate
事件(还记得吗?
<Route>
组件只是添加了对popstate
的事件监听,回头翻一下看看?)点击
<Link>
改变URL后,<Route>
组件并不知道已经改变了,所以不知道需要重新匹配和渲染,所以UI也不会刷新那么我们需要跟踪所有
Route
并在路由改变的时候调用forceUpdate
更新页面4、升级
<Route>
组件:pushState
和replaceState
不会触发onpopstate
事件为了使路由简单,我们通过把所有路由对象放到一个数组里的方式来实现
<Route>
跟踪。每当发生地址改变的时候,就遍历一遍数组,调用相应对象的
forceUpdate
函数然后更新组件的两个生命周期函数
还要更新上面定义的
historyPush
和historyReplace
方法到目前为止,只要点击
<Link>
组件,URL发生改变,每个<Route>
组件都会收到消息,进行重匹配和重渲染完美! perfect !!!我们试运行一下,go……
等下!上面好像还有个匹配函数没定义:
matchPath
😢5、定义
matchPath
方法match是一个对象
传入的参数:pathname+一个对象
上面的代码应该比较好理解
6、完整代码
附加增送一个
Redirect
组件,由上面基础应该很好理解了后记
感谢您耐心看到这里,希望有所收获!
如果不是很忙的话,麻烦点个star⭐【Github博客传送门】,举手之劳,却是对作者莫大的鼓励。
我在学习过程中喜欢做记录,分享的是自己在前端之路上的一些积累和思考,希望能跟大家一起交流与进步。
The text was updated successfully, but these errors were encountered: