0

写真を送信するフォーム(合計8つ)があり、小さな効果を適用しようとしています。写真を選択すると、ボタンが非表示になり、ファイル名が「X」とともに表示されて削除されます。その選択。

ただし、複数の写真を追加して1つを削除しようとすると、イベントが複数回呼び出され、クリックするほど、すべて同じ要素から複数のイベントが発生します。

誰かがそれを理解できますか?

var Upload =  {
    init: function ( config ) {
        this.config = config;
        this.bindEvents();
        this.counter = 1;
    },

    /**
     * Binds all events triggered by the user.
     */
    bindEvents: function () {
        this.config.photoContainer.children('li').children('input[name=images]').off();
        this.config.photoContainer.children('li').children('input[name=images]').on("change", this.photoAdded);
        this.config.photoContainer.children('li').children('p').children('a.removePhoto').on('click', this.removePhoto);
    },

    /**
     * Called when a new photo is selected in the input.
     */
    photoAdded: function ( evt ) {
        var self = Upload,
            file = this.files[0];
        $(this).hide();
        $(this).parent().append('<p class="photo" style="background-color: gray; color: white;">' + file.name + ' <a class="removePhoto" style="color: red;" href="#">X</a></p>');

        if(self.counter < 8) {  // Adds another button if needed.
            Upload.config.photoContainer.append( '<li><input type="file" name="images"></li>');
            self.counter++;
        } 
        Upload.bindEvents();
    },

    /**
     * Removes the <li> from the list.
     */
    removePhoto: function ( evt ) {
        var self = Upload;
        evt.preventDefault();

        $(this).off();
        $(this).parent().parent().remove();

        if(self.counter == 8) { // Adds a new input, if necessary.
            Upload.config.photoContainer.append( '<li><input type="file" name="images"></li>');
        }
        self.counter--;
        Upload.bindEvents();
    }
}

Upload.init({
    photoContainer: $('ul#photo-upload')
});
4

2 に答える 2

2

あなたはたくさんのことをしています:Upload.bindEvents();

それらを再度バインドする前に、それらの'liのイベントのバインドを解除する必要があります。それ以外の場合は、クリックイベントをさらに追加します。そのため、クリック数が増えています。

于 2012-08-08T16:46:42.107 に答える
2

私が見たところ、ユーザーが選択したものに基づいてイベントハンドラーをアタッチ/削除しようとしています。これは非効率的で、エラーが発生しやすくなります。

あなたの場合、Upload.bindEvents()以前のすべてのハンドラーをクリーンアップせずに、写真が追加されるたびに呼び出しています。イベントリスナーをリークしなくなるまでデバッグすることもできますが、それだけの価値はありません。

jQuery.onは非常に強力であり、まだDOMにない要素にハンドラーをアタッチできます。あなたはこのようなことをすることができるはずです:

init: function ( config ) {
  this.config = config;
  this.counter = 1;
  this.config.photoContainer.on('change', 'li > input[name=images]', this.photoAdded);
  this.config.photoContainer.on('click', 'li > p > a.removePhoto', this.removePhoto);
},

にハンドラーを1つだけアタッチしますphotoContainer。これにより、子がいつ追加されたかに関係なく、子からバブリングするすべてのイベントがキャッチされます。要素の1つでハンドラーを無効にする場合は、removePhotoクラスを削除する必要があります(フィルターと一致しないようにするため)。

于 2012-08-08T16:49:30.730 に答える