国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

淺談Vue路由快照實現思路及其問題

2019-11-19 13:41:44
字體:
來源:轉載
供稿:網友

前言:無論構建SPA還是MPA,組件的狀態(tài)是無法被保存下來的,這對于開發(fā)過程中問題的重現是比較麻煩的,因為總是會失去上下文環(huán)境,導致重現過程變得繁瑣。于是想到了將Vue Component相關信息動態(tài)綁定在路由上。本文將給出其實現思路以及相關問題。

場景重現

在使用Vue開發(fā)完應用后,應用上線進入了測試階段。測試人員測試出現問題后會對頁面進行截圖,并將頁面地址和截圖內容發(fā)送給開發(fā)人員進行bug的確定和修改。這是比較常規(guī)的方式,但這對開發(fā)人員是非常不友好的,因為開發(fā)人員拿到的URL地址時,即沒有測試人員的本地數據,也需要通過繁瑣的操作重新按照測試人員所填寫的內容進行上下文環(huán)境的重現。為什么我們不能將這些數據保存下載,測試人員將URL發(fā)送給開發(fā)人員之后,開發(fā)者能很容易定位到上下文環(huán)境并進行錯誤的重現及調試。

為什么是URL

無論你的數據是保存在內存還是Store,亦或是存放在WebDB中,都會遇到一個問題:你永遠都無法拿到測試人員的數據。那么唯一的方式就是通過URL來傳輸數據。因此,我們的構想是:當界面加載組件后,將組件的部分屬性的變化公開到URL上,同時,組件在渲染時,讀取URL后將值解析還原到組件上去。這樣,即使不斷的刷新頁面,組件的狀態(tài)也不會發(fā)生改變。

實現

于是,我們?yōu)檫@個功能編寫了一個Vue插件,取名路由快照(router-snapshot),其實現代碼如下:

// router-snapshot.js// https://github.com/dankogai/js-base64import { 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]);  // 追加屬性反向監(jiān)聽,監(jiān)聽到的屬性變化都會呈現在路由上  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});   }  }); }}

代碼邏輯大致如下:

  1. 代碼45行,注冊該組件時,我們需要指定保存在URL query部分的鍵名,默認為_;同時指定綁定在組件上的拓展屬性名,默認為routeShot;
  2. 代碼21行,根據組件拓展屬性,對這些拓展屬性實施監(jiān)聽,將屬性值的變化同步到路由中;
  3. 代碼19行,在組件created階段,獲取路由參數并解析成組件屬性,并將屬性值同步到組件中;
  4. 代碼13、25、31行對路由上的參數進行Base64的加密和解密;

組件的代碼僅僅需要追加routeShot的配置即可:

<template>  <!-- 使用的iview庫的Switch組件 -->  <Switch v-mode="switchValue"></Switch></template><script> export default {  // 配置routeShot,指定該組件的switchValue屬性映射到URL中  routeShot: ['switchValue'],  data () {   return {    switchValue: false   }  } }</script>

經過這樣,無論你怎么刷新頁面,被快照的屬性都不會發(fā)生改變。另外,除了data屬性,prop、computed屬性也是可以綁定到URL上的。

什么時候用最適合?

目前來說,應用場景中最多的還是非安全性表單以及不需要持久化的數據。舉幾個例子:

  1. 表格中篩選項有很多的情況下,用戶進行了大量的選擇和填寫操作,結果因為網絡原因導致請求失敗。待網絡恢復后,用戶重新刷新頁面,先前的操作必須重新執(zhí)行;一般情況中,用戶不會隨意更改瀏覽器的URL,在這種條件下,用戶的刷新不影響上下文的環(huán)境,能給用戶帶來一定便利;
  2. 之前代碼示例中,開關組件的值不交予服務端進行持久化,也是可以使用這種方式來保存操作的;

存在的問題

寫完這個插件,面臨了三個我認為比較重要的問題:

  1. 性能問題: 通過代碼47-50行可以看出,早期設計是將插件應用在路由組件中的,但是在后期的測試和使用中,發(fā)現還有很多組件不是注冊在路由中的,也就是父子組件,這樣的組件無法被路由鉤子攔截到,因此就將該函數混入到了所有組件的created函數中。當應用越來越大、組件越來越多的時候,這個性能未免有點令人擔憂;
  2. 持久性問題: 當URL的query部分越來越大的時候,超過了URL的長度限制,那么組件屬性的持久性將會被中斷。但我們并不能保證該長度不會超過,這隨著應用的增長是無法預料的。在前端中,我們沒有找到對應的庫能進行定長加密解密,如果能找到,這個或將被解決;
  3. 安全性問題: 一直找不到比較安全的加密解密方式,而且我覺得這樣做是會有安全隱患,但不知道究竟哪種場景會讓這種安全性問題暴露的最大;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 永和县| 呼玛县| 山东省| 泌阳县| 临西县| 集贤县| 安平县| 奉新县| 晋江市| 隆昌县| 桓仁| 大竹县| 玉环县| 中阳县| 嫩江县| 旌德县| 福鼎市| 孟州市| 晋宁县| 错那县| 东至县| 青浦区| 都匀市| 康平县| 合阳县| 东乌珠穆沁旗| 黎川县| 南充市| 宝坻区| 民县| 南投县| 明水县| 枣强县| 苗栗县| 东光县| 铜陵市| 大化| 互助| 万宁市| 巴林左旗| 天长市|