【问题标题】:jQuery ready function being called twice in a dialogjQuery 就绪函数在对话框中被调用两次
【发布时间】:2011-03-10 10:15:44
【问题描述】:

我正在用 PHP 脚本中的选项卡构建一个 jQuery 对话框。该脚本在循环内使用“include”指令,遍历选项卡并包含其他脚本。每个包含的文件都有选项卡的数据和一个

<div id="tabDialog">
  <div id="tabs">
    <ul>
      <li><a href="#tab1'>Tab1</a></li>
      <li><a href="#tab2'>Tab2</a></li>
    </ul>
    <div id="tabContainer">
      <div id="tab1">
        <?php include "tab1.php"; ?>
      </div>
      <div id="tab2">
        <?php include "tab2.php"; ?>
      </div>
    </div>
  </div>
</div>

例如,tab1.php 可能有如下内容:

<script type="text/javascript">
   $(document).ready (function () {
       alert ('tab1 loaded');
   });
</script>

问题是,在使用

作为对话框的 DIV 创建和打开对话框时,会再次调用文档的就绪函数。这是对话框代码:
 $("#tabDialog").dialog ({
   autoOpen: false,
   minWidth: 450,
   minHeight: 400,
   width: 600,
   height: 500
 }).dialog ('open');

造成这种情况的原因是什么?解决这种情况的最佳方法是什么?我试图将每个选项卡的功能保存在单独的文件中,因为它们可以在多种情况下使用,并且我不必复制与它们关联的代码。

感谢您的任何帮助或建议。

【问题讨论】:

  • 有什么方法可以添加更多代码来查看更多正在发生的事情吗?仅此一点有点难以弄清楚。
  • 既然你在循环中,你确定你没有在html中多次使用ID tabDialog 吗?在这种情况下,它将触发每个#tabDialog div 的事件。
  • 发生这种情况是因为包括脚本块在内的内容被移动到正文的末尾(并再次执行)......虽然我不确定纠正这个问题的最佳方法,但脚本可以对于所有这些都不会包含在单个外部文件中吗?
  • 您的 javascript 似乎很麻烦。这可能会有所帮助——stackoverflow.com/questions/3142504/…

标签: php jquery dialog document-ready


【解决方案1】:

您可能不需要 .dialog('open') 调用;使用选项 autoOpen : true 代替。

【讨论】:

  • 对,但是每个 ready() 函数仍然被调用两次 :(.
  • 从技术上讲,您可以在同一页面中有多个 document.ready() 调用。重要的是对您的 dialog() 函数的调用。另请参阅我对您的问题的评论。您能否向我们展示显示错误的页面的完整 html 代码?
  • 我会试着看看我能把它放在哪里,或者试着创建一个更小的例子。我“认为”问题的根本原因是包含的 PHP 文件的
  • 我将代码放在答案中,因为它太大而无法放入评论。
【解决方案2】:

.dialog()我用的不多,但是你的脚本中需要使用jQuery的ready()方法吗?

看起来.dialog() 有你可以利用的回调选项。

标签中的脚本:

    <script type="text/javascript">
        function onOpen() { alert('tab1 loaded') };
    </script>

对话:

$(this).dialog ({
    autoOpen: false,
    minWidth: 450,
    minHeight: 400,
    width: 600,
    height: 500,
    open: function(event, ui) { onOpen(); } // call function in script
}).dialog ('open');

【讨论】:

    【解决方案3】:

    所以我不得不说我不是 100% 确定它为什么会发生,即使我知道对话框确实保持它自己的状态,所以这可能是原因之一。但我可能会走得很远。但是解决它的方法是改用这样的东西:

    $(document).one('ready', function () {
       alert ('tab1 loaded');
    });
    

    这将确保它只在页面加载时运行一次。

    【讨论】:

    • 测试 这对我有用。修剪代码以适应注释。
    • 忘了说我是针对 jquery 1.3.2 版运行这个
    • 有趣。当我把它放到我的代码中时,它会调用你的每个 document.ready() 函数两次。现在把我的头发扯掉:P。
    • 您忘记将底部的 document.ready 更改为 document.one。我现在刚刚使用该更改运行了代码,它只运行了一次。有趣的是它运行了两次。
    • 我正在搜索另一个线程。 jQuery 对话框是否“克隆”了用作对话框的 div?完全复制 DIV 的内容?如果是这样,那么我认为这就是问题所在,因为 SCRIPT 也会被复制,因此会在 DOM 中出现两次 :(.
    【解决方案4】:

    这是页面的结果文本。我做了一个查看源代码,然后从页面中删除了所有无关的内容以尝试使其更简单。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html>
        <head>
            <link href="css/redmond/jquery-ui-1.8.1.custom.css" type="text/css" rel="stylesheet" media="screen" />
            <link href="css/style.css" type="text/css" rel="stylesheet" media="screen" />
            <script src="js/jquery-1.4.2.min.js" type="text/javascript"></script>
            <script src="js/jquery-ui-1.8.1.custom.min.js" type="text/javascript"></script>
        </head>
    
        <body>
            <div id="tabDialog" style="position: relative; display: none;" title="Test Dialog">
                <div id="tabs" style="position: absolute; top: 5px; bottom: 40px; left: 3px; right: 3px;">
                    <ul>
                        <li><a href='#tab1'>Tab #1</a></li><li><a href='#tab2'>Tab #2</a></li>
                    </ul>
    
                    <div class="tab_container" style="position: absolute; top: 35px; bottom: 0px; left: 1px; right: 1px; overflow: auto;">
                        <div id='tab1' class='tabPage ui-dialog-content'>
                            <form id="tab1Form">
                                More testing... <input class="keypressMonitor" type="text">
                            </form>
                            Testing...<br/>
                            Testing...<br/>
    
                            <script type="text/javascript">
                                $(document).ready (function () {
                                    alert ('tab1 loaded');
                                    $("#tab1Form").bind ('save', function () {
                                        alert ("in tab1Form.save ()");
                                    });
                                });
                            </script>
                        </div>
    
                        <div id='tab2' class='tabPage ui-dialog-content'>
                            <form id="tab2Form">
                                <div style="position: absolute; left: 1px; right: 1px; top: 1px; bottom: 1px;">
                                    Testing: <input class="keypressMonitor" type="text">
    
                                    <textarea id="testArea" class="keypressMonitor tinymce" style="position: absolute; top: 30px; bottom: 2px; left: 2px; right: 2px;"></textarea>
                                </div>
                            </form>
    
                            <script type="text/javascript">
                                $(document).ready (function () {
                                    $("#tab2Form").bind ('save', function () {
                                        alert ("in tab2Form.save ()");
                                    });
                                });
                            </script>
                        </div>
                    </div>
                </div>
    
                <div id="dialogButtons" style="position: absolute; bottom: 3px; left: 3px; right: 15px; text-align: right; height: 32px;">
                    <button class="applyButton" disabled>Apply</button>
                    <button class="okButton" disabled>Ok</button>
                    <button class="cancelButton">Cancel</button>
                </div>
            </div>
    
            <script type="text/javascript">
                $(document).ready (function () {
                    $("#tabs").tabs ();
                    $("button").button ();
    
                    /**
                     * Pressing the cancel button simply closes the dialog.
                     */
                    $(".cancelButton").click (function () {
                        $("#tabDialog").dialog ("close");
                    });
    
                    $("#tabDialog").dialog ({
                        open: function () {
                        },
                        autoOpen: true,
                        minWidth: 450,
                        minHeight: 400,
                        width: 600,
                        height: 500,
                        height: 'auto'
                    });
                });
            </script>
        </body>
    </html> 
    

    【讨论】:

      【解决方案5】:

      我相信我已经找到了原因并制定了一个相当不错的解决方案。当 jQuery 创建对话框时,它会在 DOM 中移动包含对话框内容的 DIV(到文档的最后),并用对话框所需的必要脚手架包围该 div(可能使用 .append( )功能或类似的东西)。因为动态的 DIV 中包含 Javascript,所以 jQuery 在 DIV 重新定位到 DOM 后(即第二次)调用 document.ready() 函数。因此,在构建对话框之前,我 .remove() 对话框的 DIV 中的每个脚本标签,如下所示:

          $("#tabDialog").find ("script").remove ();
          $("#tabDialog").dialog ({
            autoOpen: true,
            minWidth: 450,
            minHeight: 400,
            width: 600,
            height: 500
          });
      

      这样做会从最初加载它的 DIV 中删除 SCRIPT 标记,但 SCRIPT 本身仍然存在。我仍在研究这个,因为我不完全了解动态加载的 Javascript 代码实际“存在”的位置,但我怀疑它位于 DOM 之外的某个地方。我在 Chrome、Firefox 和 Exploder 8 中验证了这一点。

      我通过在 DIV 中放置一个按钮并分配一个 .click() 函数来验证最初包含在加载的 DIV 中的任何脚本仍然可以按预期运行。这是一个小测试来证明这一点:

      <html>
        <head>
          <link href="css/redmond/jquery-ui-1.8.1.custom.css" type="text/css" rel="stylesheet" media="screen" />
          <link href="css/style.css" type="text/css" rel="stylesheet" media="screen" />
      
          <script src="js/jquery-1.4.2.js" type="text/javascript"></script>
          <script src="js/jquery-ui-1.8.1.custom.min.js" type="text/javascript"></script>
        </head>
      
        <body>
          <div id="dialogContents" style="display: none;">
            <div  style="border: 1px solid black; height: 98%;">
              <form id="testForm">
                <input type="text">
              </form>
              <button id="testButton">Test</button>
              <script type="text/javascript">
                $(document).ready (function () {
                  alert ("ready");
      
                  $("#testButton").click (function () {
                    alert ('click');
                  });
                });
              </script>
            </div>
          </div>
        </body>
      
        <script type="text/javascript">
          $(document).ready (function () {
            //
            // Remove all the scripts from any place in the dialog contents.  If we
            // do not remove the SCRIPT tags, the .ready functions are called a
            // second time.  Removing this next line of Javascript demonstrates this.
            //
            $("#dialogContents").find ("script").remove ();
            $("#dialogContents").dialog ({
              width: 300,
              height: 300,
              title: 'Testing...'
            });
          });
        </script>
      
      </html>
      

      感谢本帖提供的帮助!

      【讨论】:

      • 这是对我的修复!我有一个准备就绪的&lt;script&gt;$(function(){...});&lt;/script&gt; 块在通过.dialog() 转换为对话框的HTML 块中进行。我的函数被调用了两次。将它移到被dialog()'ed 的 HTML 之外解决了这个问题。谢谢!
      • 非常有助于理解为什么会发生这种情况。谢谢!
      【解决方案6】:

      我也遇到过这个问题,但在我的情况下,原因是不同的。我在 div 内有一个自动关闭的 div 元素,用作对话框支架。当我用关闭标签替换自关闭元素时,文档就绪函数停止触发两次,只触发一次,正如预期的那样。

      例如,这会导致文档就绪函数触发两次:

      $("#foo").dialog({
        // ...
      });
      
      ...
      
      <div id="foo" title="My Dialog">
        <div id="bar" />
      </div>
      

      而这只会触发一次文档就绪功能:

      $("#foo").dialog({
        // ...
      });
      
      ...
      
      <div id="foo" title="My Dialog">
        <div id="bar"></div>
      </div>
      

      【讨论】:

        【解决方案7】:

        将您的脚本放入create 方法中:

        $.dialog({
            <your parameters>
            create: function() {
                <your script>
            }
        }
        

        使用此方法,您的脚本仅在您创建对话框时被调用一次,而不是两次!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-03
          • 1970-01-01
          • 1970-01-01
          • 2011-09-05
          • 1970-01-01
          • 1970-01-01
          • 2017-09-09
          相关资源
          最近更新 更多