Javascript 如何对动态添加的元素执行动态操作?

Javascript 如何对动态添加的元素执行动态操作?,javascript,jquery,html,Javascript,Jquery,Html,我的目标: 使用JS/Jquery动态填写“执行者付款”表 对于表中每个动态添加的行,其中一个数据单元包含一个下拉框。 当选择某个选项时,此下拉框应使同一单元格中的另一个下拉框可见。否则,第二个下拉列表将不可见。 在其他地方,我通过一个toggleVisible函数来实现隐藏/显示动态,该函数只添加由css标记的自定义类来隐藏或显示元素。 有关守则: 我要填充的表: <table id='performer-payments' class='performer-profile paymen

我的目标:

使用JS/Jquery动态填写“执行者付款”表 对于表中每个动态添加的行,其中一个数据单元包含一个下拉框。 当选择某个选项时,此下拉框应使同一单元格中的另一个下拉框可见。否则,第二个下拉列表将不可见。 在其他地方,我通过一个toggleVisible函数来实现隐藏/显示动态,该函数只添加由css标记的自定义类来隐藏或显示元素。 有关守则:

我要填充的表:

<table id='performer-payments' class='performer-profile payments-table'>              
    <tr>
        <th> Period </th>                                                             
        <th> Amount </th>                                                             
        <th> Paid? </th>                                                              
    </tr>
</table>
这至少有两个问题:

支付转移期-。。。即使在第一个选择框中选择了“传输”选项,也不会显示选择框。从调试工作来看,我认为可能是支付转移期-。。由于某种原因,它还不是一个有效的对象,或者类似的东西。 显然,实际上,onchange事件被触发N次N=周期数,因为我只是告诉程序在表中的内容发生更改时触发。我想它触发只为相关下拉列表,但当我试图添加付款状态-。。。作为.on函数的选择器,它使它从不触发。 注意:一般来说,我欢迎对此的反馈——我是一名经验丰富的程序员,但对HTML/JS/Jquery的使用经验很少。此外,我已经决定不在这个项目中使用模板,因为我正在尝试学习基础知识,所以如果您看到我“动态”将行添加到表中的方式,我很抱歉,但这部分是故意的

除此之外,如果这里有不清楚的地方,请要求澄清

编辑:以下是数据结构的相关部分:

data = {
    'Performers': {
        'Dira Klaggen': {
            'Payments': {
                'Q1': 'Paid',
                'Q2': 'Paid',
                'Q3': 'Unpaid'
            },
        },
        'Holden Bolden': {
            'Payments': {
                'Q2': 'Transferred to Q3',
                'Q3': 'Unpaid'
            }
        },
        'Manny Joe': {
            'Payments': {
                'Q1': 'Paid',
                'Q2': 'Unpaid',
                'Q3': 'Unpaid',
            }
        }
    },
    'Periods': [
        'Q1',
        'Q2',
        'Q3'
    ]
}  
您没有将更改处理程序附加到正确的元素。我应该是第一个被选中的人。。。而不是整张桌子

请尝试此更改处理程序:

第二种方法: 您可以通过在第一次选择时使用类而不是复杂的唯一id来简化这一点

假设您使用类付款状态:

处理程序将是:

$('#performer-payments').on('change', '.payment-status', function(){
  if ($(this).val() == 'transfer') {
    $(this).next('select').show();
  } else {
    $(this).next('select').hide();
  }
});

这个处理程序可能不在行附加循环中,因为它使用了。

让我们通过执行以下操作来清理代码:

使用类而不是丑陋的ID

使用或隐藏输入字段来保存额外信息

用于绑定动态创建的元素。在事件处理程序中,使用方法根据当前元素限制搜索范围

让我们应用这些东西

像这样构建每一行。{PLACEHOLDER}是将变量内容放入代码中的位置

<tr>
    <td>{PERIOD}</td>
    <td>{AMOUNT} $ </td>
    <td>
        <div class='performer-profile payment-status'>
            {SOMETHING-RELATING-TO-PERFORMER-PAYMENT-PERIOD}
        </div>
        <!-- remove ID -->
        <!-- store performer and period in data-attributes -->
        <select class='perfomer-profile hidden-onload displayNone payment-status-menu' data-performer='{PERFORMER}' data-period='{PERIOD}'>
            <option value='paid'>Paid</option>
            <option value='unpaid'>Unpaid</option>
            <option value='transfer'>Transfer to...</option>
        </select>
        <!-- remove ID -->
        <select class='performer-profile hidden-onload displayNone payment-period-menu'>                             
            <option value='{PERIOD}'>{PERIOD}</option>
            <option value='{PERIOD}'>{PERIOD}</option>  
            <option value='{PERIOD}'>{PERIOD}</option>
            <!-- etc -->
        </select>
    </td>
</tr>

看起来你不需要2个。但如果您这样做,则在事件处理程序中,使用获取其performer和period值。您也可以这样做。

您的数据样本将有助于重新创建问题。您的意图是好的?不幸的是,这与我尝试进一步指定“开”选择器时面临的问题相同:它从未触发。请尝试第二种方法。。。添加一个console.logChange!就在if.Great之前,您和Louys的答案似乎都表明,在JS中,按唯一ID进行选择不是一种方式,而是使用树遍历,然后,我猜,如果您需要额外的数据,则使用数据属性。不过,要明确的是,您在这里包含的数据属性纯粹是信息性的,对吗?与中一样,似乎不需要数据属性来解决这个特定问题?@Yourik是的,没错。检查我的最后一段。似乎你什么都不需要它。唯一的ID可能是一种方式。。。但在这种附加循环的情况下,这并不是最容易做到的事情。结果是一个丑陋的代码在将来更难维护。@Louyspatricebesette你是对的。就个人而言,我避免在循环中创建事件处理程序。大多数时候,如果您正确地使用jQuery方法,您不需要这样做。@Mikey:我完全同意;
$('#performer-payments').find('#payment-status-' + performer + '-' + period).on('change', function(){
  if ($(this).val() == 'transfer') {
    $(this).next('select').show();
  } else {
    $(this).next('select').hide();
  }
});
$('#performer-payments').on('change', '.payment-status', function(){
  if ($(this).val() == 'transfer') {
    $(this).next('select').show();
  } else {
    $(this).next('select').hide();
  }
});
<tr>
    <td>{PERIOD}</td>
    <td>{AMOUNT} $ </td>
    <td>
        <div class='performer-profile payment-status'>
            {SOMETHING-RELATING-TO-PERFORMER-PAYMENT-PERIOD}
        </div>
        <!-- remove ID -->
        <!-- store performer and period in data-attributes -->
        <select class='perfomer-profile hidden-onload displayNone payment-status-menu' data-performer='{PERFORMER}' data-period='{PERIOD}'>
            <option value='paid'>Paid</option>
            <option value='unpaid'>Unpaid</option>
            <option value='transfer'>Transfer to...</option>
        </select>
        <!-- remove ID -->
        <select class='performer-profile hidden-onload displayNone payment-period-menu'>                             
            <option value='{PERIOD}'>{PERIOD}</option>
            <option value='{PERIOD}'>{PERIOD}</option>  
            <option value='{PERIOD}'>{PERIOD}</option>
            <!-- etc -->
        </select>
    </td>
</tr>
$(function () {

    // ...

    for (period in data['Performers'][performer]['Payments']) {
        // build and append row
    }

    // create delegated event handler once and outside FOR loop
    $(document).on('change', '.payment-status-menu', function () {
        // get the current status menu
        var statusMenu = $(this);
        // find its related period menu
        var periodMenu = statusMenu.closest('tr').find('.payment-period-menu');
        // toggle its visibility
        periodMenu.toggle(this.value == 'Transfer');

        // of course, this could be a one-liner
        //$(this).closest('tr').find('.payment-period-menu').toggle(this.value == 'Transfer');
    });

});