首页 文章

从Typescript转换为ECMAScript 5的自定义元素v1在IE11下失败

提问于
浏览
2

在转换为ES5时,我遇到了一个简单的Web组件工作的麻烦 . 它看起来在chrome,Edge和Firefox下运行得非常好,但IE11在组件的构造函数中失败了“自定义元素构造函数没有生成要升级的元素 . ”

更新

下面的Oliver Krull的出色工作明确地将问题归结为Typescript的编译器输出 . 它可以使它工作吗?

原始源(在TypeScript中):

import "./AppDrawer.less"

class AppDrawer extends HTMLElement {
    get open() {
        return this.hasAttribute("open");
    }

    set open(val: boolean) {
        val ? this.setAttribute("open", '') : this.removeAttribute('open');
    }

    get disabled() {
        return this.hasAttribute("disabled");
    }

    set disabled(val: boolean) {
        val ? this.setAttribute("disabled", '') : this.removeAttribute('disabled');
    }

    static get observedAttributes() { return ["open"] };

    constructor() {
        super();
    }

    connectedCallback() {
        this.addEventListener("click", () => {
            this.open = !this.open;
        })
        this.textContent = this.open ? "OPEN": "CLOSED";
    }

    attributeChangedCallback(attr, oldVal, newVal) {
        this.textContent = this.open ? "OPEN": "CLOSED";
    }
}


customElements.define("app-drawer", AppDrawer)

输出( bundle.js ):

(function () {
'use strict';

function __$styleInject(css) {
    if (!css) return;

    if (typeof window == 'undefined') return;
    var style = document.createElement('style');
    style.setAttribute('media', 'screen');

    style.innerHTML = css;
    document.head.appendChild(style);
    return css;
}

__$styleInject("app-drawer {\n  color: red;\n}\n");

function __extends(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 AppDrawer = (function (_super) {
    __extends(AppDrawer, _super);
    function AppDrawer() {
        _super.call(this);
    }
    Object.defineProperty(AppDrawer.prototype, "open", {
        get: function () {
            return this.hasAttribute("open");
        },
        set: function (val) {
            val ? this.setAttribute("open", '') : this.removeAttribute('open');
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AppDrawer.prototype, "disabled", {
        get: function () {
            return this.hasAttribute("disabled");
        },
        set: function (val) {
            val ? this.setAttribute("disabled", '') : this.removeAttribute('disabled');
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AppDrawer, "observedAttributes", {
        get: function () { return ["open"]; },
        enumerable: true,
        configurable: true
    });

    AppDrawer.prototype.connectedCallback = function () {
        var _this = this;
        this.addEventListener("click", function () {
            _this.open = !_this.open;
        });
        this.textContent = this.open ? "OPEN" : "CLOSED";
    };
    AppDrawer.prototype.attributeChangedCallback = function (attr, oldVal, newVal) {
        this.textContent = this.open ? "OPEN" : "CLOSED";
    };
    return AppDrawer;
}(HTMLElement));
customElements.define("app-drawer", AppDrawer);

}());

我的HTML:

<!doctype html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/webcomponents-lite.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/custom-elements-es5-adapter.js"></script>
        <script src="bundle.js"></script>
    </head>
    <body>
        <app-drawer open disabled></app-drawer>
    </body>
</html>

2 回答

  • 2

    为了让custom elements v1工作跨浏览器,我们需要添加this native-shim(here关于它的更多信息) .

    这适用于所有主流浏览器(边缘,Safari,Firefox等)但不在ie11中!

    当我们尝试在ie11中导入它时,我们得到了一堆语法错误,因为shim是用一些es6编写的 .

    一个简单的解决方法是将填充程序编译为es5并添加es6版本(首先是es6,然后是es5以省略错误) .

    这不是最干净的解决方案,但至少它可行 .

    我创建了一个带有工作示例的repo(您的app-drawer(由于冲突而删除了 disabled 属性)) .

    再次,它不是干净但它的工作;-)

  • 4

    问题是Typescript的ES5类实现与 custom-elements-v1 垫片不兼容 . 那么,显而易见的解决方案是配置TypeScript以生成ES6并将其传递给Babel以进行转换 .

    let rollupTs = rollupTypescript(require('./tsconfig.json').compilerOptions);
    
    rollup({
        entry: "src/client/main.ts",
        plugins: [
            rollupTs,
            less({insert: true}),
            resolve({module: true, jsnext: true, main: true}),
            babel({
                presets: [
                    [es2015, { modules: false } ]
                ],
                plugins: ["external-helpers"],
                exclude: "node_modules/**"})
        ],
        dest: "bundle.js",
        format: "iife"
    })
    

    然而,看到接受的答案 - 似乎通过将es5转换后的填充添加到打字稿生成的代码修复,TypeScript 's ES5, while having no effect on babel compiled code. I' ve接受了它,因为它对于这个问题是一个相当简单的插入修复,并且我实际上并不理解的警告它为何有效

相关问题