JavaScript ES6导入/导出和类扩展

JavaScript ES6导入/导出和类扩展,javascript,html,ecmascript-6,webpack,es6-class,Javascript,Html,Ecmascript 6,Webpack,Es6 Class,我构建了一个自定义元素,它是一个汉堡按钮,现在我正在制作一个侧导航。在这个侧导航中,我想使用我的汉堡按钮,因此我尝试导出与我的按钮对应的HCHamburger类,并将其导入我的SideNav类。这样做的目的是在侧导航打开时设置按钮位置的动画。我试图用HCHamburger扩展我的SideNav类,但我得到了以下错误:uncaughttypeerror:构造“HTMLElement”失败:请使用“new”运算符,此DOM对象构造函数不能作为函数调用。 我的HCHambuger类如下所示: 'use

我构建了一个自定义元素,它是一个汉堡按钮,现在我正在制作一个侧导航。在这个侧导航中,我想使用我的汉堡按钮,因此我尝试导出与我的按钮对应的
HCHamburger
类,并将其导入我的
SideNav
类。这样做的目的是在侧导航打开时设置按钮位置的动画。我试图用
HCHamburger
扩展我的
SideNav
类,但我得到了以下错误:
uncaughttypeerror:构造“HTMLElement”失败:请使用“new”运算符,此DOM对象构造函数不能作为函数调用。

我的HCHambuger类如下所示:

'use strict';

export default class HCHamburger extends HTMLElement {

    get menuButton() {
        if (!this._menuButton) {
            this._menuButton = this.querySelector('.hamburger-menu');
        }

        return this._menuButton;
    }

    get bar() {
        if (!this._bar) {
            this._bar = this.querySelector('.bar');
        }

        return this._bar;
    }

    attachedCallback() {
        this.menuButton.addEventListener('click', _ => {
            const sideNavContainerEl = document.querySelector('.js-side-nav-container');
            this.bar.classList.toggle("animate");
            if (sideNavContainerEl.getAttribute('nav-opened') == 'false') {
                this.openMenuButton(sideNavContainerEl);
            } else {
                this.closeMenuButton(sideNavContainerEl);
            }
        });
    }

    sayHello() {
        console.log('TOTO');
    }

    openMenuButton(sideNavContainerEl) {
        this.style.transform = `translateX(${sideNavContainerEl.offsetWidth}px)`;
    }

    closeMenuButton(sideNavContainerEl) {
        this.style.transform = `translateX(0px)`;
    }
}

document.registerElement('hc-hamburger', HCHamburger);
我的SideNav类是这样的:

'use strict';

import Detabinator from './detabinator.js';
import HCHamburger from './hamburger.js';

class SideNav extends HCHamburger {
  constructor () {
    super();
    this.toggleMenuEl = document.querySelector('.js-menu');
    this.showButtonEl = document.querySelector('.js-menu-show');
    this.hideButtonEl = document.querySelector('.js-menu-hide');
    this.sideNavEl = document.querySelector('.js-side-nav');
    this.sideNavContainerEl = document.querySelector('.js-side-nav-container');
    // Control whether the container's children can be focused
    // Set initial state to inert since the drawer is offscreen
    this.detabinator = new Detabinator(this.sideNavContainerEl);
    this.detabinator.inert = true;

    this.toggleSideNav = this.toggleSideNav.bind(this);
    this.showSideNav = this.showSideNav.bind(this);
    this.hideSideNav = this.hideSideNav.bind(this);
    this.blockClicks = this.blockClicks.bind(this);
    this.onTouchStart = this.onTouchStart.bind(this);
    this.onTouchMove = this.onTouchMove.bind(this);
    this.onTouchEnd = this.onTouchEnd.bind(this);
    this.onTransitionEnd = this.onTransitionEnd.bind(this);
    this.update = this.update.bind(this);

    this.startX = 0;
    this.currentX = 0;
    this.touchingSideNav = false;

    this.supportsPassive = undefined;
    this.addEventListeners();
  }

  // apply passive event listening if it's supported
  applyPassive () {
    if (this.supportsPassive !== undefined) {
      return this.supportsPassive ? {passive: true} : false;
    }
    // feature detect
    let isSupported = false;
    try {
      document.addEventListener('test', null, {get passive () {
        isSupported = true;
      }});
    } catch (e) { }
    this.supportsPassive = isSupported;
    return this.applyPassive();
  }

  addEventListeners () {
    this.toggleMenuEl.addEventListener('click', this.toggleSideNav);
    this.sideNavEl.addEventListener('click', this.hideSideNav);
    this.sideNavContainerEl.addEventListener('click', this.blockClicks);

    this.sideNavEl.addEventListener('touchstart', this.onTouchStart, this.applyPassive());
    this.sideNavEl.addEventListener('touchmove', this.onTouchMove, this.applyPassive());
    this.sideNavEl.addEventListener('touchend', this.onTouchEnd);
  }

  onTouchStart (evt) {
    if (!this.sideNavEl.classList.contains('side-nav--visible'))
      return;

    this.startX = evt.touches[0].pageX;
    this.currentX = this.startX;

    this.touchingSideNav = true;
    requestAnimationFrame(this.update);
  }

  onTouchMove (evt) {
    if (!this.touchingSideNav)
      return;

    this.currentX = evt.touches[0].pageX;
    const translateX = Math.min(0, this.currentX - this.startX);

    if (translateX < 0) {
      evt.preventDefault();
    }
  }

  onTouchEnd (evt) {
    if (!this.touchingSideNav)
      return;

    this.touchingSideNav = false;

    const translateX = Math.min(0, this.currentX - this.startX);
    this.sideNavContainerEl.style.transform = '';

    if (translateX < 0) {
      this.hideSideNav();
    }
  }

  update () {
    if (!this.touchingSideNav)
      return;

    requestAnimationFrame(this.update);

    const translateX = Math.min(0, this.currentX - this.startX);
    this.sideNavContainerEl.style.transform = `translateX(${translateX}px)`;
  }

  blockClicks (evt) {
    evt.stopPropagation();
  }

  onTransitionEnd (evt) {
    this.sideNavEl.classList.remove('side-nav--animatable');
    this.sideNavEl.removeEventListener('transitionend', this.onTransitionEnd);
  }

  showSideNav () {
    this.sideNavEl.classList.add('side-nav--animatable');
    this.sideNavEl.classList.add('side-nav--visible');
    this.detabinator.inert = false;
    this.sideNavEl.addEventListener('transitionend', this.onTransitionEnd);
  }

  hideSideNav () {
    this.sideNavEl.classList.add('side-nav--animatable');
    this.sideNavEl.classList.remove('side-nav--visible');
    this.detabinator.inert = true;
    this.sideNavEl.addEventListener('transitionend', this.onTransitionEnd);
  }

  toggleSideNav () {
    if (this.sideNavContainerEl.getAttribute('nav-opened') == 'true') {
      this.hideSideNav();
      this.sideNavContainerEl.setAttribute('nav-opened', 'false');
    } else {
      this.showSideNav();
      this.sideNavContainerEl.setAttribute('nav-opened', 'true');
    }
  }
}

new SideNav();
“严格使用”;
从“/Detabinator.js”导入Detabinator;
从“./hamburger.js”导入HCHamburger;
类SideNav扩展到汉堡包{
构造函数(){
超级();
this.toggleMenuEl=document.querySelector(“.js菜单”);
this.showButtonnel=document.querySelector(“.js菜单显示”);
this.hideButtonEl=document.querySelector(“.js菜单隐藏”);
this.sideNavEl=document.querySelector('.js side nav');
this.sideNavContainerrel=document.querySelector('.js side nav container');
//控制容器的子容器是否可以聚焦
//将初始状态设置为惰性,因为抽屉在屏幕外
this.detabinator=新的detabinator(this.sidenavContainerre);
this.detabinator.惰性=真;
this.toggleSideNav=this.toggleSideNav.bind(this);
this.showSideNav=this.showSideNav.bind(this);
this.hideSideNav=this.hideSideNav.bind(this);
this.blockClicks=this.blockClicks.bind(this);
this.onTouchStart=this.onTouchStart.bind(this);
this.onTouchMove=this.onTouchMove.bind(this);
this.onTouchEnd=this.onTouchEnd.bind(this);
this.onTransitionEnd=this.onTransitionEnd.bind(this);
this.update=this.update.bind(this);
这个.startX=0;
这个.currentX=0;
this.touchingSideNav=false;
this.supportsPassive=未定义;
this.addEventListeners();
}
//如果支持,则应用被动事件侦听
applyPassive(){
if(this.supportsPassive!==未定义){
返回this.supportsPassive?{passive:true}:false;
}
//特征检测
让isSupported=false;
试一试{
addEventListener('test',null,{get passive(){
isSupported=真;
}});
}捕获(e){}
this.supportsPassive=isSupported;
返回这个.applyPassive();
}
addEventListeners(){
this.toggleMenuEl.addEventListener('click',this.toggleSideNav);
this.sideNavEl.addEventListener('click',this.hideSideNav);
this.sidenavContainerre.addEventListener('click',this.blockClicks);
this.sideNavEl.addEventListener('touchstart',this.onTouchStart,this.applyPassive());
this.sideNavEl.addEventListener('touchmove',this.onTouchMove,this.applyPassive());
this.sideNavEl.addEventListener('touchend',this.onTouchEnd);
}
ONTOUCH启动(evt){
如果(!this.sideNavEl.classList.contains('side-nav--visible'))
返回;
this.startX=evt.touch[0].pageX;
this.currentX=this.startX;
this.touchingSideNav=true;
requestAnimationFrame(this.update);
}
onTouchMove(evt){
如果(!this.touchingSideNav)
返回;
this.currentX=evt.touch[0].pageX;
const translateX=Math.min(0,this.currentX-this.startX);
if(translateX<0){
evt.preventDefault();
}
}
onTouchEnd(evt){
如果(!this.touchingSideNav)
返回;
this.touchingSideNav=false;
const translateX=Math.min(0,this.currentX-this.startX);
this.sideNavContainerre.style.transform='';
if(translateX<0){
this.hideSideNav();
}
}
更新(){
如果(!this.touchingSideNav)
返回;
requestAnimationFrame(this.update);
const translateX=Math.min(0,this.currentX-this.startX);
this.sidenavContainerre.style.transform=`translateX(${translateX}px)`;
}
区块点击(evt){
evt.stopPropagation();
}
onTransitionEnd(evt){
this.sideNavEl.classList.remove('side-nav--animatable');
this.sideNavEl.removeEventListener('transitionend',this.onTransitionEnd);
}
showSideNav(){
add('side-nav--animatable');
add('side-nav--visible');
this.detabinator.惰性=false;
this.sideNavEl.addEventListener('transitionend',this.onTransitionEnd);
}
hideSideNav(){
add('side-nav--animatable');
this.sideNavEl.classList.remove('side-nav--visible');
this.detabinator.惰性=真;
this.sideNavEl.addEventListener('transitionend',this.onTransitionEnd);
}
切换SideNav(){
if(this.sideNavContainerre.getAttribute('nav-opened')=='true'){
this.hideSideNav();
this.sideNavContainerre.setAttribute('nav-opened','false');
}否则{
this.showSideNav();
this.sideNavContainerre.setAttribute('nav-opened','true');
}
}
}
新的SideNav();
我正在使用webpack来构建我的JS代码,也许这就是我问题的原因。。。我尝试了不同的导入/导出方法,但没有任何效果

我本想只导出我需要的方法,但它也不起作用


感谢

从根本上说,DOM的API和JavaScript的继承(目前)只是不匹配。您不能在当前浏览器上执行
扩展HtmleElement
操作。您可能能够在某个时间点,当系统稳定下来并以其最终形式被广泛实施时,但是

如果进行传输,您将得到问题中的错误,因为传输的代码尝试按照以下方式执行操作:

函数MyElement(){
HTMLElement.call(this);
}

var e=新的MyElement()自定义元素的ES5注意事项:“新的基于构造函数的自定义元素API与ES5不兼容”