前言:不管構建SPA仍是MPA, 組件的狀態是沒法被保存下來的,這對於開發過程當中問題的重現是比較麻煩的,由於老是會失去上下文環境,致使重現過程變得繁瑣。因而想到了將Vue Component相關信息動態綁定在路由上。本文將給出其實現思路以及相關問題。
在使用Vue開發完應用後,應用上線進入了測試階段。測試人員測試出現問題後會對頁面進行截圖,並將頁面地址和截圖內容發送給開發人員進行bug的肯定和修改。這是比較常規的方式,但這對開發人員是很是不友好的,由於開發人員拿到的URL地址時,即沒有測試人員的本地數據,也須要經過繁瑣的操做從新按照測試人員所填寫的內容進行上下文環境的重現。爲何咱們不能將這些數據保存下載,測試人員將URL發送給開發人員以後,開發者能很容易定位到上下文環境並進行錯誤的重現及調試。javascript
不管你的數據是保存在內存
仍是Store
,亦或是存放在WebDB
中,都會遇到一個問題:你永遠都沒法拿到測試人員的數據。那麼惟一的方式就是經過URL來傳輸數據。所以,咱們的構想是:當界面加載組件後,將組件的部分屬性的變化公開到URL上,同時,組件在渲染時,讀取URL後將值解析還原到組件上去。這樣,即便不斷的刷新頁面,組件的狀態也不會發生改變。前端
因而,咱們爲這個功能編寫了一個Vue插件,取名路由快照(router-snapshot),其實現代碼以下:vue
// router-snapshot.js // https://github.com/dankogai/js-base64 import { Base64 } from 'js-base64'; function beforeRouteEnterHandler (vm, {key, ext}) { // 獲取路由綁定字段 const routeBindKeys = vm.$options[ext] || []; // 獲取路由綁定部分的加密字符串 const routeParamsString = vm.$route.query[key]; // 解密並轉換爲JSON let routeParamsJSON; try { routeParamsJSON = JSON.parse(Base64.decode(routeParamsString)); }catch (e) { routeParamsJSON = {}; } routeBindKeys.forEach(attr => { // 使用vue的是指方式,若瀏覽器沒有緩存值,則獲取組件默認值 vm.$set(vm, attr, routeParamsJSON.hasOwnProperty(attr) ? routeParamsJSON[attr] : vm[attr]); // 追加屬性反向監聽,監聽到的屬性變化都會呈如今路由上 vm.$watch(attr, (value) => { const query = vm.$route.query; let routeSnapshotValueJSON; try { routeSnapshotValueJSON = JSON.parse(Base64.decode(query[key])); }catch (e) { routeSnapshotValueJSON = {}; } routeSnapshotValueJSON[attr] = value; const extendQuery = {}; extendQuery[key] = Base64.encodeURI(JSON.stringify(routeSnapshotValueJSON)); vm.$router.push({ query: { ...query, ...extendQuery } }) }, { deep: true }); }) } export default { install (Vue, {key = '_', ext = 'routeShot'} = {}) { Vue.mixin({ // beforeRouteEnter (to, from, next) { // console.log('beforeRouteEnter', to, from) // next(beforeRouteEnterHandler) // } created () { beforeRouteEnterHandler(this, {key, ext}); } }); } }
代碼邏輯大體以下:java
_
;同時指定綁定在組件上的拓展屬性名,默認爲routeShot
;組件的代碼僅僅須要追加routeShot的配置便可:git
<template> <!-- 使用的iview庫的Switch組件 --> <Switch v-mode="switchValue"></Switch> </template> <script> export default { // 配置routeShot,指定該組件的switchValue屬性映射到URL中 routeShot: ['switchValue'], data () { return { switchValue: false } } } </script>
通過這樣,不管你怎麼刷新頁面,被快照的屬性都不會發生改變。另外,除了data
屬性,prop
、computed
屬性也是能夠綁定到URL上的。github
目前來講,應用場景中最多的仍是非安全性表單以及不須要持久化的數據。舉幾個例子:瀏覽器
寫完這個插件,面臨了三個我認爲比較重要的問題:緩存