history和hash详解

一、history window.history(可直接写成history)指向History对象,它表示当前窗口的浏览历史。History对象保存了当前窗口访问过的所有页面网址 1. length history.length属性保存着历史记录的url数量,初始时该值为1,如果当前窗口先后访问了三个网址,那么history对象就包括3项,history.length=32.跳转方法:允许在浏览器历史之间移动 go() 接受一个整数为参数,移动到该整数指定的页面,比如history.go(1)相当于history.forward(),history.go(-1)相当于history.back(),history.go(0)相当于刷新当前页面back() 移动到上一个访问页面,等同于浏览器的后退键,常见的返回上一页就可以用back(),是从浏览器缓存中加载,而不是重新要求服务器发送新的网页forward() 移动到下一个访问页面,等同于浏览器的前进键如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是默默的失败3.history.pushState() 在浏览器历史中添加记录 if(!!(window.hostory && history.pushState)) { // 支持History API} else { // 不支持}以上代码可以用来检查当前浏览器是否支持History API。如果不支持的话可以考虑使用Polyfill库History.jshistory.pushstate()方法接受三个参数,以此为: state: 一个与指定网址相关的状态对象,popState事件触发时,该对象会传入回调函数,如果不需要这个对象,此处可填nulltitle: 新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填nullurl: 新的网址,必须与当前页面处在同一个域,浏览器的地址栏将显示这个网址假定当前网址是example.com/1.html,我们使用pushState方法在浏览记录(history对象)中添加一个记录 var stateObj = {foo:'bar'};history.pushState(stateObj,'page 2','2.html')添加上边这个新纪录后,浏览器地址栏立刻显示example.com/2.html,但不会跳转到2.html,甚至也不会检查2.html是否存在,它只是成为浏览历史中的新纪录。这时,你在地址栏输入一个新的地址,然后点击了后退按钮,页面的url将显示2.html;你再点击以此后退按钮,url将显示1.html总之,pushState方法不会触发页面刷新,只是导致了history对象发生变化,地址栏会有反应。如果pushState的url参数,设置了一个新的锚点值(即hash),并不会触发hashChange事件,如果设置了一个跨域网址,则会报错。 //报错history.pushState(null,null,'https://twitter.com/hello')上边代码中,pushState()想要插入一个跨域的网址,导致报错,这样设计的目的是防止恶意代码让用户以为他们是在另一个网站上 4. history.replaceState()history.replaceState()方法的参数和pushState()方法一摸一样,区别是它修改浏览器历史当中的记录假定当前页面是example.com/example.html history.pushState({page:1},'title 1','?page=1')history.pushState({page:2},'title 2','?page=2')history.replaceState({page:3},'title 3','?page=3')history.back() //url显示为example.com/example.html?page=1history.back() //url显示为example.com/example.htmlhistory.go(2) //url显示为example.com/example.html?page=35. history.state属性history.state返回当前页面的state对象 history.pushState({page:1},'title 1','?page=1')history.state //{page:1}5. popState 事件每当同一个文档的浏览历史(即history)出现变化时,就会触发popState事件需要注意:仅仅调用pushState方法或replaceState方法,并不会触发该事件,只有用户点击浏览器后退和前进按钮时,或者使用js调用back、forward、go方法时才会触发。另外该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件不会被触发使用的时候,可以为popState事件指定回调函数 window.onpopstate = function (event) { console.log('location: ' + document.location); console.log('state: ' +JSON.stringify(event.state));};// 或者window.addEventListener('popstate', function(event) { console.log('location: ' + document.location); console.log('state: ' + JSON.stringify(event.state));});回调函数的参数是一个event事件对象,它的state属性指向pushState和replaceState方法为当前url所提供的状态对象(即这两个方法的第一个参数)。上边代码中的event.state就是通过pushState和replaceState方法为当前url绑定的state对象这个state也可以直接通过history对象读取history.state注意:页面第一次加载的时候,浏览器不会触发popState事件 ...

June 6, 2019 · 2 min · jiezi

前端路由笔记

前端路由的实现本质:检测URL变化,获取url地址,解析url匹配页面; 检测URL变化有两种方式: hash,HTML5 HistoryHTML5 History history.pushState 和 history.replaceState这两个api都分别接收三个参数:状态对象,标题, url(此url地址不支持跨域,跨域会报错) 这两个API都会操作浏览器的历史记录,并不引起浏览器的刷新,pushState会增加一条新的历史记录,replaceState会替换当前的历史记录; popstate事件,需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮,或者在Javascript代码中调用3.back()。 原理在点击某个路由时执行pushState,在操作浏览器时执行popstate;hash location.hash window.location修改hash至不会引起页面刷新,而是当作新页面加到历史记录中。hash值变化会触发hashchange事件。Function Router(){ this.currentUrl = ‘’; this.routes = {};}Router.prototype.route = function(url, callback){ this.routes[url] = callback || function(){}}Router.prototype.refresh = function(){ this.currentUrl = location.hash.slice(1) || ‘/’; this.routesthis.currentUrl;}Router.prototype.init = function(){ window.addEventListener(’load’, this.refresh.bind(this), false); window.addEventListener(‘hashchange’, this.refresh.bind(this), false);}//使用var $target = $(’#target’);var route = new Router();route.init();route.route(’/’, $target.html(’this is index page!!’) );route.route(’/page1’, $target.html(’this is page1!!’));

February 27, 2019 · 1 min · jiezi

history对象详解及单页面路由实现

history对象保存着用户的上网记录,从浏览器窗口打开的那一刻算起。出于安全的考虑,开发人员无法得知用户浏览过的URL。不过,借由用户访问过的页面列表,同样可以在不知道实际URL的情况下实现后退与前进一、history对象的方法go(Stirng|number)使用go方法可以在用户的历史记录中任意跳转,可以向后也可以向前。这个方法接受一个参数,表示向后或向前跳转的页面数的一个整数值。负数表示向后跳转(类似浏览器的后退按钮),正数表示向前跳转(类似浏览器的前进按钮)。来看下例子//后退一页history.go(-1)//前进一页history.go(1)//前进两页history.go(2)也可以给go()方法船体一个字符串参数,此时浏览器会跳转到历史记录中包含改字符串的第一个位置,可能后退也可能前进,具体要看哪一个位置最近。如果历史记录中不包含该字符串,则什么都不做。例如://跳转到最近的wrox.com页面history.go(“wrox.com”)//跳转到最近的douban.cn页面history.go(“douban.cn”)back()和forward这两个方法可以来代替go(),模仿浏览器的后退和前进功能back()相当于 go(-1) 后退一个页面forward相当于go(1) 前进一个页面注:接下来几个方法是html5新增的方法二、html5中history新增的方法pushState(state,title,url)该方法的作用是 在历史记录中新增一条记录,改变浏览器地址栏的url,但是,不刷新页面。pushState对象接受三个参数,state:一个与添加的记录相关联的状态对象,主要用于popstate事件。该事件触发时,该对象会传入回调函数。也就是说,浏览器会将这个对象序列化以后保留在本地,重新载入这个页面的时候,可以拿到这个对象。如果不需要这个对象,此处可以填null。title:新页面的标题。但是,现在所有浏览器都忽视这个参数,所以这里可以填空字符串。url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。举个例子,假设当前网址是hello.com/1.html,使用puchState()方法在浏览记录中添加一个新纪录var stateObj={foo:‘bar’}history.pushState(starteObj,’’,‘2.html’)添加新纪录后,浏览器的地址栏立刻显示`hello.com/2.html,但不会跳转到2.html,也不会检查2.html是否存在,它只是成为浏览历史中的最新记录。总之,pushState()方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应,使用该方法后,就可以使用history.state属性读出状态对象var stateObj={foo:‘bar’}history.pushState(starteObj,’’,‘2.html’)history.state //=> {foo:“bar”}注意:如果pushState的URL参数设置了一个新的hash值,并不会触发hashchange事件。replaceState(state,title,url)replaceState方法的作用是替换当前的历史记录,其他的都与pushState()方法一模一样。假定当前网页是example.com/example.html。history.pushState({page: 1}, ’title 1’, ‘?page=1’)// URL 显示为 http://example.com/example.html?page=1history.pushState({page: 2}, ’title 2’, ‘?page=2’);// URL 显示为 http://example.com/example.html?page=2history.replaceState({page: 3}, ’title 3’, ‘?page=3’);// URL 显示为 http://example.com/example.html?page=3history.back()// URL 显示为 http://example.com/example.html?page=1history.back()// URL 显示为 http://example.com/example.htmlhistory.go(2)// URL 显示为 http://example.com/example.html?page=3三、popstate事件popstate事件是window对象上的事件,配合pushState()和replaceState()方法使用。当同一个文档(可以理解为同一个网页,不能跳转,跳转了就不是同一个网页了)的浏览历史出现变化时,就会触发popstate事件。上面我们说过,调用pushState()或者replaceState()方法都会改变当前的历史记录,仅仅调用pushState()方法或replaceState()方法 ,并不会触发该事件,另外一个条件是用户必须点击浏览器的倒退按钮或者前进按钮,或者使用js调用history.back()或者history.forward()等方法。所以,记住popstate事件触发的条件1. 处在同一个文档(同一个html页面)2. 文档的浏览历史(即history对象)发生改变只要符合这两个条件,popstate事件就会触发具体例子//index.html<head> <script> window.onpopstate=function(){ alert(’location ‘+document.location+’,state ‘+JSON.stringify(event.state)) } </script></head><body> <!–第二步 –> <button onclick=“window.history.back()">后退</button> <button onclick=“window.history.forward()">前进</button> <!–第一步 –> <button onclick=“window.history.pushState(null,’’,‘1.html’)">pushState</button> </body>先点击pushState按钮,在点击后退按钮,就会触发popstate事件再来一个例子//index.html<head> <script> window.onpopstate=function(){ alert(’location ‘+document.location+’,state ‘+JSON.stringify(event.state)) } </script></head><body> <a href="#one”>#one</a> </body>直接点击a标签,也可以触发popstate事件四、浏览器兼容性图片来自mdn传送门五、单页面路由原理前端路由的本质是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新。目前单页面使用的路由就只有两种实现方式hash模式history模式hash模式www.test.com/##/就是Hash URL,当##后面的哈希值发生变化时,不会向服务器请求数据,可以通过hashchange事件来监听到URL的变化,从而进行跳转页面网上偷来的一张图:history模式history模式相比hash模式更美观,需要用到Html5新增的几个api实现,原理如下:继续偷图:五、实例,使用history api实现简单的单页面路由在介绍实例前先介绍下location对象,location对象提供了与当前窗口中加载的文档有关的信息。它包含以下属性:属性名例子说明hostwww.hello.com:8080返回服务器名称和端口号(如果有的话)hostnamewww.hello.com返回服务器名称,不带端口号hrefhttp://www.hello.com返回当前加载页面的完整urlpathname/user/ming返回url中的目录hash#content返回url中的hash,如果没有返回空字符串search?q=javascript返回Url的查询字符串,这个字符串以问号开头我们在下方的示例中需要用到pathname属性拿到访问的路径一个简单的history模式单页面路由实现如下://1. 路由规则const routes={ ‘/user’:user, //user是引入的视图 import user from ‘./view/user’ ‘/about’:about}//2. 路由控制类class Router { start() { // 点击浏览器后退/前进按钮时会触发window.onpopstate事件, 我们在这时切换到相应页面 // https://developer.mozilla.org/en-US/docs/Web/Events/popstate window.addEventListener(‘popstate’, () => { this.load(location.pathname) }) // 打开页面时加载当前页面 在单页面入口文件中要调用start方法 this.load(location.pathname) } // 前往path, 变更地址栏URL, 并加载相应页面 go(path) { // 变更地址栏URL history.pushState({}, ‘’, path) // 加载页面 this.load(path) } // 加载path路径的页面 load(path) { // 首页 if (path === ‘/’) path = ‘/foo’ // 创建页面实例 const view = new routespath // 调用页面方法, 把页面加载到document.body中 view.mount(document.body) }}Router类的作用是控制页面根据当前Url切换start()作用1: 监听onpopstate事件,在浏览器前进或后退时加载相应的页面作用2: 打开页面时加载当前页面,需要在单页面的入口文件引入,并执行go(path)跳转到path对应的页面load(path)加载path路径的页面参考链接高程三 p215(history对象) p207(location对象)JavaScript标准参考教程-阮一峰interviewMap ...

February 20, 2019 · 1 min · jiezi