javascript - Comment parcourir les fonctions et le contenu des éléments ajoutés dynamiquement
代言
代言 2017-06-12 09:28:08
0
5
813

Comme le montre l'image : la fonction à réaliser est de cliquer sur le bouton Ajouter en haut et d'ajouter dynamiquement des lignes de tableau en bas, puis le contenu de chaque ligne est parcouru à partir de l'objet.
Ensuite, je n'ai que les lignes écrites dans le premier html qui ont du contenu et des fonctions.
La ligne qui apparaît après avoir cliqué sur le bouton n'a ni contenu ni fonction. (Remarque : la fonction fait référence à ma première colonne et à ma deuxième colonne, qui sont l'effet de liaison de deuxième niveau)

Voici le code suivant : (je suis novice, et je ne connais pas très bien jq, donc l'écriture est très compliquée, et c'est un mélange de js et jq =-=, donnez-moi s'il vous plaît quelques conseils et orientations ! )

    <p class="clearfix" style="margin-left:200px;">
    <button class="button2" style="border:1px solid #000">添加</button>
    <form class="clearfix" style="float:left;margin-top:100px;">
        <table id="b" border="1px solid #000">
            <thead>
                <tr class="zzz">
                    <th style="width:141px;">计算期类型</th>
                    <th style="width:281px;">期间</th>
                    <th style="width:141px;">征收方式</th>
                </tr>
            </thead>
            <tbody id="zType_all">
                <tr>
                    <td>
                        <select id="zType_time"></select>
                    </td>
                    <td>
                        <select id="zType_years" style="float:left;"></select>
                        <select id="month_quarter"></select>
                    </td>
                    <td>
                        <select id="zCollection">
                            <option value="chazhang">查账征收</option>
                            <option value="heding">核定征收</option>
                        </select>
                    </td>
                </tr>
            </tbody>
        </table>
    </form>
    </p>
//点击按钮添加

    $('.button2').on('click',function(){
    var ccc = $('<tr><td><select id="zType_time"></select></td><td><select id="zType_years"></select><select id="month_quarter"></select></td><td><select id="zCollection"><option value="chazhang">查账征收</option><option value="heding">核定征收</option></select></td></tr>');
    var ddd = $('#zType_all');
    ddd.append(ccc);
    $('#a').css({"background":"white","color":"#000"});
    });



//下面是关于二级和三级联动的遍历
//这个是存储着option里信息的对象

    var zType_chose = [
    {
    "name":"年终汇算","types":[
        {"years":"2015年"},
        {"years":"2016年"}
        ]
     },
     {
        "name":"预缴-月度","types":[
        {"years":"2015年","zType_time1":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"]},
        {"years":"2016年","zType_time1":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"]}
        ]
     },
     {
        "name":"预缴-季度","types":[
        {"years":"2015年","zType_time1":["第一季度","第二季度","第三季度","第四季度"]},
        {"years":"2016年","zType_time1":["第一季度","第二季度","第三季度","第四季度"]}
        ]
     }
     ];

    //下面是我实现联动的js代码
    var zType_time = document.getElementById("zType_time");
    var zType_years = document.getElementById("zType_years");
    var month_quarter = document.getElementById("month_quarter");
    var zType_all = document.getElementById("zType_all");
    zType_time.options[0] = new Option("计算期类型");
    zType_years.options[0] = new Option("请选择年");
    month_quarter.options[0] = new Option("请选择月/季度");
    // 循环第一步把计算期类型循环进select
    for (var i = 0; i < zType_chose.length; i++) {
    zType_time.options[zType_time.length] = new Option(zType_chose[i].name);
    // 循环第二步,把第二列都循环进select
    zType_time.onchange = function(){
    zType_years.options.length = 0;
    month_quarter.options.length = 0;
    zType_years.options[zType_years.length] = new Option("请选择年");
    month_quarter.options[month_quarter.length] = new Option("请选择月/季度");
    for (var j = 0; j < zType_chose[zType_time.selectedIndex-1].types.length; j++) {
        zType_years.options[zType_years.length] = new Option(zType_chose[zType_time.selectedIndex-1].types[j].years)
    }
    if(zType_time.options[zType_time.selectedIndex].text == "年终汇算"){
        month_quarter.style.display = "none";
    }else{
        month_quarter.style.display = "inline-block";
    }
    }
    zType_years.onchange = function(){
        month_quarter.options.length = 0;
        month_quarter.options[month_quarter.length] = new Option("请选择月/季度");
        //循环另一个
        for (var k = 0; k < zType_chose[zType_time.selectedIndex-1].types[zType_years.selectedIndex-1].zType_time1.length; k++) {
            month_quarter.options[month_quarter.length] = new Option(zType_chose[zType_time.selectedIndex-1].types[zType_years.selectedIndex-1].zType_time1[k]);  
        };
    }
    };

Je pense que peut-être le contenu devrait être parcouru lors de la création des lignes du tableau ? Mais je ne sais pas comment faire, et que dois-je faire de ma fonction ?
En attendant une grande star en ligne

Dis-moi ! Merci beaucoup! urgent!

代言
代言

répondre à tous(5)
typecho

Tout d'abord, l'identifiant ne peut apparaître qu'une seule fois dans une page et est unique. Seule la classe peut apparaître plusieurs fois !

Déclaration

id 为唯一属性,即一个 html 文件中只能出现一个对应的 idclass Vous pouvez en utiliser plusieurs ;

Réalisation des exigences

La partie front-end, du framework aux fonctions, peut toutes être résolue à l'aide de modèles de conception. Pour parler franchement, elles peuvent toutes être résolues à l'aide de MVC, comme dans votre exemple :

  • C -> Logique JS entière

  • V -> Entrée sur une seule ligne

  • M -> données remplies ;

  • Vous pouvez en fait encapsuler ce genre de chose avec une fermeture ou en faire une classe de traitement. Tel que :
<p class="clearfix" style="margin-left:200px;">
    <button class="button2" style="border:1px solid #000">添加</button>
    <form class="clearfix" style="float:left;margin-top:100px;">
        <table border="1">
            <thead>
                <tr class="zzz">
                    <th width="240">计算期类型</th>
                    <th width="240">期间</th>
                    <th width="128">征收方式</th>
                </tr>
            </thead>
            <tbody id="zType_all">
            </tbody>
        </table>
    </form>
</p>

Continuez à améliorer le script :

(function($) {
    'use strict';

    /**
     * 组件条目解析
     * 一行即一个组件条目,该构造方法
     * 例:var thisRow = new AppRow();
     * @return {object} 一个 jQuery 对象
     */
    var AppRow = function() {
        return this.rowParse(this.rowDom());
    };

    // HTML 结构
    AppRow.prototype.rowDom = function() {
        var row = '',
            options = AppRow.typeChose,
            optionYears = options[0].types;

        // 计算期类型
        row += '<td><select class="type">';
        row += '<option value="-1">请选择</option>';
        for (var i in options) {
            row += '<option value="' + i + '">' + options[i].name + '</option>';
        }
        row += '</select></td>';

        // 期间
        row += '<td class="types"></td>';

        // 征收方式
        row += '<td><select class="collection">';
        row += '<option value="0">请选择</option>';
        row += '<option value="1">查账征收</option>';
        row += '<option value="2">核定征收</option>';
        row += '</select></td>';

        return '<tr>' + row + '</tr>';
    };

    // 解析行结构,添加事件
    AppRow.prototype.rowParse = function(row) {
        var $row = $(row),
            $typeTime = $row.find('select.type'),
            $typeTypes = $row.find('.types'),
            optionsData = AppRow.typeChose;

        // 计算期类型
        $typeTime.on('change.app', $.proxy(function(e) {
            var val = $typeTime[0].value;
            $typeTypes.children().remove();
            $typeTypes.append(this.selectYears(val));
        }, this));

        return $row;
    };

    // 返回年度表单
    AppRow.prototype.selectYears = function(type) {
        var optionYears = AppRow.typeChose[0].types,
            select = '',
            $select = null;

        // 构建表单
        select += '<select class="year">';
        select += '<option value="-1">请选择</option>';
        for (var i in optionYears) {
            select += '<option value="' + i + '">' + optionYears[i].years + '</option>';
        }
        select += '</select>';

        // 构建成 jQuery 对象
        $select = $(select);

        // 事件绑定
        $select.on({
            // 选择事件
            'change.app': $.proxy(function(e) {
                var val = $select[0].value,
                    $sub = $select.next('.sub');

                if (type <= 0) {
                    // 年终汇算无后续表单
                    return;
                }

                if (val === -1) {
                    // 未选择,则移除后续表单
                    $select.nextAll().remove();
                    return;
                }

                // 创建或或初始化后续表单
                if (!$sub.get(0)) {
                    // 表单不存在则创建
                    $select.after(this.selectSub(type, val));
                }
                $sub.trigger('reset.app');
            }, this),

            // 重置表单
            'reset.app': $.proxy(function(e) {
                $select.find('option').prop('selected', false)
                    .eq(0)
                    .prop('selected', true);
            })
        });

        return $select;
    };

    // 返回季度或月份表单
    AppRow.prototype.selectSub = function(type, year) {
        var optionData = AppRow.typeChose[type].types[year].zType_time1,
            select = '',
            $select = null;

        if (!optionData) {
            // 无数据
            return;
        }

        // 构建表单
        select += '<select class="sub">';
        select += '<option value="-1">请选择</option>';
        for (var i in optionData) {
            select += '<option value="' + i + '">' + optionData[i] + '</option>';
        }
        select += '</select>';
        $select = $(select);

        // 事件绑定
        $select.on({
            // 重置表单
            'reset.app': $.proxy(function(e) {
                $select.find('option').prop('selected', false)
                    .eq(0)
                    .prop('selected', true);
            })
        });

        return $select;
    };

    // 联动数据 - zType_chose
    AppRow.typeChose = [{
        "name": "年终汇算",
        "types": [{
            "years": "2015年"
        }, {
            "years": "2016年"
        }]
    }, {
        "name": "预缴-月度",
        "types": [{
            "years": "2015年",
            "zType_time1": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
        }, {
            "years": "2016年",
            "zType_time1": ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
        }]
    }, {
        "name": "预缴-季度",
        "types": [{
            "years": "2015年",
            "zType_time1": ["第一季度", "第二季度", "第三季度", "第四季度"]
        }, {
            "years": "2016年",
            "zType_time1": ["第一季度", "第二季度", "第三季度", "第四季度"]
        }]
    }];

    AppRow.VERSION = '1.0.0';

    // ===========================================

    // 添加按钮事件绑定
    var $addBtn = $('.button2'),
        $rowList = $('#zType_all');

    // 点击添加
    $addBtn.on('click.app', function(e) {
        // 或直接添加实例
        $rowList.append(new AppRow());
    });

})(jQuery);

Explication

    Créer un constructeur pour générer une structure avec effet d'encapsulation interactive - composant
  • ;

  • Ajoutez une série de méthodes au composant et créez une logique à l'intérieur
  •  ;

  • L'encapsulation de fermeture ne prend effet qu'en
  •  ;

    (function($){ /*code*/ })(jQuery);

  • $.fn.remove可以保证页面的数据的安全性,切忌使用 $.fn.hidepeut également être utilisé

    pour prolonger les opérations de suppression
  •  ;

    AppRow.prototype.delete()Si nécessaire, utilisez

    ;
  • name 做数据提交,则需使用 name="row[index][name]" 的格式,如:name="row[1]['type']"name="row[1]['year']"name="row[1]['sub']"Effet final :

Effet en ligne https://jsfiddle.net/kxjyo7fp...

某草草

Mettez le code pour parcourir les données dans la méthode où vous cliquez pour ajouter une ligne. La coordination spécifique est de savoir comment ajouter une ligne et en parcourir une. Vous devez l'implémenter vous-même, je ne l'ai pas examiné attentivement. Vous êtes maintenant un peu comme un élément ajouté dynamiquement. Vous liez l'événement, et le résultat est lié dans le code HTML écrit, mais l'élément ajouté n'est pas lié à l'événement

.
学霸

Il est recommandé d'utiliser directement la bibliothèque ui pour jquery, vous pouvez choisir easyui / bootstrap table

.
学习ing

La liaison d'événement sera liée avec succès une fois le rendu de la page terminé et ne sera pas automatiquement liée par la suite. Autrement dit, les nœuds ajoutés après le rendu de la page ne peuvent pas être liés ici. .click (...) Il s'agit d'une méthode similaire car lors de sa première compilation, un événement sera lié à la classe A sur la page si vous conditionnez dynamiquement plusieurs nœuds avec la classe a dans JS, puis les ajoutez. later n'aura aucun effet, car le nœud ajouté plus tard n'existe pas lors de la première liaison.
La solution est d'utiliser la méthode on(). Par exemple, $('body').on('click','.a',fun(){}) Cette méthode convient, car la balise body existera. peu importe le moment. Par conséquent, il n'y aura aucune situation dans laquelle le nœud ne pourra pas être trouvé et ne pourra pas être lié.
Bien sûr, vous pouvez également écrire vous-même la fonction sur le nœud, mais ce n'est pas recommandé.

小葫芦

J'ai réécrit une partie du script pour générer du DOM en utilisant jQuery. Pour plus de rapidité, j'ai utilisé une syntaxe ES6. Mais la fonction n'est pas encore terminée

https://jsfiddle.net/jrhju549/1/

Puis, quand je pensais mettre en cascade cette partie des choses, j'ai trouvé un problème (à propos des données) :

Du point de vue des données, les données facultatives pour le paiement mensuel et le trimestre sont les mêmes quelle que soit l'année. Le mois est de 12 mois et le trimestre est de 4 trimestres. Ensuite, ces données sont en fait fixes et peuvent être écrites directement en HTML. De cette façon, lors de la génération de nouvelles lignes, il vous suffit d'abord de les cloner, puis de gérer les détails, ce qui est beaucoup plus simple.

Cependant, une autre possibilité ne peut être exclue, c'est-à-dire que vos options sont différentes chaque année. Par exemple, 2015 fait 12 mois, 2016 fait 8 mois... (Bien sûr, la possibilité que cette situation se produise est très faible), dans ce cas, la sélection peut être générée dynamiquement sur la base de ces données. Ensuite, avant de générer dynamiquement une sélection, vous devez utiliser une fonction findXxxx pour trouver les données que la liste d'options correspondante doit utiliser - ce processus sera bien sûr beaucoup plus compliqué.

Au vu des progrès actuels, voici quelques points principaux

Traitement modulaire

Ne pensez pas à tout faire dans une seule fonction, divisez-la. Par exemple, j'ai initialement divisé createRow et createSelect dans le code. Parmi eux, createSelect est hautement réutilisable

// 创建 select,items 是数据 map 是名称映射表
// 如果名称本来就是按 value 和 text 来命名,就不需要映射表
function createSelect(items, map = {}) {
    const value = map.value || "name";
    const text = map.text || "text";
    const $options = items
        .map(t => $("<option>").prop({ value: t[value] }).text(t[text] || ""));
    return $("<select>").append(...$options);
}
// 创建一个 tr,含 td 和初始化的 select
function createRow() {
    var $tr = $("<tr>");
    var $tds = Array.from(Array(3))
        .map(() => $("<td>"));

    createSelect(types).appendTo($tds[0]);

    createSelect([
        { value: "chazhang", text: "查账征收" },
        { value: "heding", text: "核定征收" }
    ]).appendTo($tds[2]);

    return $tr.append(...$tds);
}

Organisez d'abord les données

Étant donné que la structure DOM est générée sur la base de données, les données sont très importantes. La manière intuitive consiste à rechercher les données en même temps, mais de cette façon, le code semble compliqué. Par conséquent, il est généralement recommandé d'organiser et de préparer d'abord les données correspondantes, puis de générer du DOM basé sur les données organisées

Par exemple, types,就是从 zType_chose est extrait en premier

// 生成类型数据
var types = [{ text: "计算机期类型" }]
    .concat(zType_chose.map(t => ({
        value: t.name,
        text: t.name
    })));

Lors du tri des données de liste, la cartographie, le filtrage et la réduction sont fondamentalement standard (pour des situations plus complexes, vous pouvez envisager des RxJ)

Vous avez changé l'identifiant en classe, ce qui est bien et ouvre la voie pour une utilisation ultérieure $.fn.close(). Comme je n'ai pas beaucoup de temps pour m'en occuper davantage, je vous laisse la question : envisagez de définir select en HTML, puis gérez les détails (comme le masquage) dans le code. Si la sélection doit encore être définie en fonction des données, vous pouvez remplir toute la première sélection au début pour faciliter le clonage ultérieur - bien sûr, dans ce cas, le processus de perfectionnement de tr est encapsulé dans une fonction, et vous ne le faites pas. même besoin de cloner. Vous pouvez également créer tr directement.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal