You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义元素中在XMLHttpRequest回调内调用组件方法的问题

自定义HTML元素StaffList回调中访问组件方法的问题解决

问题描述

编写自定义HTML元素StaffList时遇到以下问题:

  • 在connectedCallback()方法中通过XMLHttpRequest请求数据后,调用组件的addStaff方法时,用super会触发语法错误:Uncaught SyntaxError: use of super property accesses only valid within methods or eval code within methods
  • 用this时,this指向XMLHttpRequest对象而非自定义元素实例,导致无法调用组件方法

原代码(注:原代码存在语法错误,addStaff方法需移至类内部):

class StaffList extends HTMLElement {

  // selected属性的getter/setter
  get selected() {
    return this.hasAttribute('selected');
  }
  set selected(val) {
    if (val) {
      this.setAttribute('selected', '');
    } else {
      this.removeAttribute('selected');
    }
  }

  constructor() {
    super();
    // 绑定子元素点击事件
    for (const item of this.children) {
      item.addEventListener('click', e => {
        console.log(e);
      });
    }
  }

  connectedCallback() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        for (var item of JSON.parse(this.responseText)) {
          console.log(item);
          this.addStaff(item);
        }
      }
    };
    xhttp.open('GET', "/api/get_staff");
    xhttp.send();
  }

  // 修正:将addStaff移至类内部
  addStaff(item) {
    console.log("add staff", item);
  }
}

customElements.define('staff-list', StaffList);

问题原因

  • 传统函数作为onreadystatechange回调时,this会绑定到调用它的对象(即XMLHttpRequest实例),而非自定义元素实例
  • super只能在类的方法内部使用,回调函数不属于类的方法,因此使用super会触发语法错误

解决方法

方法1:使用箭头函数

箭头函数不会绑定自身的this,会继承外层作用域的this(即StaffList实例):

connectedCallback() {
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = () => {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      for (const item of JSON.parse(xhttp.responseText)) {
        console.log(item);
        this.addStaff(item); // this指向StaffList实例
      }
    }
  };
  xhttp.open('GET', "/api/get_staff");
  xhttp.send();
}

方法2:提前保存组件实例到变量

在connectedCallback中先将组件实例的this保存到变量,回调中使用该变量:

connectedCallback() {
  const self = this; // 保存组件实例引用
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      for (const item of JSON.parse(this.responseText)) {
        console.log(item);
        self.addStaff(item); // 使用self访问组件实例
      }
    }
  };
  xhttp.open('GET', "/api/get_staff");
  xhttp.send();
}

方法3:使用bind绑定this

通过bind方法将回调函数的this强制绑定到组件实例:

connectedCallback() {
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      for (const item of JSON.parse(this.responseText)) {
        console.log(item);
        this.addStaff(item); // this指向StaffList实例
      }
    }
  }.bind(this); // 绑定组件实例到回调的this
  xhttp.open('GET', "/api/get_staff");
  xhttp.send();
}

额外建议:使用fetch替代XMLHttpRequest

现代浏览器推荐使用fetch API,基于Promise的写法更简洁易读:

async connectedCallback() {
  try {
    const response = await fetch("/api/get_staff");
    const staffList = await response.json();
    for (const item of staffList) {
      this.addStaff(item);
    }
  } catch (error) {
    console.error('获取员工数据失败:', error);
  }
}

内容的提问来源于stack exchange,提问作者user21776820

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:22:51