【问题标题】:How can I write my listener function somewhere else if it uses local variables?如果它使用局部变量,我如何在其他地方编写我的侦听器函数?
【发布时间】:2016-12-04 16:56:29
【问题描述】:

我是 Javascript 开发的初学者,我必须做经典的待办事项应用程序。它必须是面向对象的,我的程序有两个类:Task 和 Tag。 一个任务包含一些标签。

当用户点击一个标签时,他可以修改它的名字。首先,我确实写了一个匿名回调函数,它正在监听修改表单提交,并且运行良好。但是,我必须创建一个在其他地方声明的命名函数,而不是我现有的侦听器。但是,我需要访问我的对象(已编辑)的一些属性,我完全不知道如何做这样的事情。

这是我的一小部分代码:

  module.Tag = class Tag {
      constructor(name = 'untitled', parent = null) {
          this.name = name;
          this.parentTask = parent;
      }

      //Method which displays the tag name
      display_name() {
        return $('<li>').addClass('tag').text(this.name);      
      }

      //Method which displays the tag
      display() {
        let tag_item = this.display_name();

        let field = $('<input>').prop('type', 'text').prop('value', this.name);
        let button = $('<button>').addClass('validationButton').prop('type', 'submit').text('✓');
        let removeButton = $('<button>').addClass('removeButton').text('X');
        let form = $('<form>').append(field).append(button).append(removeButton);
        let in_edit = false;

        tag_item.click((event) => {
          event.stopPropagation();
          event.preventDefault();

          let target = $(event.target);

          if (target.is('li') && !in_edit) {
            tag_item.empty();
            tag_item.append(form);
            in_edit = true;          
          }

          if (target.is('button') && target.prop('type') === 'submit') {
            if(field.val() !== '') {
              this.name = field.val(); 
              module.StorageManager.storeTasks();
            }

            tag_item.empty();
            tag_item.text(this.name);

            field.val(this.name);

            in_edit = false;
          }

          if (target.is('button') && target.hasClass('removeButton')) {
            if(confirm('Voulez-vous vraiment supprimer ce tag ?')) {
              tag_item.remove();
              this.removeTagFromParent();

              module.StorageManager.storeTasks();  
            }
          }
       });

       return tag_item;
     }

     //Method which removes the tag from the parent task
     removeTagFromParent() {
       this.parentTask.removeTag(this);
     }
  }; 

我的监听器在 display 方法中,它使用Tag.name 属性和在方法体中创建的一些变量。我看不到如何在其他地方编写此函数,Google 也没有帮助我。

我希望我的问题很清楚,英语不是我的母语。 有什么建议吗?

【问题讨论】:

  • "我必须创建一个在其他地方声明的命名函数,而不是我现有的侦听器" - 为什么?使用有效的代码。
  • 使用闭包。
  • 如果我的教授没有要求我在其他地方执行特定功能,我会这样做。另一个原因是我的代码的另一部分有相同的侦听器,如果我找到解决问题的方法,我可以避免重复代码。
  • 尽管我进行了反思,但我无法找到闭包对我的帮助。正如我所说,我是一个初学者,许多明显的做法对我来说还不自然。
  • 保留监听器的现有函数表达式,但不保留其主体。通过调用命名函数来替换函数内部的所有内容,并将您需要的任何参数和局部变量作为参数传递给它。

标签: javascript jquery oop


【解决方案1】:

您可以将您的匿名函数提取为另一个类方法。它是一个事件处理程序,因此为了正确访问已定义的对象,您必须正确绑定它。

以下是修改后的脚本示例:

module.Tag = class Tag {
      constructor(name = 'untitled', parent = null) {
          this.name = name;
          this.parentTask = parent;
      }

      //Method which displays the tag name
      display_name() {
        return $('<li>').addClass('tag').text(this.name);      
      }

      //Method which displays the tag
      display() {
        let tag_item = this.display_name();

        let field = $('<input>').prop('type', 'text').prop('value', this.name);
        let button = $('<button>').addClass('validationButton').prop('type', 'submit').text('✓');
        let removeButton = $('<button>').addClass('removeButton').text('X');
        let form = $('<form>').append(field).append(button).append(removeButton);
        let in_edit = false;

        tag_item.click(this.handleClick.bind(this));  
        // this is where you invoke the function and 
        //bind it to the context of the class

       return tag_item;
     }

     //Method which removes the tag from the parent task
     removeTagFromParent() {
       this.parentTask.removeTag(this);
     }

     // extracted method defined here:
      handleClick(event) {
          let tag_item = this.display_name();
          let field = $('').prop('type', 'text').prop('value', this.name);
          event.stopPropagation();
          event.preventDefault();

          let target = $(event.target);

          if (target.is('li') && !in_edit) {
            tag_item.empty();
            tag_item.append(form);
            in_edit = true;          
          }

          if (target.is('button') && target.prop('type') === 'submit') {
            if(field.val() !== '') {
              this.name = field.val(); 
              module.StorageManager.storeTasks();
            }

            tag_item.empty();
            tag_item.text(this.name);

            field.val(this.name);

            in_edit = false;
          }

          if (target.is('button') && target.hasClass('removeButton')) {
            if(confirm('Voulez-vous vraiment supprimer ce tag ?')) {
              tag_item.remove();
              this.removeTagFromParent();

              module.StorageManager.storeTasks();  
            }
          }
       }
  }; 

【讨论】:

  • 感谢您的回答。另一个问题是我必须在我的 Tag 类之外编写函数,所以我无法访问 'this.name' 或 'this.display_name()'。
  • 要在类之外使用函数,您可以在它之外提取名称函数体“handclick”。然后,您必须修改函数以接受参数以处理标记项目类的范围或直接参数以接受 tag_item 和字段的值。
  • 很高兴我能帮上忙 :-)
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多