1. 网页利用的倒退
早在 ajax
技术呈现以前,网页的运行模式就是在服务器端写好所有的动态页面,用户通过在浏览器输出不同的 url
,浏览器负责向对应的 url
地址发送申请,服务器端响应申请,将对应的动态页面返回给浏览器,浏览器收到动态页面负责解析后显示给用户。此时的网页利用,用户想要与网页利用进行交互或者进行页面跳转,就必须发送不同的 url
申请失去,也就是说必须刷新浏览器。发送申请和响应申请的频繁操作让用户体验很不好。(页面交互和页面跳转都须要页面刷新)
起初,随着 ajax
技术的呈现,做到了部分异步数据申请而不刷新浏览器。节俭了很多的动态页面的频繁申请,而且 ajax
申请的发送和响应速度比动态页面的要快得多。这样一来,ajax
做到了用户在与页面交互时是无刷新的。(页面交互无刷新,页面跳转有刷新)
ajax
技术尽管极大地改善了用户与网页的交互性,然而,传统的网页利用还是须要向服务器端申请多个动态页面资源,发送申请和响应申请也都须要工夫,在网络不好的状况下,用户体验还是很差。因而就有了起初的 SPA(single page application)单页面利用
。单页面利用的设计思维就是,整个网页利用就只有一个 index.html
动态页面,页面显示内容的切换时通过更新 index.html
页面的 div
容器内的内容来实现的。这样一来,查看内容之间的切换就变成了相似于让 div
容器内的上一个内容暗藏,显示下一个内容这样的模式。当然了,必定不是显示 / 暗藏的设计思维,而是通过 JavaScript
语言全权操作 DOM 元素 的模式更新视图(view = render(model))。把所有的元素都变成了 JS 管制的动静生成的形式,也就不必再频繁地向服务器发送申请了,网页与用户的交互性更强了,访问速度更快了。(页面交互和页面跳转都不须要页面刷新)
SPA 的核心思想就是:更新视图而不从新申请页面
浏览器向服务器发送申请的形式就是刷新页面
2. SPA 与前端路由
SPA 单页面利用尽管是用内容切换的形式代替了页面跳转,然而 SPA 仍旧是依据 url
的扭转来模仿页面跳转的。
那么如何用 url
模仿页面跳转而不让浏览器刷新呢?
这时前端路由就呈现了,专门用于 SPA 单页面利用的,确保扭转 url
的状况下,不让页面刷新。
无论是 Vue 还是 React,只有是 SPA 单页面利用,都须要前端路由。
3. 手动实现一个前端路由管理器
依据 url
的形成可知,当 url
中含 #
时,会被认为是 #
及其前面的内容是用于定位页面内的某一元素的,因而 #
及其前面的内容不会被发送到服务器,也就是说,当 url
中 #
前面的内容扭转时,浏览器不会发送申请,因而就不会进行页面刷新。
因而能够用 url
中 #
前面内容的扭转来让 url
扭转,从而模仿跳转页面。
手动实现一个前端路由器的思路就是匹配不同的 url 门路
,而后动静渲染出对应的 html 内容。
用到的 URL 相干的 Web API 有:window.location.hash、hashchange event
//inde.html
<body>
<a href="#1"> 查看第 1 个页面 </a>
<a href="#2"> 查看第 2 个页面 </a>
<a href="#3"> 查看第 3 个页面 </a>
<a href="#4"> 查看第 4 个页面 </a>
<div id="app"></div>
<script src="./index.js"></script>
</body>
//index.js
const app = document.querySelector("#app")
const div1 = document.createElement('div')
div1.innerHTML = '我是第 1 个页面的内容'
const div2 = document.createElement('div')
div2.innerHTML = '我是第 2 个页面的内容'
const div3 = document.createElement('div')
div3.innerHTML = '我是第 3 个页面的内容'
const div4 = document.createElement('div')
div4.innerHTML = '我是第 4 个页面的内容'
const div404 = document.createElement('div')
div404.innerHTML = '您输出的页面不存在'
const routeTable = {
'1': div1,
'2': div2,
'3': div3,
'4': div4
}
function route(){const hash = window.location.hash.substr(1) || '1' // 保底值为默认路由
let div = routeTable[hash]
if(!div){div = div404}//404 页面
app.innerHTML = ''
app.appendChild(div)
}
route()
window.addEventListener('hashchange',()=>{route()
})
4. 手动欠缺路由器之嵌套路由
上述手写的路由器只是单层的路由,嵌套路由是指,在第一层路由下的一个页面中还有向上层持续跳转的页面。url
要记录残缺的路由信息,因而嵌套路由为如下模式 #1/1
//index.js
const app = document.querySelector('#app')
const div1 = document.createElement('div')
div1.innerHTML = `
<br/>
我是第 1 个页面的内容,我有两个路由
<a href="#1/1"> 查看 1.1 页面 </a>
<a href="#1/2"> 查看 1.2 页面 </a>
`
const div11 = document.createElement('div')
div11.innerHTML = '我是 1.1 页面的内容'
const div12 = document.createElement('div')
div12.innerHTML = '我是 1.2 页面的内容'
const div2 = document.createElement('div')
div2.innerHTML = `
<br/>
我是第 2 个页面的内容,我有两个路由
<a href="#2/1"> 查看 2.1 页面 </a>
<a href="#2/2"> 查看 2.2 页面 </a>
`
const div21 = document.createElement('div')
div21.innerHTML = '我是 2.1 页面的内容'
const div22 = document.createElement('div')
div22.innerHTML = '我是 2.2 页面的内容'
const div3 = document.createElement('div')
div3.innerHTML = '我是第 3 个页面的内容'
const div4 = document.createElement('div')
div4.innerHTML = '我是第 4 个页面的内容'
const div404 = document.createElement('div')
div404.innerHTML = '您输出的页面不存在'
const routeTable = {
'1': div1,
'2': div2,
'3': div3,
'4': div4
}
const routeTable2 = {
'1/1': div11,
'1/2': div12,
'2/1': div21,
'2/2': div22
}
const hashTable = {
1: routeTable,
2: routeTable2
}// 不同的层数对应不同的 routeTable
function route(table){const hash = window.location.hash.substr(1) || '1'
let div = table[hash]
if(!div){div = div404}
app.innerHTML = ''
app.appendChild(div)
}
route(routeTable)
window.addEventListener('hashchange',()=>{const hash = window.location.hash.substr(1) || '1'
const hashArray = hash.split('/')
const table = hashTable[hashArray.length]
route(table)
})
5. 更改路由模式为 history
上述内容是用 hash 的模式实现了前端路由器。所谓的 hash 就是 window.location.hash
取得的以 #
结尾的 url
。hash 模式的路由器的实现依赖的原理就是 url
中 #
前面的内容不会被浏览器发送到服务器,#
前面的内容变动不会引起浏览器的刷新,能够随时批改 #
前面的内容来模仿页面跳转。
hash 模式是所有状况下都能够应用的,然而有一个致命的毛病就是:SEO 不敌对 。为什么会这样呢?那是因为搜索引擎(SEO)的服务器在收录网页信息时是依据一个 url
对应一个页面信息的形式来收录的。这样能力在用户搜寻到页面中的关键字时精确地返回该页面。hash 模式下,无论是 http://localhost:1234/#1
还是 http://localhost:1234/#3/1
,在向后盾发送申请时的 url
都是 http://localhost:1234/
,返回的都是同一个页面,而后通过 JS 文件 批改页面的显示内容。这样一来,在搜索引擎的服务器上存储该 SPA 的永远都是一个页面,就无奈精确地提供相干的搜寻。
在起初的倒退中,Web API 中的 History 接口新增了两个办法,就是 pushState() 和 replaceState(),这两个办法的作用简略来说就是能够让程序员手动随便批改 url
,而不是仅仅像 go() / back() / forward()
这样有限度地批改 url
。而且,这两个办法最神奇的是不会引起浏览器的页面刷新,也就是说不会向后端发动申请。可看如下实例,留神 url 的变动。
因而有了这两个神奇接口的呈现,咱们就能够批改必须带 #
的 SPA 前端路由的场面。具体思路就是,手动拦挡
参考博客
从头开始学习 vue-router
vue-router 应用详情