重用导入的 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() {...}
}
}
我构建了一个 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() {...}
}
}