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年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 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年前 评论

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