PJAX 取回的 JS 文件未生效的问题

这两天参考社区里 龙哥 和 ChiVincent 的两篇关于 pjax 的文章 在 Laravel 应用中使用 pjax 进行页面加速在 Laravel 5.3 中使用 Pjax,着手给自己的博客使用上该特性。

我的博客是用 laravel 5.3 写的,前端使用了 jquery-pjax , 后端使用了 JacobBennett/pjax , 按照步骤操作下来,体验貌似不错,但点了几下发现问题:我博客使用了 gulp 将所有需要的(除了jquery) 压缩到 all.js 文件当中,然后放在 body 最底部,当我用 pjax 去请求页面时, 查看 response :

file

看到响应的内容中,明明有返回 all.js ,但实际上,js 并未进行加载,除了 boostrap 带的响应式菜单未失效外(但是,我 bootstrap 脚本也包含在 all.js 中),其他的 js 效果都失效了。

同学们可以看看我的博客 麦肯先生,目前仍然是这个问题。帮忙找找原因,谢谢。

本帖已被设为精华帖!
本帖由系统于 6年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
Summer
最佳答案

需要多了解下 PJAX 的原理:

简单来说是利用 pushState 和 ajax 来实现 HTML DOM 的「局部刷新」,并且去除页面 JS 的再次加载来加快页面访问速度。

PJAX 里的 JS 运行环境不同于「页面刷新」的运行环境。

像以下代码 $(document).ready 只会发生在「页面刷新」的时候触发:

$(document).ready(function()
{
    PHPHub.init();
});

后续的通过 PJAX 来渲染的「局部刷新」页面,都需要使用 PJAX 的事件 pjax:end 来触发:

           $(document).on('pjax:end', function() {
                NProgress.done();
                self.siteBootUp();
            });

康哥你需要做的不是让 all.js 加载起来,而是重构 all.js 的初始化流程。可以参照 phphub 的 js 初始化流程

(function($){

    var PHPHub = {
        init: function(){
            var self = this;

            // 初始化
            $(document).pjax('a:not(a[target="_blank"])', 'body', {
                timeout: 1600,
                maxCacheLength: 500
            });

            // PJAX 渲染结束时
            $(document).on('pjax:end', function() {
                // 这里的调用 **只有** 在「局部刷新」时才会运行
                self.siteBootUp();
            });
            self.siteBootUp();
        },

        /*
        * Things to be execute when normal page load
        * and pjax page load.
        */
        siteBootUp: function(){
            // ... 「局部刷新」和「页面刷新」都需要运行的代码
        }
    };
    window.PHPHub = PHPHub;

})(jQuery);

//「页面刷新」事件触发运行
$(document).ready(function()
{
    PHPHub.init();
});
7年前 评论
讨论数量: 7
Summer

需要多了解下 PJAX 的原理:

简单来说是利用 pushState 和 ajax 来实现 HTML DOM 的「局部刷新」,并且去除页面 JS 的再次加载来加快页面访问速度。

PJAX 里的 JS 运行环境不同于「页面刷新」的运行环境。

像以下代码 $(document).ready 只会发生在「页面刷新」的时候触发:

$(document).ready(function()
{
    PHPHub.init();
});

后续的通过 PJAX 来渲染的「局部刷新」页面,都需要使用 PJAX 的事件 pjax:end 来触发:

           $(document).on('pjax:end', function() {
                NProgress.done();
                self.siteBootUp();
            });

康哥你需要做的不是让 all.js 加载起来,而是重构 all.js 的初始化流程。可以参照 phphub 的 js 初始化流程

(function($){

    var PHPHub = {
        init: function(){
            var self = this;

            // 初始化
            $(document).pjax('a:not(a[target="_blank"])', 'body', {
                timeout: 1600,
                maxCacheLength: 500
            });

            // PJAX 渲染结束时
            $(document).on('pjax:end', function() {
                // 这里的调用 **只有** 在「局部刷新」时才会运行
                self.siteBootUp();
            });
            self.siteBootUp();
        },

        /*
        * Things to be execute when normal page load
        * and pjax page load.
        */
        siteBootUp: function(){
            // ... 「局部刷新」和「页面刷新」都需要运行的代码
        }
    };
    window.PHPHub = PHPHub;

})(jQuery);

//「页面刷新」事件触发运行
$(document).ready(function()
{
    PHPHub.init();
});
7年前 评论
Summer

需要多了解下 PJAX 的原理:

简单来说是利用 pushState 和 ajax 来实现 HTML DOM 的「局部刷新」,并且去除页面 JS 的再次加载来加快页面访问速度。

PJAX 里的 JS 运行环境不同于「页面刷新」的运行环境。

像以下代码 $(document).ready 只会发生在「页面刷新」的时候触发:

$(document).ready(function()
{
    PHPHub.init();
});

后续的通过 PJAX 来渲染的「局部刷新」页面,都需要使用 PJAX 的事件 pjax:end 来触发:

           $(document).on('pjax:end', function() {
                NProgress.done();
                self.siteBootUp();
            });

康哥你需要做的不是让 all.js 加载起来,而是重构 all.js 的初始化流程。可以参照 phphub 的 js 初始化流程

(function($){

    var PHPHub = {
        init: function(){
            var self = this;

            // 初始化
            $(document).pjax('a:not(a[target="_blank"])', 'body', {
                timeout: 1600,
                maxCacheLength: 500
            });

            // PJAX 渲染结束时
            $(document).on('pjax:end', function() {
                // 这里的调用 **只有** 在「局部刷新」时才会运行
                self.siteBootUp();
            });
            self.siteBootUp();
        },

        /*
        * Things to be execute when normal page load
        * and pjax page load.
        */
        siteBootUp: function(){
            // ... 「局部刷新」和「页面刷新」都需要运行的代码
        }
    };
    window.PHPHub = PHPHub;

})(jQuery);

//「页面刷新」事件触发运行
$(document).ready(function()
{
    PHPHub.init();
});
7年前 评论
Summer

把需要每一个页面运行代码都封装到 siteBootUp 里

7年前 评论

Jq-pjax 默认就有执行 content的js.
你的问题应该是渲染和JS执行的顺序问题. 毕竟pjax不同于浏览器刷新加载.
建议你直接使用requirejs seajs这样的模块化加载器. 哪怕将它降级看成是LABjs这种文件加载器也是可以的.

require(['jquery', 'bootstrap'], function() {
     // load completed
     something.init();
})

我个人偏向应该把脚本逻辑放到pjax target自身中去, 而不是类似@Summer 这种把相关逻辑都放到caller中

7年前 评论

@说好的呢 谢谢~ 这个问题早已经解决了,就是将所有需要执行的脚本重新再调用一次就OK ~

7年前 评论

@Summer 谢谢,学习了,但有个问题,有时候 self.siteBootUp();会执行两次,不知道大家遇到过这个问题没有?

7年前 评论

重复执行两次的问题已解决,原因未知,解决方法是用了PHPHub的包里的jquery.pjax.js,我原来使用的是从官方下载的,对比了一下,有较大差异。

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!