【问题标题】:jQuery: When using .load() to load php file, cause XHR finished loading to increase exponentially with every loadjQuery:使用 .load() 加载 php 文件时,导致 XHR 完成加载随着每次加载呈指数增长
【发布时间】:2015-09-27 22:20:15
【问题描述】:

我有一个问题,当我按下导航栏或链接时,我使用 .load() 将我的 php 页面加载到 div 中。但是我意识到,现在多次按下链接和导航栏后,“XHR 完成加载”呈指数增长,并且似乎同一个 php 文件被多次调用。

我将部分 javascript 代码放入名为 general.js 的通用 javascript 文件中,该文件也插入到所有其他 php 文件中,因为如果我不插入需要部分 javascript 代码的 php 文件中,它会不运行

此代码的一部分将 php 文件加载到 div 中。每当任何导航栏变为点击时,它都会加载 php 内容,但是加载请求会多次加载文件,并且随着点击次数的增加而增加。

$(".uk-navbar-nav").click(function(){

    if($("#subnav_1").hasClass("uk-active")){
      $("#welcome_tab").load("z_admin_welcome/welcome_admin.php");
      console.log("nav1");
  }
    else if($("#subnav_2").hasClass("uk-active")){
      $("#message_tab").load("z_admin/message_admin.php");
      console.log("nav2");
  }

  else if($("#subnav_3").hasClass("uk-active")){
        $("#Face_tab").load("z_admin_face/face_admin.php");
        console.log("nav3");
      }

  else if($("#subnav_4").hasClass("uk-active")){
        $("#QR_tab").load("z_admin/QR_admin.php");

        console.log("nav4");
    }
});

这是加载到 div 中的示例文件 (welcome_admin.php)

 <!DOCTYPE html>
 <html>
 <head>
 <!-- css styling is only on admin.php -->
 <!-- br break new line -->
 <script type="text/javascript" src="js/general.js"></script>
 <script type="text/javascript" src="uikit/js/uikit.min.js"></script> <!-- insert this as failing to do so cause it not to work -->

 </head>

 <body>

    <h3> Status </h3>
    <hr> 

    <div class="uk-margin">
        <div data-uk-button-radio data-uk-switcher="{connect: '#radio_status'}" id="welcome_radio_but">
            <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_1">Available</button>
            <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_2">Away</button>
            <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_3">Busy</button>
        </div>
    </div>

    <ul id="radio_status" class="uk-switcher uk-margin">
        <li class="uk-active uk-panel-box uk-width-1-3" aria-hidden="false" id="radio_display_1">Please knock before entering</li>
        <li aria-hidden="true" class="uk-panel-box uk-width-1-3" id="radio_display_2"></li>
        <li aria-hidden="true" class="uk-panel-box uk-width-1-3" id="radio_display_3">Do Not Disturb,please email me</li>

    </ul>


 </body>

 </html>

这是我的问题的屏幕截图,其中 XHR 被多次调用并完成加载同一个文件。

所以总的来说,问题在于 php 文件被多次调用并最终减慢/崩溃浏览器。

想知道:

  1. 是否应该停止将一个通用 javascript 附加到我将加载到的所有外部 php 文件中? (拆分函数并保存到多个不同的js文件?)
  2. 还有其他解决方案吗?

    感谢您的任何帮助/建议

更新 1:.uk-navbar-nav 所在的位置,这是主页

 <!DOCTYPE html>
<html>


    <head> <!--inseart script here -->
            <title></title>
        <link rel="stylesheet" text="text/css" href="uikit/css/uikit.gradient.min.css">
        <link rel="stylesheet" text="text/css" href="uikit/css/components/sticky.gradient.min.css">

        <script type="text/javascript" src="js/jquery.js"></script>
        <script type="text/javascript" src="uikit/js/uikit.min.js"></script>
        <script type="text/javascript" src="js/general.js"></script>
        <script type="text/javascript" src="uikit/js/components/sticky.min.js"></script>


    </head>

    <body onload="body_load()">


    <div class="uk-container uk-container-center uk-margin-top"> <!--top center margin overall -->


    <h1 class="uk-heading-large uk-panel-title uk-panel-box uk-icon-rebel"> This is the Main Page </h1>

    <!-- simpler header line stop here -->
    <div data-uk-sticky="{animation: uk-animation-slide-top}">
        <nav class="uk-navbar">
          <!-- Navigation tab bars -->
             <ul class="uk-navbar-nav" data-uk-switcher="{connect:'#subnav-pill-content-1'}">
              <li class="uk-active" id="subnav_1" aria-expanded="true"><a href="#"><i class="uk-icon-medium uk-icon-home"></i> Welcome</a></li>
              <li aria-expanded="false" id="subnav_2" class=""><a href="#"><i class="uk-icon-medium uk-icon-envelope"></i> Message</a></li>
              <li aria-expanded="false" id="subnav_3" class=""><a href="#"><i class="uk-icon-medium uk-icon-camera"></i> Facial Recognition</a></li>
              <li aria-expanded="false" id="subnav_4" class=""><a href="#"><i class="uk-icon-medium uk-icon-qrcode"></i> QR Code</a></li>
              <li aria-expanded="false" id="subnav_5" class=""><a href="#"><i class="uk-icon-medium uk-icon-gears"></i> Settings</a></li>
            </ul>

        </nav>
    </div>  
            <ul id="subnav-pill-content-1" class="uk-switcher">
              <!--welcome page -->
              <li class="uk-active" aria-hidden="false" id="welcome_tab" value=""></li>

              <!--Message -->
              <li aria-hidden="true" id="message_tab" class=""></li>

              <!--Facial Recognition -->
              <li aria-hidden="true" id="Face_tab" class=""></li>

              <!--QR Code -->
              <li aria-hidden="true"  id="QR_tab" class=""></li>

              <!--Settings Code -->
              <li aria-hidden="true"  id="settings_tab" class=""></li>
            </ul> 
        <!-- end of navigation tab bar -->

        </div>


     </body>

</html>

【问题讨论】:

  • 您应该向我们展示放置.uk-navbar-nav的HTML代码。
  • 很可能您正在重新加载相同的脚本并在每次加载时添加新的事件处理程序......导致越来越多的请求

标签: javascript php jquery html performance


【解决方案1】:

两次调用相同的代码将添加 2 个执行相同操作的事件处理程序...再次加载将创建第三个处理程序,依此类推

在添加新的单击处理程序之前,请使用off() 删除现有的单击处理程序,以防止复合添加新的单击处理程序。

$(".uk-navbar-nav").off('click').click(function(){

    // your existing click handler code

});

如果您要使用事件委托,理想情况下您只需要加载一次此代码

【讨论】:

  • 虽然它可能会起作用,但这是一种解决方法,他们应该尝试理解为什么要添加多个事件处理程序,因为他们应该只添加一个 :)
  • 我是否将我的 js 文件分开并为我不想具有点击功能的页面添加该行
  • @Buzinas 这就是我评论使用事件委托的原因
  • @Buzinas 你通过添加更多事件处理程序来做什么?我只为目标 id div 内容添加事件处理程序
  • @peekaboo 一遍又一遍地加载相同的脚本确实是一个设计缺陷。对event delegation 做一些研究,可以在页面加载时执行一次,而不是再次加载其他脚本
【解决方案2】:

首先,如果您的 welcome_admin.php 仅通过 jQuery 的 load 函数加载,则它不应包含完整的 HTML 代码(htmlheadbody 标记等)。它不应该加载你的general.js 文件。

尝试只为应该加载到div中的内容更改它,例如:

<h3> Status </h3>
<hr>

<div class="uk-margin">
  <div data-uk-button-radio data-uk-switcher="{connect: '#radio_status'}" id="welcome_radio_but">
    <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_1">Available</button>
    <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_2">Away</button>
    <button class="uk-button uk-width-1-10 radio_welcome" id="radio_but_3">Busy</button>
  </div>
</div>

<ul id="radio_status" class="uk-switcher uk-margin">
  <li class="uk-active uk-panel-box uk-width-1-3" aria-hidden="false" id="radio_display_1">Please knock before entering</li>
  <li aria-hidden="true" class="uk-panel-box uk-width-1-3" id="radio_display_2"></li>
  <li aria-hidden="true" class="uk-panel-box uk-width-1-3" id="radio_display_3">Do Not Disturb,please email me</li>
</ul>

这将防止您的general.js 文件被多次加载,然后,每次您的新页面被 jQuery 加载时,都会向您的uk-navbar-nav 添加新的事件处理程序。

另一件事是:您执行事件委托的方式并不是很酷。你应该这样做:

$('.uk-navbar-nav').on('click', 'li', function(e) {
  var item = e.target;

  switch (item.id) {
    case 'subnav_1':
      $('#welcome_tab').load('z_admin_welcome/welcome_admin.php');
      break;
    case 'subnav_2':
      $('#message_tab').load('z_admin/message_admin.php');
      break;
    case 'subnav_3':
      $('#Face_tab').load('z_admin_face/face_admin.php');
      break;
    case 'subnav_4':
      $('#QR_tab').load('z_admin/QR_admin.php');
      break;
  }
});

【讨论】:

  • 对于您放置var item = e.target 的js 文件,我正在考虑插入e.preventDefault(); 以防止冒泡效果?
  • 由于您使用的是li 标签,因此无需阻止默认行为。但是如果在你的菜单中你在litags中使用a标签会更好,所以你可以使用它的href属性,然后,你可以使用e.preventDefault方法来防止默认行为(重定向到另一个页面),相反,您可以使用 jQuery 的 load 方法。例如$('.uk-navbar-nav').on('click', 'li a', function(e) { e.preventDefault(); $(e.target).load(e.target.href); });
  • @peekaboo 如果我的回答对您有用,请点击箭头点赞,如果足够好,请点击V 将其标记为已接受的答案。谢谢! :)
  • 我忘了提一下,如果我不包括我的 js 函数我说 welcome_admin.php 并根据你的建议进行编辑,并且只在我的一般 js 文件中包含该函数,该文件将只加载在主页上,需要这些功能的welcome_admin.php 页面将不起作用。在这种情况下,您是否建议为每个页面创建单独的 js 文件?将添加到其中。例如:在我的welcome_admin.php div 标签的第一行上方,我会插入那个单独的 js 文件?
  • @peekaboo 您可以使用jQuery's event delegation,因此您的代码将在您向页面添加内容后立即开始工作。或者您可以将每个代码添加到包装器中,例如:var welcome_tab = { init: function() { /* your code for welcome_tab load here */ }; 等其他选项卡。然后,您可以执行以下操作:$('#welcome_tab').load('z_ad(...).php').then(welcome_tab.init);
【解决方案3】:

正如其他回复和 cmets 所说,问题在于您通过 $.load() 加载的页面带有她自己的 javascript,并在页面上重新附加了一个侦听器。因此,下次您尝试加载页面时,它会由原始脚本和动态加载的脚本加载。它不完全是“性能”问题,由使用 $.load() 加载内容缓慢或其他原因引起,这是一个逻辑问题,因为您的脚本在设计上有缺陷,做了很多不应该做的事情。

解决方案是只加载您需要显示的内容而不使用 javascript。

我应该停止将一个通用 javascript 附加到我将加载到的所有外部 php 文件中吗? (拆分函数并保存到多个不同的js文件?)

好吧,我认为问题不在于将单个 javascript 绑定到您的 php 脚本,而是有一个包含演示数据和脚本链接的 php 文件。如果您有一个 php 控制器,它使用正确的 javascript 加载正确的页面,然后是另一组正确的 php 文件,其中包含要呈现的数据(欢迎、消息、Face、Qr 等)并且没有多余的客户端脚本,您就不会这样问题。

但是,顺便说一句,将您的 javascript 分成单独的模块也是一个不错的决定。

还有其他解决方案吗?

好吧,您可以在加载新内容时使用 $.off() 分离事件侦听器,因此侦听器不会堆叠,并且额外的内容不会随着进一步的请求而加载。但是这种懒惰的方法最终往往会耗费大量时间。

【讨论】:

  • 感谢您的反馈 :)
【解决方案4】:

你可以试试这个:

$(".uk-navbar-nav").click(function(){
    if(!window['once']){
        window['once'] = true;

        //you code...

    }
});

【讨论】:

  • 首先,该代码非常难看。其次,它会使click 事件只工作一次,这不是我们想要的行为。
  • 它不会使click事件只工作一次,它会使if语句中的代码只执行一次,这就是我们想要的行为。
  • 一个元素一次......然后其他元素都不会工作
猜你喜欢
  • 1970-01-01
  • 2010-11-27
  • 2015-10-29
  • 2012-04-19
  • 2021-12-16
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
相关资源
最近更新 更多