21.框架通识-路由

单页面应用原理 单页面应用的特征,说穿了就是两点:
1.通过 js 能够改变浏览器地址栏的地址,然后页面也跟着改变,但是不会重新加载页面。
想通过 js 能够改变浏览器地址栏的地址,很简单,比如对location.href,或者location.pathname进行赋值,但这会导致浏览器会重新加载一个目标页面。要想不重新加载页面有两种方式:一是对 location.hash 进行赋值,二是使用 histrory 对象的 pushState 或 replaceState 方法。还剩最后一个问题,如何让页面也跟着改变?如果我能监听到地址栏变化,然后调用函数(比如叫updateView)更新页面就行了。
如:

window.onTheUrlChange = function updateView() {}

如果不能监听到的话,那直接在改变地址栏后,再去调用updateView也行。
function toggleRoute() { changeURL(); updateView(); }

幸运的是,还真能监听到地址栏变化。
window.onhashchange、window.onpopstate这两个api,不仅能监听到对location.hash的赋值,或者调用histrory.pushState\histrory.replaceState导致的地址栏改变,而且还能监听到浏览器前进、后退按钮带来的地址栏改变,或者history.go(-1)之类的,总之,只要是地址栏的改变,都能被捕获。
2.能恢复刷新前的页面
window.onhashchange、window.onpopstate有个小问题,刷新页面时两者都不会被触发。但是刷新又天然的会重新加载页面,导致刷新前的页面丢失。比如我们自应用首页进入了about页面,此时刷新浏览器,页面被重新加载,所以我们又回到了首页。这时候可以用load事件,根据当前url中的信息,知道应该渲染的是about。所以调用updateView('about')就行。
路由的实现方式 url的组成部分:
http:127.0.0.1:80/main/doc?lang=cn#part/1
协议 | 主机地址 | 端口 | 路径(pathname) | search | hash
pathname部分(/main/doc),刷新时会被带进重新请求的url中
hash部分(part/1),刷新时会被忽略掉
所以刷新后的请求url是http:127.0.0.1:80/main/doc?lang=cn
方式一:hash 模式
location.hash + hashchange
【21.框架通识-路由】原理:通过location.hash 改变地址栏hash,监听地址栏hash变化,更新视图
  • 当点击导航元素时,对location.hash进行赋值,触发hashchange
  • 当点击浏览器前进后退按钮时,触发hashchange
  • 当手动改变地址栏然后enter时以及当F5刷新时,hash部分,不会被加入到请求路径中,(如http:127.0.0.1:80/main/doc?lang=cn#part/1刷新,浏览器发送请求url是http:127.0.0.1:80/main/doc?lang=cn
    无法监听到hashchange事件,则通过load事件来更新视图
$('.btn').click(function() { location.hash = 'user' })window.onhashchange = function() { $('router-outlet').html(user-template) }window.onload = function() { const path = location.hash; const template = getTemplate(path); $('router-outlet').html(template) }

?
方式二:history模式
history.pushState() + popstate
因为history模式,路由信息部分是加到url的pathname部分的,所以刷新时,路由信息会被添加到请求中,如果服务端不处理,会导致404,所以需要服务端配合重定向。只要收到对某个路由的请求,统一返回index.html。
$('.btn').click(function() { let data = https://www.it610.com/article/{name:'张三'}; history.pushState(data, '', 'user/zhangsan'); $('router-outlet').html(template) })window.onpopstate = function() { $('router-outlet').html(user-template) }// 后端重定向后需要 window.onload = function() { const path = location.pathname; const template = getTemplate(path); $('router-outlet').html(template) }

框架路由的一些共同点(ngjs\ng\vue) 1.多视图,可以有多个路由容器
2.路由嵌套,可以层层嵌套
3.路由参数,参数都有三种形式
  • 动态路由参数,出现在url的pathname部分
  • params
  • query ,出现在url的search部分
4.路由守卫

    推荐阅读