重用导入的 Web 组件模板

re-use imported Web Component template

我构建了一个 Web 组件(我是新手,不是 Javascript 专家)并将其注入 Shadow DOM。但是,我想在页面上多次使用这个模板。我发现组件的私有作用域被复用了,这不是我想要的。我想要重复的组件。

index.html

<body>
<my-template id="data1" data="data.json" ></my-template>
<br/>
<br/>

<my-template id="data2" data="data.json"></my-template> 

这是模板初始化和脚本

我的-template.html

(function (doc) {

    var data;
    var id;
    var total = 0;
    var template;
    var root;
    var totalSelected;
    var container;

    // This element will be registered to index.html
    // Because `document` here means the one in index.html
    var XComponent = document.registerElement('my-template', {
        prototype: Object.create(HTMLElement.prototype, {
            createdCallback: {
                value: function() {
                    root = this.createShadowRoot();
                    // use doc instead of document or document.currentScript.ownerDocument
                    template = doc.querySelector('#template');
                    var clone = document.importNode(template.content, true);
                    root.appendChild(clone);
                    data = this.getAttribute('data');
                    id = this.getAttribute('id');
                    init();
                }
            }
        })
    });

    function init(){

        console.log('init ',id);

        // create input field
        totalSelected = document.createElement('input');
        totalSelected.type = 'text';
        totalSelected.id = 'total-selected'+id;
        totalSelected.addEventListener("click", showList);

        root.appendChild(totalSelected);

        // values container
        container = document.createElement('div');
        container.id = 'container'+id;
        container.className = 'container';

        for(var i=0 ; i < 3; i++){

            var row = document.createElement('div');
            row.id = 'row-'+i+'-'+id;
            container.appendChild(row);
        }

        root.appendChild(container);

    }

    return {
        append : append,
        showList : showList,
        hideList : hideList
    }



    function showList() {
        console.log('showList', container);
        container.style.display = 'block';
    }

    function hideList() {
        container.style.display = 'none';
    }

})(document.currentScript.ownerDocument); // pass document of x-component.html

现在,当我单击输入字段时,总是会打开 "data2"。这意味着当点击 data1 组件时,变量被 data2 init 覆盖:(

当我创建第二个 html 并将其注册为 my-template2.html 时,显然一切正常,但(显然)我不想要这个。

如何使用它自己的初始化来重复这个模板?有可能吗?

因为你定义的所有变量:

var data;
var id;
var total = 0;
var template;
var root;
var totalSelected;
var container;

... 是全局的,然后共享给您的所有元素。

为避免这种情况,有多种解决方案。

1) 将它们设置为自定义元素对象本身的属性,并将方法附加到原型:

prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {
        value: function() {
            this.data = this.getAttributes( 'data' )
            //this.id is automatically set
            ...
            this.init()
        }
    },
    init: {
        value: function() {
            this.container = ...
        }
    }

2) 定义一个将它们全部集中的对象:

this.vm = {
    data: this.getAttribute( 'data' )
    id: this.getAttribute( 'id' )
}

3) 将它们放在闭包中,例如 createdCallback:

createdCallback: {
    value: function() {
        var data = this.getAttribute( 'data' )
        var id = this.id  
        init()
        function init() {...}
        function showList() {...}      
    }
}