0

我是法国人,所以请原谅一些翻译错误...

我有一个代码,使用 Jquery 和 Ajax 调用,但我不明白以下问题。

我有一张桌子,第一行。在行的末尾,有两个选项:有效和删除。当您单击有效图标时,会出现加载图标,出现新行,追加到表格,加载图标消失,并显示删除图标。

当您单击删除图标时,它会删除该行。

所以我的问题...

一开始,我直接在图标上实现了“onclick=valid()”和“onclick="delete()”。但现在,我发现使用a更干净:

$('#valid'+i).click(function(){
    valid(i);
});
$('#delete'+i).click(function(){
    delete(i);
});

问题出现了:当您单击时,例如在第 3 行的删除图标上,出现在第 4 行的是加载...

有代码

PHP/HTML

<?php
    include_once 'functions_sandbox.php';
?>
<html>
    <head>
        <script src="http://code.jquery.com/jquery-1.9.0.min.js" type="text/javascript"></script>
    </head>
    <body>
    <script type="text/javascript">
        //Fonction qui charge les datepicker et les différentes options sur les champs
        function reload_jquery(){
            $('input[type=text][id*=tags]').each(function() {
                i = $(this).attr('num');
                $(this).css('border','thin blue solid');
                $('#valid'+i).click(function(){
                    valid_temps(i);
                });
                $('#delete'+i).click(function(){
                    delete_temps(i);
                });             
            });     
        }   
        function valid_temps(i){
            $('#loading'+i).show();
            $('#valid'+i).hide();
            var variables = 'mode=saisie_temps&j='+$('#j').val();
            $.ajax(
                {
                    // Define AJAX properties.
                    type: "POST",
                    url: "/dgi/ajax_sandbox.php",
                    data : variables,
                    dataType: "html",
                    timeout: 6000,

                    // Define the succss method.
                    success: function(data)
                    {
                        $('#data_retour').append(data);
                        $('#loading'+i).hide();
                        $('#delete'+i).show();                  
                        $('#j').val(parseInt($('#j').val())+1);
                        reload_jquery();
                    }
                }
            );      
        }
        function delete_temps(i){
            $('#loading'+i).show();
            $('#delete'+i).hide();
            $( "#confirm").dialog({
                resizable: false,
                height:160,
                width: 350,
                modal: true,
                buttons: {
                    "Oui": function() {
                        supp_temps(i);
                        $(this).dialog( "close" );
                    },
                    "Non": function() {
                        $('#loading'+i).hide();
                        $('#delete'+i).show();
                        $(this).dialog( "close" );
                    }
                }
            });
        }
        function supp_temps(i){
            $('#ligne'+i).hide('slow');
        }   

    $(function(){
        reload_jquery();
    });

    </script>
    <table id="data_retour" class="module">
        <?php echo ligne_saisie_sandbox(0); ?>
    </table>
    <div style="display:none" id="confirm" title="Confirmation">Voulez-vous vraiment supprimer ce temps ?</div> 
    <label>Indice J : </label>
    <input type="text" value="1" id="j" name="j" />
</body>
</html>

“functions_sandbox.php”中的“ligne_saisie_sandbox”函数

function ligne_saisie_sandbox($j){
    $retour = '
    <tr id="ligne'.$j.'">
        <td class="cellule _light">
            <label>Attraction'.$j.' : </label>
            <input type="text" id="tags'.$j.'" num="'.$j.'" />

            <img src="/dgi/img/b_save.png" alt="Valid" title="Valider votre temps" title="Valider le temps" id="valid'.$j.'" style="margin-top:5px;float:right">
            <img src="/dgi/img/b_empty.png" alt="Supprimer" title="Supprimer votre temps" title="Supprimer le temps" id="delete'.$j.'" style="margin-top:5px;float:right;display:none">
            <img src="/dgi/img/ajax_clock_small.gif" alt="Load" id="loading'.$j.'" style="margin-top:5px;float:right;display:none;" />
        </td>           
    </tr>'; 
    return $retour;
}

和“ajax_sandbox.php”中的 Ajax

include_once 'functions_sandbox.php';
switch ($_POST['mode'])
{
    case "saisie_temps":
        $j = $_POST['j'];
        $retour = ligne_saisie_sandbox($j);
        echo $retour;
    break;
}

一张小图来说明问题

4

2 回答 2

2

出现您的问题是因为您忽略了var这一行:

i = $(this).attr('num');

通过离开var,您创建了i一个全局变量,这使得i您的回调 ( delete_temps(i);) 中的 s 都指向 global i,而不是 local i

将该行更改为:

var i = $(this).attr('num');

它应该工作。我还建议不要使用自定义属性。使用 HTML5data-属性:

<input type="text" id="tags'.$j.'" data-num="'.$j.'" />

并使用.data()功能:

var i = $(this).data('num');
于 2013-03-08T08:22:06.030 回答
0

您遇到的问题是 JavaScript 中的常见问题。这是一个关闭问题。您隐式声明了i在此行中调用的变量。

i = $(this).attr('num');

由于它是隐式声明的,它也是全局的。这将导致每次迭代都.each()使用相同的变量。

在您的情况下,您必须选择如何解决它。JavaScript 中的变量具有函数作用域,因为您永远不会覆盖 i 的值,您可以简单地像这样显式声明变量:

var i = $(this).attr('num');

通常建议显式声明变量,如果你像这样开始你的函数,你实际上可以让大多数 JS 引擎为你检查这个

function(){
  "use strict";
  //...
}

另一种选择是对这种封闭问题的更一般的解决方案。在本节中 $('#valid'+i).click(function(){ valid_temps(i); }); $('#delete'+i).click(function(){ delete_temps(i); });

你可以把它改成

i = $(this).attr('num')       
(function(i){
  $('#valid'+i).click(function(){
      valid_temps(i);
  });
  $('#delete'+i).click(function(){
      delete_temps(i);
  });
})(i);

不同之处在于,在您的代码中,直到调用该方法才对 i 进行评估,从而为您提供在最后一次迭代中写入 i 的值.each()。在上面的代码i中,立即评估。作为您面临的关闭问题的一个简单示例,您可以使用这段代码

var i,j, arr = [];

for(i=0;i<10;i += 1){
    //creates a function that closes over i
    arr[arr.length] = function(){console.log(i);}
}
for(j=0;j<10;j += 1){
   arr[j](); //They all output 9 to the console
}

将第一个循环的主体更改为

arr[arr.length] = (function(k){function(){console.log(k);}})(i);

导致大多数人期望的第一手行为,即 0..9 输出到控制台

在您的特定情况下,简单地在i本地声明可能是这两个选项中最易读的,但最好知道如何避免在一般情况下关闭变量。

于 2013-03-08T08:43:26.610 回答