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年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
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年前 评论

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