3

私は 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> 

これはテンプレートの初期化とスクリプトです

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 によって上書きされたことを意味します:(

2 番目の html を作成して my-template2.html として登録すると、明らかにすべて機能しますが、(明らかに) これは必要ありません。

独自の init を使用して、このテンプレートを繰り返すにはどうすればよいですか? それは可能ですか?

4

1 に答える 1

1

これは、定義したすべての変数が原因です。

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() {...}      
    }
}
于 2016-11-07T11:24:45.937 に答える