Web开发中路由实现原理html
什么是路由:前端
根据不一样的url地址,展现不一样的页面或者更新页面局部视图
Demogit
服务器端路由管理,常见的开发模式是前端根据url的不一样,使用ajax发起异步请求,获取不一样的页面资源,前端获取资源后更新页面。github
后端路由处理,通常是基于先后端没有分离的项目,html和数据绑定发生在后端(后端渲染),有利于SEO,由于每次发送请求都须要获取资源,对服务器形成资源浪费,前端页面可能由于网速形成延迟,页面局部视图更新,ajax请求不一样保存当前的请求状态,不能使用浏览器前进后退快捷键操做。web
server路由处理实现相似于下面实现:不一样的url请求路径,返回不一样的模板ajax
app.get('', function (req, res) { res.header('Access-Control-Allow-Origin', '*'); res.sendFile( __dirname + "/" + "index.html" ); }) app.get('/home.html', function (req, res) { res.header('Access-Control-Allow-Origin', '*'); res.sendFile( __dirname + "/" + "pages/home.html" ); }) app.get('*', function (req, res) { res.header('Access-Control-Allow-Origin', '*'); res.sendFile( __dirname + "/" + "pages/404.html" ); })
Demosegmentfault
在单页面(SPA)开发中,经过Hash能够实现前端路由,hash路由形如:http:localhost:8100/#/home,
在url后缀存在#(锚点),用来作页面定位,即根据页面id将该元素所在的区域展现在可视区域,#后面内容的改变不会发送请求到服务器。后端
前端路由须要实现一下:浏览器
原理:
页面hash值能够经过 window.location.hash 属性获取,当url的hash值发生变化,会触发window对象的hashchange事件,经过监听 hashchange 事件,操做 window.location.hash 属性能够实现服务器
Route.js
function Route(params) { if(!params){ console.log("请检查初始化数据") return false; } this.registeredRoute = []; this.contentId = params.contentId; this.routes = params.routes; this.devStatus = params.devStatus || 'none' this.otherRouter = params.otherRouter; this.init(); } Route.prototype = { constructor: Route, init: function() { window.addEventListener('hashchange', (function(event){ var currentHash = location.hash.substring(1) || this.otherRouter; var route = this.routes && this.routes.find(item => item['path'] === currentHash); if(this.devStatus === 'log') { console.log("hash has been changed to:", currentHash) } if(route) { this.activeRoute(); this.render(route) } }).bind(this)) var initEvent = new Event('hashchange'); window.dispatchEvent(initEvent); }, //更新视图 render(route) { if(!$){ console.log("请确保项目正确引入jQuery") return false; } var _routeContent = $(`#${this.contentId}`); if(_routeContent) { var currentView = `<div>current page: ${route['path']}</div> <div>Params:${JSON.stringify(route['params'])} </div> <div>View:${route['component']}</div>`; _routeContent.html(currentView) }else { console.log("请绑定须要更新的视图区域"); } }, //当前激活路由样式 activeRoute() { var _routeList = $(".route") || []; for(var i=0; i< _routeList.length;i++) { var _item = _routeList[i]; var _classList = _item.classList; var _defActice = !location.hash && _aDome['context'].getAttribute('data-route-param')==='home'); var _aDome = $(_item.getElementsByTagName("a") && $(_item.getElementsByTagName("a")[0]); var _activeBool = _aDome['context'].getAttribute('data-route-param') === location.hash.substring(1) || _defActice; if(_activeBool) { _classList.add('active') } else { _classList.remove('active'); } } } }
index.html 片断
<div id="route-content"></div> <script> window.onload = function(){ //路由列表 var routes = [ { path:'home', params: { id:1 }, component: '<dev>home page </dev>' }, { path:'list', params: { id:2 }, component: '<dev>list page </dev>' }, { path:'about', params: { id:3 }, component: '<dev>about page </dev>' }, { path:'info', params: { id:4 }, component: '<dev>info page </dev>' } ]; var _routeContent = $("#route-content"); if(!_routeContent) { console.log("请检查是否存在#route-content视图区域") } var route = new Route({ contentId: 'route-content', routes: routes, //路由集合 otherRouter: 'home',//默认路由 devStatus: 'log' //设置开发模式 }); } </script>
window.history (window是浏览器的全局对象,因此window.history和history相同)是浏览器提供的用来记录和操做浏览器页面历史栈的对象的接口,提供了经常使用的属性和方法:
history.back(); //回退 history.go(-1); //等同于history.back(); history.forward(); //前进 history.go(1); //等同forward() window.history.length; //历史栈页面的数量
H5对History进行了扩展,增长了两个重要的新的方法:
History.pushState() //浏览器历史记录压栈,增长一条历史记录 History.replaceState() //浏览器历史记录最后一条数据更新,替换当前历史记录
操做pushState和replaceState方法会触发popstate事件,页面刷新不一样浏览器事件监听存在差别,Chrome和Safari会触发popstate事件,Firefox不会触发。
咱们能够经过pushState(),replaceState()记录和更新当前url和参数;
pushState(),replaceState()包含三个参数:
state:存储当前参数的JSON title:短标题,浏览器实现不统一有些fireFox会直接忽略,能够设置为null作占位, url:当前url,更新浏览器url的值