简单的基于hash和hashchange的前端路由
hash定義
hash這個玩意是地址欄上#及后面部分,代表網頁中的一個位置,#后面部分為位置標識符。頁面打開后,會自動滾動到指定位置處。
位置標識符 ,一是使用錨點,比如<a name="demo"></a>,二是使用id屬性,比如 <span id="demo" ></span>
帶hash的請求
當打開http://www.example.com/#print服務器實際收到的請求地址是http://www.example.com/,是不帶hash值的。
那么你真想帶#字符咋辦,轉義啊, #轉義字符為%23。也許有人會說,我咋知道這個轉義啊,呵呵噠encodeURIComponent。
hashchange事件
從The HashChangeEvent interface可以看到hashchange事件的參數HashChangeEvent繼承了Event,僅僅多了兩個屬性
- oldURL 先前會話歷史記錄的URL
- newURL 當前會話歷史記錄的URL
簡單的調用方式
hash | CAN I USE 上可以看到除了IE8一下和那個尷尬的Opera Mini,hashchange事件都是支持得很好。那么怎么做到兼容,用MDN的代碼做個引子
function(window) { if ("onhashchange" in window) { return; }var location = window.location,oldURL = location.href,oldHash = location.hash;setInterval(function() {var newURL = location.href, newHash = location.hash;if (newHash != oldHash && typeof window.onhashchange === "function") { window.onhashchange({type: "hashchange",oldURL: oldURL,newURL: newURL});oldURL = newURL;oldHash = newHash;}}, 100); }hash history 簡單版本實現
從上面可以得知,我們的實現思路就是監聽hashchange事件,這里先拋開兼容性問題。
1 首先監聽hashchange事件,定義個RouterManager函數
- bind(this)讓函數this指向RouterManager實例
- 取到oldURL和newURL,同時查找一下是否注冊,然后加載相關路由
2 定義添加,刪除,加載,和初始化等方法
- add的時候,判斷是不是string, 如果是,重新構造一個新的router實例配置
- load這里主要是用來還原直接輸入帶hash的地址,比如 http://ex.com/#music
- loadWithRouter是最終渲染的入口
- getByUrlOrName,你可以通過名字和path查找路由,name是方便日后擴展
- setIndex設置默認路由地址
- go, back, forward同history的方法
- init里面會檢測地址是不是帶hash,然后走不通的邏輯。history.replaceState這是因為,如果不這么做, http://ex.com/跳轉到http://ex.com/#/music會產生兩條歷史記錄,這是我們不期望的。
3 公布函數
RouterManager.prototype.use = RouterManager.prototype.addwin.Router = RouterManager4 頁面怎么配置,簡單的利用a標簽href
<ul><li><li><a href="#/m1">菜單1</a></li><ul><li><a href="#/m11">菜單11</a></li><li><a href="#/m12">菜單12</a></li></ul></li><li><a href="#/m2">菜單2</a></li><li><a href="#/m3">菜單3</a></li> </ul>5 注冊,當然你也可以通過選擇器批量注冊
var router = new Router() router.NOTFOUND = function (msg) {content.innerHTML = msg } router.use('/m1', function (r) {req(r.path.slice(1)) }) router.use('/m11', function (r) {req(r.path.slice(1)) }) router.use('/m12', function (r) {req(r.path.slice(1)) }) router.use('/m2', function (r) {req(r.path.slice(1)) }) router.use('/m3', function (r) {req(r.path.slice(1)) }) router.setIndex('/m1') router.init()為了方便演示,定義req,ajax方法,模擬ajax請求
function req(url) {ajax(url, function (res) {content.innerHTML = res}) }function ajax(id, callback) {callback({'m1': '菜單1的主區域內容','m11': '菜單11的主區域內容','m12': '菜單12的主區域內容','m2': '菜單2的主區域內容','m3': '菜單3的主區域內容'}[id] || '404 Not Found!') }6 demo地址
hash-Router1.0
7 源碼地址
簡單的前端hash路由
8 下一步
這就成了最簡單最基本的路由了。讓然還有很多要考慮,比如如下
hash | CAN I USE
The HashChangeEvent interface
onhashchange | MDN
window.location.hash 使用說明
JS單頁面應用實現前端路由(hash)
Ajax保留瀏覽器歷史的兩種解決方案(Hash&Pjax)
理解瀏覽器的歷史記錄
理解瀏覽器歷史記錄(2)-hashchange、pushState
Web開發中 前端路由 實現的幾種方式和適用場景
自己動手寫一個前端路由插件
vue-router
react-router
總結
以上是生活随笔為你收集整理的简单的基于hash和hashchange的前端路由的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有外键约束的子表插入数据时出现的错误
- 下一篇: 六周第四次课(1月18日)