<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Complex Custom Element</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.global-text {
color: blue;
}
</style>
</head>
<body>
<h1>复杂自定义元素示例:可折叠卡片</h1>
<p class="global-text">这是全局样式的段落,颜色为蓝色。</p>
<collapse-card title="用户信息">
<div slot="content">
<p>姓名:张三</p>
<p>年龄:30</p>
<p>职业:前端工程师</p>
</div>
</collapse-card>
<collapse-card title="项目详情">
<div slot="content">
<p>项目名称:Web Components 实践</p>
<p>状态:进行中</p>
<p>截止日期:2023-12-31</p>
</div>
</collapse-card>
<script>
class CollapseCard extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
this._isOpen = false;
shadowRoot.innerHTML = `
<style>
:host {
display: block;
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
.card-header {
padding: 10px;
background-color: #f5f5f5;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.card-content {
padding: 10px;
display: none;
background-color: white;
}
.card-content.show {
display: block;
}
.toggle-icon::after {
content: "▼";
transition: transform 0.3s;
}
.toggle-icon.open::after {
transform: rotate(180deg);
}
</style>
<div class="card-header">
<span class="card-title">${this.getAttribute('title') || '默认标题'}</span>
<span class="toggle-icon"></span>
</div>
<div class="card-content">
<slot name="content"></slot>
</div>
`;
shadowRoot.querySelector('.card-header').addEventListener('click', () => this.toggle());
}
static get observedAttributes() {
return ['title'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'title') {
this.shadowRoot.querySelector('.card-title').textContent = newValue;
}
}
toggle() {
this._isOpen = !this._isOpen;
const content = this.shadowRoot.querySelector('.card-content');
const toggleIcon = this.shadowRoot.querySelector('.toggle-icon');
content.classList.toggle('show', this._isOpen);
toggleIcon.classList.toggle('open', this._isOpen);
this.dispatchEvent(new CustomEvent('toggle', {
detail: { isOpen: this._isOpen }
}));
}
}
customElements.define('collapse-card', CollapseCard);
document.querySelectorAll('collapse-card').forEach(card => {
card.addEventListener('toggle', (e) => {
console.log(`卡片状态:${e.detail.isOpen ? '展开' : '折叠'}`);
});
});
</script>
</body>
</html>