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

原理:通过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 = {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.路由守卫

你可能感兴趣的:(21.框架通识-路由)