功能相同,保留变量/元素

时间:2018-08-23 17:32:06

标签: javascript jquery

我正在创建一个可创建模式的javascript函数。功能如下:

    function createModal(options) {
        var self = this;
        modalHeaderText = options.header;
        modalBodyText = options.body;
        $modal = $('<div />').addClass('modal').appendTo('body');
        $modalOverlay = $('<div />').addClass('modal-overlay').appendTo($modal);
        $modalContainer = $('<div />').addClass('modal-container').appendTo($modal);
        $modalHeader = $('<div />').addClass('modal-header').addClass(options.headerClass).html(modalHeaderText).appendTo($modalContainer);
        $modalBody = $('<div />').addClass('modal-body').addClass(options.bodyClass).html(modalBodyText).appendTo($modalContainer);
        if (options.buttons) {
            $modalFooter = $('<div />').addClass('modal-footer').appendTo($modalContainer);
            $.each(options.buttons, function(name, buttonOptions) {
                $modalButton = $('<button />').addClass(buttonOptions.class).html(name).appendTo($modalFooter);
                if(buttonOptions.callback) {
                    $modalButton.on('click', function() { 
                        buttonOptions.callback(); 
                    });
                } else {
                    $modalButton.on('click', function(e) { 
                        $modal.remove();
                    });
                };
            });
        };
        $modal.addClass('active');
        if (options.closeOnOverlayClick == true) {
            $modalOverlay.on('click', function(e) {
                $modal.remove();
            });
        };
    };

这很好用,但是我希望能够在同一个函数中调用该函数,如下所示:

    $('#modal').on('click', function(e){
        e.preventDefault();
        createModal({
            header      : 'Enter your name',
            body        : '<input type="text" class="name" />',
            buttons     : {
                'OK'    : {
                    class : 'btn btn-success',
                    callback : function() {
                        var name = self.$modalBody.find('.name').val();
                        if (!name) {
                            createModal({
                                header      : 'Error',
                                body        : 'You must provide a name',
                                buttons     : {
                                    'OK'    : {
                                        class : 'btn'
                                    }
                                }
                            });
                        } else {
                            alert(name);
                        };
                    },
                },
                'Close' : {
                    class : 'btn btn-error'
                }
            }
        });
    });

我想要的是以下内容:当某人单击ID为“ modal”的按钮(因此为“ #modal”)时,将打开一个带有输入的模式。当按下OK按钮时,它将检查输入(“名称”)是否具有值。如果是这样,该值将显示在警报中。如果不是,则使用文本“您必须提供名称”对新模式进行开放式设置(在当前模式之上)。

如果输入名称,则可以使用。名称显示在警报中,并且关闭按钮也起作用。但是,如果我没有输入名称,并且显示了第二个模式,则该函数中的所有变量都将被覆盖。

如何保留第一个模态中的变量/元素,以便在显示(清除)第二个模态后,第一个模态中的按钮仍然有效。

我在这里创建了一个JSFiddle:https://jsfiddle.net/6pq7ce0a/2/

您可以像这样测试它:

1)点击“开放模式” 2)输入名称 3)点击“确定” 4)名称显示在警报中 ==>可行

问题在这里:

1)点击“开放模式” 2)不要输入名字 3)点击“确定” 4)显示了一个新的模态 5)在新(错误)模式中单击“确定” 6)第一个模式中的按钮(带有输入字段)不再起作用

提前谢谢!

更新

如果我将功能更改为以下功能,则第一个模态根本不起作用。

    function createModal(options) {
        var self = this;
        var modalHeaderText = options.header;
        var modalBodyText = options.body;
        var $modal = $('<div />').addClass('modal').appendTo('body');
        var $modalOverlay = $('<div />').addClass('modal-overlay').appendTo($modal);
        var $modalContainer = $('<div />').addClass('modal-container').appendTo($modal);
        var $modalHeader = $('<div />').addClass('modal-header').addClass(options.headerClass).html(modalHeaderText).appendTo($modalContainer);
        var $modalBody = $('<div />').addClass('modal-body').addClass(options.bodyClass).html(modalBodyText).appendTo($modalContainer);
        if (options.buttons) {
            var $modalFooter = $('<div />').addClass('modal-footer').appendTo($modalContainer);
            $.each(options.buttons, function(name, buttonOptions) {
                var $modalButton = $('<button />').addClass(buttonOptions.class).html(name).appendTo($modalFooter);
                if(buttonOptions.callback) {
                    $modalButton.on('click', function() { 
                        buttonOptions.callback(); 
                    });
                } else {
                    $modalButton.on('click', function(e) { 
                        $modal.remove();
                    });
                };
            });
        };
        $modal.addClass('active');
        if (options.closeOnOverlayClick == true) {
            $modalOverlay.on('click', function(e) {
                $modal.remove();
            });
        };
    };

问题在这里:

var name = self.$modalBody.find('.name').val();

如果我将'var'添加到所有元素中,则未定义$ modalBody。

2 个答案:

答案 0 :(得分:3)

因此,除了上面关于不声明var的注释之外,您还将对window的引用存储在self变量中。为了避免所有这些,我在这个小提琴中走了一条路:https://jsfiddle.net/10fanzw6/1/

快速解释。

  • 首先不要将this分配给self,因为this是窗口
  • 第二次将所有内容分配给空的self对象以及本地var(以提高可读性)
  • 第三次将self变量传递回任何按钮回调,使您可以访问所需模态的任何部分。

对于后代,包括此处的更新功能:

function createModal(options) {
  var self = {};
  var modalHeaderText = options.header;
  var modalBodyText = options.body;
  var $modal = self.$modal = $('<div />').addClass('modal').appendTo('body');
  var $modalOverlay = self.$modalOverlay = $('<div />').addClass('modal-overlay').appendTo($modal);
  var $modalContainer = self.$modalContainer = $('<div />').addClass('modal-container').appendTo(self.$modal);
  self.$modalHeader = $('<div />').addClass('modal-header').addClass(options.headerClass).html(modalHeaderText).appendTo($modalContainer);
  self.$modalBody = $('<div />').addClass('modal-body').addClass(options.bodyClass).html(modalBodyText).appendTo($modalContainer);
  if (options.buttons) {
    var $modalFooter = self.$modalFooter = $('<div />').addClass('modal-footer').appendTo($modalContainer);
    $.each(options.buttons, function(name, buttonOptions) {
      var $modalButton = $('<button />').addClass(buttonOptions.class).html(name).appendTo($modalFooter);
      if (buttonOptions.callback) {
        $modalButton.on('click', function() {
          buttonOptions.callback(self);
        });
      } else {
        $modalButton.on('click', function(e) {
          $modal.remove();
        });
      };
    });
  };
  $modal.addClass('active');
  if (options.closeOnOverlayClick == true) {
    $modalOverlay.on('click', function(e) {
      $modal.remove();
    });
  };
};
$('#modal').on('click', function(e) {
  e.preventDefault();
  createModal({
    header: 'Enter your name',
    body: '<input type="text" class="name" />',
    buttons: {
      'OK': {
        class: 'btn btn-success',
        callback: function(modal) {
          var name = modal.$modalBody.find('.name').val();
          if (!name) {
            createModal({
              header: 'Error',
              body: 'You must provide a name',
              buttons: {
                'OK': {
                  class: 'btn'
                }
              }
            });
          } else {
            alert(name);
          };
        },
      },
      'Close': {
        class: 'btn btn-error'
      }
    }
  });
});

答案 1 :(得分:0)

仅不使用var变量前面的$modal导致变量存储在窗口范围内。当下一个下一个$ modal关闭时,该变量引用的是一个已经删除的元素,因此在第一个模式的Close按钮上单击时什么也没有发生。