前言:无论构建SPA还是MPA,组件的状态是无法被保存下来的,这对于开发过程中问题的重现是比较麻烦的,因为总是会失去上下文环境,导致重现过程变得繁琐。于是想到了将Vue Component相关信息动态绑定在路由上。本文将给出其实现思路以及相关问题。
场景重现
在使用Vue开发完应用后,应用上线进入了测试阶段。测试人员测试出现问题后会对页面进行截图,并将页面地址和截图内容发送给开发人员进行bug的确定和修改。这是比较常规的方式,但这对开发人员是非常不友好的,因为开发人员拿到的URL地址时,即没有测试人员的本地数据,也需要通过繁琐的操作重新按照测试人员所填写的内容进行上下文环境的重现。为什么我们不能将这些数据保存下载,测试人员将URL发送给开发人员之后,开发者能很容易定位到上下文环境并进行错误的重现及调试。
为什么是URL
无论你的数据是保存在内存还是Store,亦或是存放在WebDB中,都会遇到一个问题:你永远都无法拿到测试人员的数据。那么唯一的方式就是通过URL来传输数据。因此,我们的构想是:当界面加载组件后,将组件的部分属性的变化公开到URL上,同时,组件在渲染时,读取URL后将值解析还原到组件上去。这样,即使不断的刷新页面,组件的状态也不会发生改变。
实现
于是,我们为这个功能编写了一个Vue插件,取名路由快照(router-snapshot),其实现代码如下:
// 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}); } }); } }
代码逻辑大致如下:
组件的代码仅仅需要追加routeShot的配置即可:
经过这样,无论你怎么刷新页面,被快照的属性都不会发生改变。另外,除了data属性,prop、computed属性也是可以绑定到URL上的。
什么时候用最适合?
目前来说,应用场景中最多的还是非安全性表单以及不需要持久化的数据。举几个例子:
存在的问题
写完这个插件,面临了三个我认为比较重要的问题:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。