我正在使用以下代码创建Web组件的实例:
<main></main>
<template id="my-template">
<style>
p { color: green; }
</style>
<p>I'm in Shadow DOM.</p>
</template>
<script>
let tmpl = document.querySelector('#my-template');
class AppDrawer extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
//this.root.appendChild(tmpl.content.cloneNode(true));
}
set details(user) {
this.root.innerHTML = `<h2> ${user.company.name}</h2>`
}
}
window.customElements.define('app-drawer', AppDrawer);
async function asyncCall() {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const json = await res.json();
const main = document.querySelector("main");
json.forEach(user=> {
const el = document.createElement("app-drawer");
el.details = user;
main.appendChild(el);
});
}
asyncCall();
</script>
通过运行上面的命令,我得到了一些名称作为输出。到目前为止,一切都很好。现在,尝试使用<template>
而不是通过删除构造函数中的注释并同时删除el.details = user;
来获得多个I'm in Shadow DOM.
我的问题是 如何使用第二种方法实现第一种情况的动态内容(不同的用户名)? ?
答案 0 :(得分:1)
您只需要用一条将适当的HTML添加到影子DOM的语句替换el.details = user
。 (这使设置员无关紧要,因此我已将其注释掉。)
user.company.name
作为属性传递给Web组件,而不是在此之后强制设置该值。
(请注意,我从模板中删除了<p>
元素,而只包含了将显示<h2>
的{{1}}元素。)
userCompanyName
let tmpl = document.querySelector('#my-template');
class AppDrawer extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({ mode: 'open' });
// Creates a copy of the `<template>` element's contents
const copy = tmpl.content.cloneNode(true);
// Selects a target element withinin the copy
const header = copy.querySelector("H2");
// Copies the component instance's `usernamecomp` attribute to its `userCompName` property
this.userCompName = this.getAttribute("usercompname");
// Sets the target element's contents equal to the`userCompName` property
header.innerHTML = this.userCompName;
// Appends the augmented copy to the shadowDOM
this.root.appendChild(copy);
}
}
window.customElements.define('app-drawer', AppDrawer);
async function asyncCall() {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const json = await res.json();
const main = document.querySelector("main");
json.forEach(user => {
// Identifies the string to pass into the component instance as an attribute
const userCompName = user.company.name;
// Writes HTML to be used to instantiate an `<app-drawer>` element with a `usercompname` attribute
const drawerInstance = `<app-drawer usercompname=${userCompName}></app-drawer>`;
// Creates the new `<app-drawer>` element, appended to the `<main>` element
main.insertAdjacentHTML("beforeend", drawerInstance);
});
}
asyncCall();
答案 1 :(得分:1)
您可以将加载的值作为参数传递给使用new
创建的自定义元素:
json.forEach( user => main.appendChild( new AppDrawer( user ) ) )
您只需要使用参数定义自定义元素constructor()
:
constructor( user ) {
...
}
请参阅下面的完整示例:
class AppDrawer extends HTMLElement {
constructor( user ) {
super()
this.attachShadow( {mode: 'open'} )
.innerHTML = `<style> p { color: green } </style>
<p> ${user.company.name} </p>`
}
}
window.customElements.define( 'app-drawer', AppDrawer )
async function asyncCall() {
const res = await fetch( "https://jsonplaceholder.typicode.com/users" )
const json = await res.json()
const main = document.querySelector( "main" )
json.forEach( user => main.appendChild( new AppDrawer( user ) ) )
}
asyncCall()
<main></main>