@无名啊,我和
viewer.js还有另一兼容问题待解决:用户没点击过的图片无法正常预览,翻页只能看到红字svg。
@无名啊,所以,把
setTimeout做为加载顺序控制器是非常简单且有效的方法。在所有人都遵守这一规则的情况下,函数第二参数的数值就是加载顺序。为了防止我默认的0占尽先机,我决定把自己的数值改成10,以便让出一些位置给想先加载的代码。
setTimeout的单位是毫秒,50以内应该都不会引起用户察觉。
@无名啊,添加一点点延时就可以了,
setTimeout(() => {}, 1);后续脚本继续增加延迟,就可以按顺序形成调用链。
Javascript是单线程的,所以只要延迟数值比我的数值(没给,默认为0)大,就会晚于我执行。
@无名啊,这不现实,我想你也看到了,在我的代码开始执行时,图片请求实际上已经发出了。如果我的代码晚于其他代码加载,浏览器就有更多机会下完整个图片。要想实现最好的效果,我的代码应该放在加载顺序的最开头,而这与
viewer.js的要求显然是矛盾的。为了方便用户导入,我的代码不可能同时在插件列表的开头和结尾。
@无名啊,只要添加
setTimeout,就可以在我的$(document).ready()先执行的情况下,让我的绑定后执行。$(document).ready(() => { // 加这个延时,就可以保证晚于任何其他插件执行,以解决和viewer.js的冲突 setTimeout(() => { document.querySelectorAll('.userimg').forEach(x => { // 替换掉虎绿林的点击查看大图事件 x._onclick = x.onclick; x.onclick = function () { this.src = this._url; // 再次点击就触发虎绿林的点击查看大图事件 x.onclick = x._onclick; // 恢复被抑制的图片外层链接 if (x.parentNode._href) { // 为了防止外层链接被立即触发,所以加个延时 setTimeout(() => x.parentNode.href = x.parentNode._href); } }; }); }); });
@无名啊,我的更新已经发布了,你可以看我的代码。
@无名啊,这就是我一直在说的方案,并且我已经做好了。
我确实想到一个解决方法,就是用
setTimeout推迟onclick事件的绑定。
唯一的解决方法是在一切尘埃落定后重新绑定事件。多个
$(document).ready()的执行顺序是未知的,但是在$(document).ready()中使用setTimeout,那么就一定会晚于对方执行,即使延迟是0。
@无名啊,因为我的代码不在事件监听器和
defer内,我的代码是同步js文件中的立即执行表达式,总是最先执行,所以不必关心执行顺序了。唯一的解决方法是在一切尘埃落定后重新绑定事件。
@无名啊,因为最开始网页插件在顶部,加载很卡。
@无名啊,
$(document).ready()事件在DOMContentLoaded事件之后发生。
@无名啊,问题好像并不是同时触发,而是
$(document).ready()事件在DOMContentLoaded事件之后发生。
不过现在研究这个问题无意义了,因为我的代码现在位于立即执行表达式中,总是最先执行。
我确实想到一个解决方法,就是用setTimeout推迟onclick事件的绑定。$(document).ready(function () { document.querySelectorAll('.userimg, .userthumb').forEach(img => (img.onclick = function () { // 链接中的图片不预览 if (0 !== $(this).parents('a').length) return; let elem = document.querySelector('body'); let viewer = new Viewer(elem, { hidden: () => viewer.destroy(), filter(image) { return image.matches('.userimg, .userthumb'); } }); viewer.show() })); });
@无名啊,既然MDN这么说,那么问题就不是执行顺序问题,而是
onclick和addEventListener('click')互不影响,可以同时触发。
@无名啊,
defer在DOMContentLoaded之后执行,而且onclick和addEventListener('click')互不影响,可以同时触发。
@无名啊,现在我把插件代码改到底部了,我的代码改成立即执行表达式了,加载时也不会闪一下再消失了。
请求确实发出了,但首先请求的是hu60.cn,那个302重定向给JS代码的执行和后续请求的取消保留了足够的时间,最终没有到
file.hu60.cn的请求发出。
@无名啊,把插件放在网页底部,就可以取消事件监听器了。直接把代码暴露在最外层即可。这样就会在DOM解析好之后立即执行。
@无名啊,额,好像并非总是如此。有时候请求确实发出了,只是随后取消了。看起来必须把插件添加到网页底部,才能及时执行。![]()
@无名啊,为什么我强调“安装我的插件”,因为我可以保证我的插件里只有同步代码,所以执行时机一定是及时的。如果插件包含异步代码(async/await),那执行就不及时了,执行可能发生在多媒体内容开始加载之后,而非之前。
@无名啊,你的感觉可能不准确,你可以安装我的插件,关闭表情插件(因为表情插件有很多图片),然后自己看F12控制台。在用户点击前并没有图片请求发出。
@无名啊,至于不在file.hu60.cn上的文件,如果alt里没有大小,那在不请求服务器的情况下,自然没有任何办法得知其大小。
@无名啊,所有位于file.hu60.cn的文件都可以使用
function getSizeFromUrl(url) { url = hu60_decode_url64(url); var parts = url.match(/\/file\/(?:hash\/[^\/]+\/[a-f0-9]{32}|uuid\/[^\/]+\/[a-f0-9-]{36})(\d+)\b/); return parts ? parseInt(parts[1]) : 0; }获取文件大小。
文件路径是这样生成的:
if ($fileMd5 !== null) { $key = 'file/hash/' . $type . '/' . $fileMd5 . $fileSize . $ext; } else { $uuid = str::guidv4(); $key = 'file/uuid/' . $type . '/' . $uuid . $fileSize . $ext; }
