javascript - 重用导入的 Web 组件模板

标签 javascript web-component custom-element html5-template

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

index.html

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

<my-template id="data2" data="data.json"></my-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):

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() {...}      
    }
}

关于javascript - 重用导入的 Web 组件模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40463149/

相关文章:

javascript - 如何增加 React Prop

javascript - 跳过参数以保留 JavaScript 中的默认值

javascript - jQuery - 用其他字符替换找到的字符

web-component - 如何避免在影子 DOM 中重复样式?

javascript - 使用 elm 中的 bootstrap-select

个人 Tumblr 帖子上的 Javascript

web-component - 你如何避免使用 vanilla web 组件的请求 hell ?

javascript - <body> 元素上的 Shadow DOM 是一个坏主意吗?

javascript - 如何将javascript代码结果返回到 polymer 自定义元素的<template>?

css - 可以而且应该设计自定义元素的样式