前端URL與狀態(tài)的雙向綁定
在接觸以 React,Vue 為代表的工程化前端框架前,我還是一個拿著 jQuery 手?jǐn)]特效和手寫 CSS 的切圖仔,搗鼓 Vue 時接觸到的一個非常核心的概念就叫做“雙向綁定”,這里的雙向綁定指的是視圖(template)與狀態(tài)(state)的雙向綁定,狀態(tài)的變化直接觸發(fā)組件的渲染,不需要手寫控制和更新渲染的 js 函數(shù)了(沒錯這是我之前干的事)
這篇要討論的這個概念,應(yīng)該也不是我發(fā)明的新詞,叫 URL 與狀態(tài)的雙向綁定,字面意思來說,在刷新頁面或跳轉(zhuǎn)頁面時解析 URL 并對應(yīng)更新組件的狀態(tài),在組件狀態(tài)更新時同步更新 URL,為什么要引入這種機(jī)制嘞?
比如我目前在做的一個項(xiàng)目是一個管理后臺,在一個非常典型的日志查詢場景,可以選擇和調(diào)整很多查詢參數(shù)進(jìn)行查詢,但是由此就引出了一個問題,如果按照目前 Vue 雙向綁定的寫法,變更查詢組件的狀態(tài)(選擇或輸入?yún)?shù)等)不會反映到 URL 上,這時如果我需要將一組查詢好的結(jié)果分享給同事,只能復(fù)制當(dāng)前的頁面鏈接給他,讓他進(jìn)入后再選擇和我一樣的查詢參數(shù),可以看到有一部分沒有包含在 URL 中的信息其實(shí)是被丟棄掉了,另外在進(jìn)行站內(nèi)跳轉(zhuǎn)時也無法跳轉(zhuǎn)的更“具體”,只能跳轉(zhuǎn)到 router 定義的頁面在初始渲染完成后的樣子
這就引入URL與狀態(tài)雙向綁定的好處了,比如我在日志查詢頁面中選擇查詢方法為 POST ,等級為 ERROR 的日志,監(jiān)聽組件對應(yīng)的狀態(tài)變更,并更新URL(假設(shè)為?method=POST&level=ERROR),同理適用于其他的變更
當(dāng)然做到監(jiān)聽組件狀態(tài)更新 URL 只是做到了雙向綁定的一向,要想讓你的同事真的恢復(fù)到你當(dāng)前頁面的狀態(tài)還需要實(shí)現(xiàn)另一向的操作,即將 URL 解析到組件狀態(tài),往往是在頁面組件 mount 時解析當(dāng)前的 URL 路徑與QueryString,將其中的參數(shù)解析出來并與組件的狀態(tài)進(jìn)行同步,事實(shí)上就實(shí)現(xiàn)了
URL ? 組件狀態(tài) ? 組件視圖
帶給用戶的直觀體驗(yàn)就是視圖與 URL 的綁定,這時如果你將瀏覽器中的鏈接粘貼給同事,他在打開時就可以復(fù)現(xiàn)你當(dāng)前的組件狀態(tài),進(jìn)而得到你目前的視圖界面了
總結(jié)一下,實(shí)現(xiàn) URL 與狀態(tài)的雙向綁定其實(shí)就是需要實(shí)現(xiàn)
監(jiān)聽組件狀態(tài)更新URL(通過 watch 或 $emit 等手段)
將 URL 解析到組件狀態(tài)(如在組件 mount 時將 URL 參數(shù)解析并賦值給組件的 data 狀態(tài))
帶來的好處有
分享鏈接可以讓訪問者完整復(fù)現(xiàn)當(dāng)前頁面的狀態(tài)(至少是復(fù)現(xiàn)到你希望的粒度)
站內(nèi)跳轉(zhuǎn)可以隨心所欲跳轉(zhuǎn)到任何可能的狀態(tài)(而且僅通過 URL 這種 Web 原生的方式,而非使用 Vuex 之類的狀態(tài)管理)
這樣的功能業(yè)界其實(shí)也已經(jīng)有過一些開源庫能夠自動實(shí)現(xiàn)組件狀態(tài)與 URL 查詢參數(shù)的綁定,奈何自動化的方案給出的 URL 都太過冗余,而我在命名方面又是一個強(qiáng)迫癥,秉承著奧卡姆剃刀原則,我還是手動實(shí)現(xiàn)了每個狀態(tài)的綁定與解析,雖然較為機(jī)械化,但是往往就是在這種時候,我可以聽著音樂哼著歌,以近乎肌肉記憶的狀態(tài)有節(jié)律地敲打鍵盤,把這些不需要思考的代碼寫好
比起調(diào) infra 里那些搖擺不定,反復(fù)橫跳,此起彼伏的 bug,寫前端,調(diào)界面逐漸變成了一件放松身心的事~