[深入11] 前端路由
文章图片
导航
[[深入01] 执行上下文](https://juejin.im/post/684490...
[[深入02] 原型链](https://juejin.im/post/684490...
[[深入03] 继承](https://juejin.im/post/684490...
[[深入04] 事件循环](https://juejin.im/post/684490...
[[深入05] 柯里化 偏函数 函数记忆](https://juejin.im/post/684490...
[[深入06] 隐式转换 和 运算符](https://juejin.im/post/684490...
[[深入07] 浏览器缓存机制(http缓存机制)](https://juejin.im/post/684490...
[[深入08] 前端安全](https://juejin.im/post/684490...
[[深入09] 深浅拷贝](https://juejin.im/post/684490...
[[深入10] Debounce Throttle](https://juejin.im/post/684490...
[[深入11] 前端路由](https://juejin.im/post/684490...
[[深入12] 前端模块化](https://juejin.im/post/684490...
[[深入13] 观察者模式 发布订阅模式 双向数据绑定](https://juejin.im/post/684490...
[[深入14] canvas](https://juejin.im/post/684490...
[[深入15] webSocket](https://juejin.im/post/684490...
[[深入16] webpack](https://juejin.im/post/684490...
[[深入17] http 和 https](https://juejin.im/post/684490...
[[深入18] CSS-interview](https://juejin.im/post/684490...
[[深入19] 手写Promise](https://juejin.im/post/684490...
[[深入20] 手写函数](https://juejin.im/post/684490...
[[react] Hooks](https://juejin.im/post/684490...
【[深入11] 前端路由】[[部署01] Nginx](https://juejin.im/post/684490...
[[部署02] Docker 部署vue项目](https://juejin.im/post/684490...
[[部署03] gitlab-CI](https://juejin.im/post/684490...
[[源码-webpack01-前置知识] AST抽象语法树](https://juejin.im/post/684490...
[[源码-webpack02-前置知识] Tapable](https://juejin.im/post/684490...
[[源码-webpack03] 手写webpack - compiler简单编译流程](https://juejin.im/post/684490...
[[源码] Redux React-Redux01](https://juejin.im/post/684490...
[[源码] axios ](https://juejin.im/post/684490...
[[源码] vuex ](https://juejin.im/post/684490...
[[源码-vue01] data响应式 和 初始化渲染 ](https://juejin.im/post/684490...
[[源码-vue02] computed 响应式 - 初始化,访问,更新过程 ](https://juejin.im/post/684490...
前置知识
URL 和 URI
- URI:统一资源标识符 ( I => Identifier:标识符Id)
(Universal Resource Identifier
- URL:统一资源定位符 ( L => Locator:定位器)
Uniform Resource Locator
- 区别:
- URL:强调的是地址,即( 定位 )这个唯一的资源
- URI:强调的是( 标识 )资源,资源具有的( 唯一性 )
分别标识唯一资源和标识唯一地址很麻烦,所以用URL也充当RUI的角色,即标记唯一资源还标记该资源的唯一地址
http://www.baidu.com:80/stu/index.html?name=xxx&age=25#teacher
- Protocol:协议
http://
,https://
- Domain:域名
www.baicu.com
- Port:端口
:80
- http协议的默认地址是 :80
- https自已的默认地址是:443
- Path:文件路径, =>
/开始 ?之前的部分
, 本例中是:/stu/index.html
- Query:查询字符串 =>
?开头到结尾,或者?开头到#之前
,本例是:?name=xxx&age=25
- Hash:哈希值 =>
#开头到结尾
,本例是:teacher
- protocol,domain,port,path,query,hash
- window.onload
window.addEventListener('load', ....)
- DOMContentLoaded
- 区别:
- DOMContentLoaded:DOM加载完成时触发
- load:需要DOM,样式,脚本,图片,视频等所有资源都加载完成时才会触发,即页面加载完成才触发
DOM完整解析过程:
- 解析html
- 解析css - 包括当html中的样式和外部引入的样式
- 解析并运行脚本 - 报错本html中的脚本和外部引入的脚本
- DOM构建完成 ---------------------------------------------------- DOM加载完成,触发 DOMContentLoaded
- 加载图片,视频等其他资源
- 页面加载完毕 --------------------------------------------------- 页面加载完成,触发 load
// 2021/07/25更新 - 上面的过程不完善,这里再简单记录下
// - 详见https://juejin.cn/post/698357...
- parse-html
- parse-styleSheet
- evaluate-script
- layout
- paint
- composite
- slice可用于 ( 数组 ) 和 ( 字符串 )
- 有返回值,不改变原字符串
- String.prototype.slice(开始位置,结束位置) 截取字符串,不包括结束位置
String.prototype.slice()特例: ''.slice(1) ----------- 返回 '' 空字符串案例: window.location.hash // 因为:当地址栏的url中的hash不存在时,window.location.hash返回的是空字符串,这种情况如下 // 所以:window.location.hash.slice(1) => 返回空字符串
window.location 对象属性:
pathname: 返回url的path部分,/开始 ?之前 或者 /开始到结果,如果没有query和hash
origin:protocal + hostname + port 三者之和,相当于协议,域名,端口
protocal:协议 http:// https://
hostnme: 主机名
port:端口号
host:主机 (hostname + port)
search:查询字符串 (?开头到#之前,或者?开头到结尾)
hash:片段字符串 (哈希值,#开头到结尾)返回值:
- window.location返回的是一个只读的Location对象,你仍然可以赋给它一个 DOMString
- 这意味着您可以在大多数情况下处理 location,就像它是一个字符串一样
- window.location = 'http://www.example.com',是 window.location.href = 'http://www.example.com'的同义词问题:
- window.location.assign() 和 window.location.href 的区别?
- location.assign(url)是函数式的方式
- window.location.href=https://www.it610.com/article/url 比 location.assign(url) 更快
hash路由
- url中的hash以#号开头,原本用来作为锚点,从而定位到页面的特定区域
- 当 hash 发生改变时,页面不会刷新,浏览器也不会向服务器发送请求
- 注意:hash改变时,可以触发 hashchange 事件,在监听函数中可以请求数据,实现页面的更新操作
锚点1
锚点2锚点1的位置
锚点2的位置说明:
- 点击a2,页面会跳转到div2的位置
- 并且页面的hash部分也会改变,即 url 中以 #开头的字符串会改变
- anchor:是锚的意思- 注意:a标签的name属性已经废弃,用id代替 (因为有的教程使用name属性实现的)
hashchange事件
- 如果监听了hashchange事件,hash改变,地址栏的url中的hash部分就会改变,同时hashchange也会触发
- 但是页面不会刷新,即浏览器的刷新按钮的圈圈不会转动
- 但是可以利用hashchange的回调函数更新页面的内容,注意不是页面刷新
锚点1 锚点2
- 点击a标签,url中的hash改变,hash改变,hashchange事件触发,则监听函数就会执行,输出111111
hash-router原理:
(1) hash改变,地址栏url的hash字符串改变,触发hashchange事件
(2) 在hashchange事件的回调函数中更新视图代码:
Document - 锐客网
home
other
内容部分
2020/12/24复习 - hash路由
Document - 锐客网
home页面
other页面
内容部分,即路由替换的部分
2021/07/25优化 - hash路由
Document - 锐客网
home页面
other页面
内容部分,即路由替换的部分
history路由 window.history 对象
- window.history对象的方法:
back()
,forward()
,go()
,pushState()
,replaceState()
- pushState()
- replaceState()
- pushState() 和 replaceState()
- 不会触发页面刷新,只能导致History对象发生变化,地址栏的url会变化
- 会改变url,不会触发 popstate 事件,地址栏的url有所变化
- window.history.pushState(state, title, url)
- state:一个与添加的记录相关联的对象
- title:新页面的标题,现在所有浏览器都忽略该参数,可以传入空字符串
- url:新的url地址,必须与当前页面同一个域,浏览器的地址栏显示这个网址
window.history.pushState({}, null, url)
- 注意:pushState不会刷新页面,只会改变History对象,地址栏url会变化
- 可以通过 History.state 读取状态对象
- popstate触发的条件
- 浏览器的前进后退按钮
- history.go(), history.back(), history.forward()
- 注意:window.history.pushState() 和 window.history.replaceState()不会触发 popstate 事件
- 注意:pushState()和replaceState()可以改变url,且实现不向服务器发送请求,不存在#号,比hash路由更美观,但是 History 路由需要服务器的支持,并且需将所有的路由重定向到根页面
原理分析
- 第一步:给每个a标签都绑定一个click事件,click事件触发时,再去触发pushState()事件,将url的path部分改变为a的data-href自定义属性的值即路由的path,传入window.history.pushState({}, null, path),这样地址栏的url就改变了
- 第二步:改变地址栏的url后,通过window.location.pathname获取更新的url的path部分
- 第三步:用 path 和 route对象中的key去匹配,匹配上就去执行更新视图的函数
- 第四步:
这只是一条线:1-3步即点击a标签的情况
还有一条线:浏览器的前进后退,和函数式导航go() back() forward() 则有 popstate 事件来处理,过程差不多
history-router原理: (1) 封装一个方法,在pushState()和replaceState()改变url后调用,在该方法中获取最新的window.location.path,更相信页面 (2) 通过 go() back() forward() 浏览器前进后退等触发 popstate 事件代码:
Document - 锐客网 home // html中的自定义属性 other content的内容注意:该html需要用 Live Server 启动,vscode插件,来提供server
Document - 锐客网
点击去home页面
点击去other页面
内容部分,即路由要替换的内容注意:该html需要用 Live Server 启动,vscode插件,来提供server
2021/07/25优化 - history路由
Document - 锐客网
home
other
content注意:该html需要用 Live Server 启动,vscode插件,来提供server
手动实现一个vue-router(hash版)
- 原理
- 大体的原理和hash路由的html版本一样,微小区别
- 都是利用 ( a标签 ) 的 ( href ) 中的 ( '#/xxx' ) 这样的hash串
- 只要点击 a标签 => 地址栏的url的hash部分就会改变 => 同时触发 hashchange 事件 => 通过window.location.hash获取最新的hash
- 获取到 hash 在和 routeMap 中的path匹配,匹配后就改变视图
- 区别
- 区别就是 Vue 自己封装了
和
组件 - 可以通过 Vue.component() 方法注册上面两个组件
- 通过
vm.name 可以访问到 new Vue({data: {name: xx}})中的name
手动实现一个vue-router(hash版)
- 区别就是 Vue 自己封装了
home // 点击会跳转到 '#/home' 地址// 路由将显示的DOM位置
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: ''
})
- 因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项
- 例如 data、computed、watch、methods 以及生命周期钩子等。
Document - 锐客网
home
other
URI和URL的区别举例(很形象)https://juejin.im/post/684490...
URL的组成(优秀)https://www.jianshu.com/p/406...
DOMContentLoaded和load的区别:https://www.jianshu.com/p/1a8...
window.location对象:https://wangdoc.com/javascrip...
vue-router模拟实现 https://juejin.im/post/684490...
hash history 路由 模拟实现 https://juejin.im/post/684490...
vue-router源码记录 https://juejin.im/post/684490...
VueRouter源码分析 https://juejin.im/post/684490...
推荐阅读
- 深入理解Go之generate
- 【1057快报】深入机关,走下田间,交通普法,共创文明
- 生发知识,带你深入了解
- Jsr303做前端数据校验
- 深入理解|深入理解 Android 9.0 Crash 机制(二)
- 深入浅出谈一下有关分布式消息技术(Kafka)
- 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件
- 前端代码|前端代码 返回顶部 backToTop
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- 前端自学笔记01