如何从调用同一类的方法的javascript类render方法添加click事件?

时间:2018-05-22 16:15:10

标签: javascript class mouseclick-event

我有一个JS类:

class MyClass {
    constructor() {
    }

    handleClick() {
        alert('clicked');
    }

    render() {
        return `<input type="radio" onClick="${this.handleClick} /><label>My Label</label>"`;
    }
}

window.addEventListener('load', init);

function init() {
    const myClassInstance = new MyClass();
    const el = document.getElementsByClassName('myelement')[0];
    el.insertAdjacentHTML('beforeend', myClassInstance.render());
}

这会在元素中使用类myelement呈现无线电输入,但是当我单击单选按钮时,我会看到:

Uncaught SyntaxError: Unexpected token {

错误是指handleClick方法。

我的语法是否关闭?如果我使用onClick="${this.handleClick()}",我就不会看到错误,但会立即调用该函数而不是单击。我做错了什么?

2 个答案:

答案 0 :(得分:0)

您最好的选择是不使用标记,因为您从onxyz - 属性样式事件处理程序调用的函数必须是全局的。

相反,创建元素然后将函数分配给它:

class MyClass {
    constructor() {
    }

    handleClick(e) {
        alert('clicked');
    }

    render() {
        var input = document.createElement("input");
        input.type = "radio";
        input.addEventListener("click", e => this.handleClick(e));
        return input;
    }
}

window.addEventListener('load', init);

function init() {
    const myClassInstance = new MyClass();
    const el = document.getElementsByClassName('myelement')[0];
    el.appendChild(myClassInstance.render());
}
<div class="myelement"></div>

请注意使用箭头功能,以便在我们调用thisthis.handleClick正确无误。显然,你不仅仅需要alert,但我想你会想要使用MyClass实例的属性。 (要访问发生点击的元素,请使用e.currentTarget,因为它不是this。)

如果您对使用标记执行此操作有强烈偏好,则选项为:

  • 有一个initEvents方法或类似的方法,让班级的消费者应该打电话(就像他们应该打电话给render
  • 在标记中使用唯一ID
  • 使用该ID查找元素和挂钩事件

或者更好的是:让render接受要添加的元素,并在添加后进行事件连接。

但是使用现有的render方法:

const MyClass = (() => {
  let nextId = 1;
  class MyClass {
      constructor() {
          this.id = `__MyClass__${nextId++}`;
      }

      handleClick(e) {
          alert('clicked');
      }

      render() {
          return `<input type="radio" id="${this.id}" />`;
      }
      
      initEvents() {
          const e = document.getElementById(this.id);
          if (!e) {
              throw new Error("initEvents must be called after appending the markup from render to the DOM");
          }
          e.addEventListener("click", e => this.handleClick(e));
      }
  }
  return MyClass;
})();

window.addEventListener('load', init);

function init() {
    const myClassInstance = new MyClass();
    const el = document.getElementsByClassName('myelement')[0];
    el.insertAdjacentHTML('beforeend', myClassInstance.render());
    myClassInstance.initEvents();
}
<div class="myelement"></div>

答案 1 :(得分:0)

如果你想要这个onclick工作,那么你需要将全局函数分配给class MyClass { constructor() {} handleClick() { alert('clicked'); } render() { const globalId = "h" + Math.floor((Math.random() * 100) + 12345); window[globalId] = this.handleClick; return `<input type="radio" onClick=window['${globalId}']() />`; } } window.addEventListener('load', init); function init() { const myClassInstance = new MyClass(); const el = document.getElementsByClassName('myelement')[0]; el.insertAdjacentHTML('beforeend', myClassInstance.render()); }否则你不能这样做我做了快速修复它只是一个临时解决方案你可以选择这个或@TJ答案也很好看。

<div class="myelement"></div>
 @Html.EditorFor(x => x.FirstName, new { htmlAttributes = new { @class = "form-control", required = "required", title = "User First Name is required"} })
    @Html.ValidationMessageFor(x => x.FirstName,"", new { @class = "text-danger" })
<!-- NextOfKin entry -->
@Html.EditorFor(y => y.FirstName, new { htmlAttributes = new { @class = "form-control", required = "required", title = "Next Of Kin First Name is required"} })
    @Html.ValidationMessageFor(y => y.FirstName,"", new { @class = "text-danger" })