hash和history

hashhistory
#后的就是hash内容history即正常的路径
可以通过location.hash拿到location.pathname
可以通过onhashchange监听hash的改变可以用onpopstate监听history的变化

hash 模式:
#后面 hash 值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面
通过监听 hashchange 事件可以知道 hash 发生了哪些变化,然后根据 hash 变化来实现更新页面部分内容的操作。

history 模式:
history 模式的实现,主要是 HTML5 标准发布的两个 API,pushState 和 replaceState,这两个 API 可以在改变 url,但是不会发送请求。这样就可以监听 url 变化来实现更新页面部分内容的操作。

区别:
url 展示上,hash 模式有“#”,history 模式没有
刷新页面时,hash 模式可以正常加载到 hash 值对应的页面,而 history 没有处理的话,会返回 404,一般需要后端将所有页面都配置重定向到首页路由
兼容性,hash 可以支持低版本浏览器和 IE。

前端路由中,实现路由的2种机制:history  hash
URL后 #1    hash
路由变化: 
window.location.hash = 1
Let hash = window.location.hash
window.onhashchange = function (e) {
    // 可捕捉URL变化,可实现spa
    console.log(‘旧的’, e.oldURL)
    console.log(‘新的’, e.newURL)
}

浏览器中1改为2,oldURL = 1, newURL = 2
返回键:old URL = 2, newURL = 1
· Hash机制思路(下)兼容性好,可兼容ie8
1 创建路由对象,register处理每个hash对应的回调函数
2 不存在hash时,默认首页,实现index方法,处理首页的回调(不点击任何链接时)
3 通过hashchange监听hash的变化,定义hash变化的回调函数

<!DOCTYPE html>
<html>
<head>
	<title>SPA路由原理与实现方式:hash机制</title>
</head>
<body>
	<div id="nav">
		<a href="#/page1">page1</a>
		<a href="#/page2">page2</a>
		<a href="#/page3">page3</a>
	</div>
	<div id="container"></div>
</body>
<script type="text/javascript">
	/*
	 * 1. 创建一个路由对象,register用于处理每个hash值对应的回调函数
	 * 2. 不存在hash的时候,默认首页。实现一个index方法,用于处理首页的回调函数
	 * 3. 通过hashchange事件来监听hash的变化,定义hash变化的回调函数
	 */
	 function Router () {
	 	// 用于存储不同的hash值对应的回调函数
	 	this.routes = {};
	 	// 监听hashchange
	 	window.addEventListener('hashchange', this.reload.bind(this));
	 }

	 // 首页的回调方法
	 Router.prototype.index = function (callback) {
	 	this.routes['index'] = callback;
	 }

	 // 其他页面的回调方法
	 Router.prototype.register = function (hash, callback) {
	 	this.routes[hash] = callback;
	 }

	 // 实现reload方法
	 Router.prototype.reload = function () {
	 	let callback;
	 	// /page3
	 	let hash = location.hash.slice(1);
	 	!hash ? callback = this.routes.index : callback = this.routes[hash]
	 	callback.call(this)
	 }
	 // 调用
	 let router = new Router();
	 let container = document.getElementById('container');

	 // 首页的回调函数
	 router.index(() => {
	 	container.innerHTML="我是首页";
	 })
	 // 回调函数
	 router.register('/page1', ()=>{
	 	container.innerHTML="我是page1";

	 })
	 router.register('/page2', ()=>{
	 	container.innerHTML="我是page2";

	 })
	 router.register('/page3', ()=>{
	 	container.innerHTML="我是page3";

	 })
	 // 调用
	 router.reload();
</script>
</html>

History 后退:history.go(-1)。history.go(2) 简单的页面跳转
H5新增的两个api:
History.pushstate() 跳转URL且能后退
history.replacestate() 替换URL且不能回退
可改变URL,不会刷新页面,具备实现前端路由的能力,不会出发任何事件,暂时无法监听。history.popstate监听history下的路由变化
变向监听,url可能改变的情况:
1 浏览器前进,后退
2 a标签
3 js中,触发history.replacestate() 和 history.pushstate()

<!DOCTYPE html>
<html>
<head>
	<title>SPA路由原理与实现方式:history机制</title>
</head>
<body>
	<div id="nav">
		<a href="/page1">page1</a>
		<a href="/page2">page2</a>
		<a href="/page3">page3</a>
	</div>
	<div id="container"></div>
</body>
<script type="text/javascript">
	/*
	 * 1. 创建一个路由对象,register location.pathname的值对应回调函数
	 * 2. 处理首页
	 * 3. 处理其他页

	 es5的写法:所有的方法挂在在原型上
	 es6的class 写法
	 */
	 class Router {
	 	constructor () {
	 	 	// 用于存储不同的path值对应的回调函数
	 		this.routes = {};
	 		this.listenPopState()
	 		this.listenLink()
	 	}
	 	// 监听postState,历史记录更改的时候,将触发postState事件
	 	listenPopState () {
		 	window.addEventListener('popstate', (e) => {
		 		let state = e.state || {};
		 		let path = state.path || ''
		 		this.handle(path)
		 	});
	 	}

	 	// a链接的页面跳转
	 	listenLink () {
	 		window.addEventListener('click', (e)=>{
	 			let ev = e.target
	 			if (ev.tagName === 'A' && ev.getAttribute('href')) {
	 				e.preventDefault()
	 				// 更新URL
	 				this.urlRefresh(ev.getAttribute('href'))
	 			}
	 		})
	 	}
		 // load
		 load () {
		 	let path = location.pathname
		 }

		 register (path, cb) {
		 	this.routes[path] = cb
		 	console.log(cb)
		 }

		 // 首页
		 index (cb) {
		 	this.routes['/'] =cb
		 }
		 // 未找到路由
		 notfound (cb) {
		 	this.routes['notfound'] = cb
		 }

		 // 出现异常
		 error (cb) {
		 	this.routes['error'] = cb
		 }

		 // 更新URL
		 urlRefresh (path) {
		 	// 参数,1合理的js对象,2 title 现在浏览器都不要写这个 3,url,跳转的界面
		 	history.pushState({path}, null, path)
		 	this.handle(path)
		 }

		 // 通用的回调函数
		 handle (path) {
		 	let cb
	 		cb = this.routes[path]
	 		cb.call(this)
		 }
	 }

	let router = new Router;
	router.load()
	let container = document.getElementById('container')
	// 处理回调
	// 首页的回调函数
	router.index(() => {
	 	container.innerHTML="我是首页";
	})
	router.register('/page1', ()=>{
		container.innerHTML = '我是page1'
	})
	router.register('/page2', ()=>{
		container.innerHTML = '我是page2'
	})
	router.register('/page3', ()=>{
		container.innerHTML = '我是page3'
	})
</script>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值