1 问题背景
做web前端开发的总会用到图片查看器,就是点击查看大图的功能。对于大厂,肯定是自己实现一套图片查看器,但对于个人开发者,时间、精力、技术都有限,自己实现一套不现实,还是引用第三方库比较实际。其中viewerjs几乎是开源出来的图片查看器中功能最全的库,截止目前Github上的小星星已经有7.4k。
对于viewerjs的使用非常简单,如果不需要个性化配置的话,两三行js代码就能初始化。
<!-- a block container is required -->
<template>
<div>
<ul id="images">
<li><img src="picture-1.jpg" alt="Picture 1"></li>
<li><img src="picture-2.jpg" alt="Picture 2"></li>
<li><img src="picture-3.jpg" alt="Picture 3"></li>
</ul>
</div>
</template>
<script>
import 'viewerjs/dist/viewer.css';
import Viewer from 'viewerjs';
const viewerjs = new Viewer(document.getElementById('images'));
</script>
在做卧卷想法时,由于每一条想法的图片集合都应该是一个独立的数据集,自然而然就想到针对每一条动态都初始化一个viewerjs。然后在测试的时候发现,除了第一条想法的图片查看器是正常的,其他想法均无法打开图片查看器。这是由于viewerjs的初始化过程在同一个页面只能执行一次,即使是在组件里初始化,只要这些组件都在同一个页面使用,就不能这样简单粗暴再次初始化viewerjs,这也算是viewerjs一个小小的不足之处。
2 解决方案
viewerjs有一个destroy( )方法,用于销毁viewerjs实例。
destroy( ): Destroy the viewer and remove the instance.
如图所示,想法的图片集合最外层是一个div,对这个div绑定一个唯一的id,并绑定一个在捕获阶段触发的点击事件。在点击事件中,首先判断变量viewerjs是否为null,如果不为null,则先执行destroy( )方法销毁,然后重新进行一次初始化。此处代码实例使用Vue作为框架。
<template>
<div id="id" @click.capture="initViewerjs">
<ul id="images">
<li><img src="picture-1.jpg" alt="Picture 1"></li>
<li><img src="picture-2.jpg" alt="Picture 2"></li>
<li><img src="picture-3.jpg" alt="Picture 3"></li>
</ul>
</div>
</template>
<script>
import 'viewerjs/dist/viewer.css';
import Viewer from 'viewerjs';
let viewerjs = null
initViewerjs() {
if (viewerjs !== null) {
viewerjs.destroy()
}
this.$nextTick(() => {
viewerjs = new Viewer(document.getElementById('id'))
})
}
</script>
3 方案完善
上述代码示例有个不完善的地方。点击一次图片集合,viewerjs就初始化一次,但对于重复点击同一个图片集合,不应该执行销毁和初始化流程,众所周知,销毁对象、创建对象是一项非常消耗性能的操作,也容易造成内存泄漏。因此对代码示例稍作完善,增加一个lastInitViewerjsID变量,用于记录上一次初始化的图片集合div的id是多少。执行initViewerjs时,先判断触发本次点击事件的图片集合id和上一次初始化的图片集合id是否为同一个,如果为同一个则不执行后续的销毁、初始化流程。
<template>
<div id="id" @click.capture="initViewerjs(id)">
<ul id="images">
<li><img src="picture-1.jpg" alt="Picture 1"></li>
<li><img src="picture-2.jpg" alt="Picture 2"></li>
<li><img src="picture-3.jpg" alt="Picture 3"></li>
</ul>
</div>
</template>
<script>
import 'viewerjs/dist/viewer.css';
import Viewer from 'viewerjs';
let viewerjs = null
let lastInitViewerjsID = ''
initViewerjs(id) {
if (id === lastInitViewerjsID ) {
return
}
if (viewerjs !== null) {
viewerjs.destroy()
}
this.$nextTick(() => {
viewerjs = new Viewer(document.getElementById('id'))
})
}
</script>
参考: