扩展HTMLElement:使用webpack时构造函数失败

mbu*_*bue 19 javascript web-component typescript webpack

我将以下TypeScript程序转换为ES5:

档案1:

class BaseElement extends HTMLElement {
    constructor() {
        super();
    }
}
Run Code Online (Sandbox Code Playgroud)

文件2:

import {BaseElement} from './BaseElement';

class MyElement extends BaseElement {
    constructor() {
        super();
    }
}

var el = new MyElement();
Run Code Online (Sandbox Code Playgroud)

将所有内容手动放入文件中,代码工作正常并在浏览器中执行,HTMLElement构造没有问题.但是,只要我通过webpack打包它,我收到以下错误消息:

Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
Run Code Online (Sandbox Code Playgroud)

没有webpack,构造了以下JS代码:

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var BaseElement = (function (_super) {
    __extends(BaseElement, _super);
    function BaseElement() {
        _super.call(this);
    }
    return BaseElement;
}(HTMLElement));
var MyElement = (function (_super) {
    __extends(MyElement, _super);
    function MyElement() {
        _super.call(this);
    }
    MyElement.prototype.createdCallback = function () {
        this.innerHTML = "lol";
    };
    return MyElement;
}(BaseElement));
var el = new MyElement();
Run Code Online (Sandbox Code Playgroud)

使用webpack,构造以下代码:

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};

/******/    // The require function
/******/    function __webpack_require__(moduleId) {

/******/        // Check if module is in cache
/******/        if(installedModules[moduleId])
/******/            return installedModules[moduleId].exports;

/******/        // Create a new module (and put it into the cache)
/******/        var module = installedModules[moduleId] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = true;

/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }


/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;

/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);
    __webpack_require__(2);

/***/ },
/* 1 */
/***/ function(module, exports) {

    "use strict";
    var BaseElement = (function (_super) {
        __extends(BaseElement, _super);
        function BaseElement() {
            _super.call(this);
        }
        return BaseElement;
    }(HTMLElement));
    exports.BaseElement = BaseElement;


/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

    "use strict";
    var BaseElement_1 = __webpack_require__(1);
    var MyElement = (function (_super) {
        __extends(MyElement, _super);
        function MyElement() {
            _super.call(this);
        }
        MyElement.prototype.createdCallback = function () {
            this.innerHTML = "lol";
        };
        return MyElement;
    }(BaseElement_1.BaseElement));
    exports.MyElement = MyElement;
    // TODO: inject
    var p = new MyElement();
/***/ }
/******/ ]);
Run Code Online (Sandbox Code Playgroud)

基本上,webpack将任何模块放入一个函数中并在它们之间维护一个导出变量,但是HTMLElement的构造失败了.没有webpack(上面的代码),它工作正常.

有任何想法吗?

Ami*_*mit 14

这是一个转发问题.如果您正在转换或使用ES5,那么您需要为具有本机Web组件支持的浏览器捆绑native-shim.(https://github.com/webcomponents/custom-elements/blob/master/src/native-shim.js)

ES5样式的类不适用于本机自定义元素,因为HTMLElement构造函数使用值new.target来查找当前调用的构造函数的自定义元素定义.new.target仅在new调用时设置,并且仅通过super()调用传播.在ES5中,super()不可模拟.SuperClass.call(this)`` only works when extending other ES5-style classes, and does not propagatenew.target` 的模式.

查看问题讨论https://github.com/webcomponents/custom-elements/issues/29

  • 我们总是欢迎指向潜在解决方案的链接,但请[在链接上添加上下文](http://meta.stackexchange.com/a/8259),以便您的其他用户能够了解它是什么以及它为何存在.如果目标站点无法访问或永久脱机,请始终引用重要链接的最相关部分.考虑到只是链接到外部网站的可能性是[为什么以及如何删除某些答案?](http://stackoverflow.com/help/deleted-answers). (4认同)
  • 在我的项目中添加了 `native-shim.js`,它解决了这个问题。谢谢 (2认同)

小智 7

ES5风格的类不适用于本机自定义元素

要变通,只需将tsconfig.json文件中的目标更改为es6。