java pjax_PJAX,站点加速之翼

PJAX(Push State with Ajax)在第二次执行时会导致JS脚本失效。本文深入解析了PJAX的工作原理,通过`extractContainer`和`executeScriptTags`函数了解其如何处理HTML片段和脚本。当PJAX结束时,由于脚本不被重新执行,导致问题出现。解决方法是监听`pjax:end`事件并在该事件中触发必要的初始化函数,如`self.blogBootUp()`,以确保每次页面切换时脚本正常运行。
摘要由CSDN通过智能技术生成

之所以说 pjax 不是开箱即用,主要是因为所有 js 脚本的调用会在第二次执行 pjax 方法时失效。我刚开始遇到这个问题时,一头雾水,折腾了许久而不得解,然后在 laravel china 发帖求助,很快站长龙哥就站出来,耐心细致的解答了我的疑惑。仔细研究了源码,我发现了其中两个有趣的函数:

var container = extractContainer("", xhr, options)

executeScriptTags(container.scripts)

字面意思是将取回的 html 碎片 进行加工处理成一个容器对象,并处理其中的脚本标签,那为什么第一次之后的 pjax 就没执行我的脚本呢?我们继续阅读两个函数体内的关键代码:

extractContainer :

// Gather all script[src] elements

obj.scripts = findAll(obj.contents, 'script[src]').remove()

obj.contents = obj.contents.not(obj.scripts)

将 html 碎片中的所有带 src 的脚本删除并储存在容器对象的 scripts 属性中,将去除了 scripts 的 html 碎片内容赋给 contents 属性。看到这里,你可能会大概明白了 pjax 的用意。继续看另一个函数体的内容:

executeScriptTags :

if (!scripts) return

var existingScripts = $('script[src]')

scripts.each(function() {

var src = this.src

var matchedScripts = existingScripts.filter(function() {

return this.src === src

})

if (matchedScripts.length) return

var script = document.createElement('script')

var type = $(this).attr('type')

if (type) script.type = type

script.src = $(this).attr('src')

document.head.appendChild(script)

})

获取目前 DOM 中的所有带 src 的脚本,然后和 html 碎片中的脚本逐个做比对,如果碎片中有新的脚本就将其插入到 head 标签的最后。啊哈~ pjax 这么做是确保不会重复请求任何已经下载过的脚本文件,节省 HTTP 开支。但这么做的弊端就是本段开头说的那个问题,那如何解决呢?

灵活运用 pjax 提供的事件。 要解决上述问题,我们可以监听 pjax:end 事件,当然 pjax:success 和 pjax:complete 也行,区别不大 :

$(document).on('pjax:end', function() {

self.blogBootUp()

})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值