Vue SFC Playground是一个Vue单文件组件的在线代码演练场,通过它我们可以直接在浏览器中在线编写Vue单文件组件代码,并实时看到代码的渲染效果,是一个很方便的工具。
在使用过程中我发现了一个实用且有趣的功能:每次改动代码后,点击右上角的分享按钮,都会复制一个新的链接,来和别人分享你当前状态的代码。
进一步观察,可以发现:
- 每次改动代码,网页地址的hash值都在变,且同样的代码内容,对应的hash值是固定的。分享按钮其实就是简单的把地址复制到了剪贴板。
- 如果直接访问
https://play.vuejs.org
,页面会自动在地址栏后拼上一个固定的hash值,显示一个Hello World
的代码。 - 代码改动过程中,并没有发起任何请求。
基于以上的信息,可以得出以下结论:
- 代码内容与
location.href.hash
之间存在一对一的映射关系。 - 代码改动导致hash改动的过程,没有与服务端发生交互,所以这应该是一个纯前端实现的方案。
这感觉有点类似加密解密的过程:改动代码 > 把代码加密为一个hash > 别人访问带hash的url > 把hash解密为代码字符串展示出来。
我尝试搜了一下这个是怎么实现的,并没有得到我想要的答案,可能是搜索关键字不对吧。所幸我发现了网站右上角的github图标,那就好办了,我们直接来看一下它的源码是怎么实现的。
一般看github上的源码,我会先用github自带的在线编辑器,如果需要稍微深入的看我会用vscode的Remote-SSH扩展直接连接远程库在vscode里查看,这里就不展开说了。我用了第二种方式,由于问题的关键就是地址栏里的hash
,所以我直接在源码中搜索了location.hash
。定位到hash
是传入了new ReplStore()
中,这个构造函数来自一个依赖@/vue/repl,那么剩下的代码我们可以先不用看了。直接来看这个依赖的源码。
来到@/vue/repl源码中,由于上一步hash
是传递给了serializedState
属性,所以我们直接搜索serializedState
,定位到下面的deserialize
和serialize
方法。
不用看其它代码,只看我上图截图中的划线部分,结合方法本身的语义,不难看出:deserialize
是一个反序列化方法,用来把hash
序列化为文件内容。serialize
是一个序列化方法,用来生成对应的hash。而这两个方法分别用到了atou
和utoa
方法。
基于这两个方法我们就能实现文件内容与hash
之间的序列化与反序列化了。
总结
上面只是说明了下我是怎么在大量的源码中找到我想要的最终的答案的,并没有展开分析源码的实现细节。整个分享链接功能的流程可以概括为下面两点:
- 改动代码,调用
utoa
生成hash,改变浏览器的location.hash
- 访问带
hash
的链接,使用atou
解析出hash
对应的字符内容,渲染出代码。