Web Components #7 组件事件
web components 事件处理
自定义事件
一个弹窗组件例子,支持close,confirm自定义事件.
<button onclick="openDialogHandler()">打开弹窗</button>
<hr />
<x-dialog status="closed" onclose="onDialogClose()"></x-dialog>
<script>
// 打开弹窗
function openDialogHandler(){
document.querySelector('x-dialog').show();
}
// close事件
function onDialogClose() {
console.log('dialog closed');
}
// 监听x-dialog的confirm事件
document.querySelector('x-dialog')
.addEventListener('confirm',(e)=>{
console.log('dialog confirm',e.detail.data);
e.target.setAttribute('status','closed')
});
// XDialog 组件
customElements.define('x-dialog',
class extends HTMLElement {
static get observedAttributes() {
return ["status"];
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.dialog {
box-shadow: 0 0 10px #ccc;
width: 300px;
}
header,article,footer{
border-bottom: 1px solid #ccc;
padding: 10px;
}
</style>
<div class="dialog" style="display:${this.status?'block':'none'}">
<header>弹窗</header>
<article>
<form>
<p><label for="name">姓名:
<input type="text" name="name" placeholder="请输入姓名">
</label>
</p>
<p>
<label for="email">Email:
<input type="email" name="email" placeholder="请输入邮箱">
</label>
</p>
</form>
</article>
<footer>
<button class="close-btn">关闭窗口</button>
<button class="confirm-btn">提交</button>
</footer>
</div>
`;
this.shadowRoot.querySelector('.close-btn')
.addEventListener('click',this.closeHandler);
this.shadowRoot.querySelector('.confirm-btn')
.addEventListener('click',this.confirmHandler);
}
attributeChangedCallback(name, oldValue, newValue){
if(name=='status'){
if(newValue=='opened'){
this.shadowRoot
.querySelector('.dialog').style.display='block';
}else{
this.shadowRoot
.querySelector('.dialog').style.display='none';
}
}
}
closeHandler =()=>{
console.log('关闭弹窗',this.shadowRoot);
this.shadowRoot
.querySelector('.dialog').style.display='none';
this.dispatchEvent(new CustomEvent('close'));
this.setAttribute('status','closed');
}
confirmHandler=()=>{
const form=this.shadowRoot.querySelector('form');
// 获取
const data=Object.fromEntries((new FormData(form)).entries());
this.dispatchEvent(new CustomEvent('confirm',{detail:{data}}));
}
show=()=>{
this.shadowRoot
.querySelector('.dialog').style.display='block';
this.setAttribute('status','opened');
}
})
</script>
自定义事件:
const event=new CustomEvent("custom-event",{});
触发事件:
dom.dispatchEvent(event);
监听自定义事件:
<x-foo></x-foo>
document.addEventlistener("custom-event",function(){})
Shadow DOM中的事件处理
Shadow DOM 中的事件.
<div id="my-element"></div>
<script>
const element = document.querySelector('#my-element');
const btn=document.createElement('button');
btn.innerText='click me';
const shadowRoot = element.attachShadow({mode: 'open'});
shadowRoot.appendChild(btn);
shadowRoot.addEventListener('click',function(e){
// 返回 button
console.log('shadowDom clicked',e.target);
});
element.addEventListener('click',function(e){
// 返回 my-element
console.log('element clicked',e.target);
});
</script>
- 在shadow外监听target元素为shadow.
- 在shadow内监听target为实际的元素.
组件间的事件通信
通过自定义事件,组件之间监听通过同一父级组件.
customElements.define('x-b', class extends HTMLElement{
constructor(){
super()
this.attachShadow({mode: 'open'})
this.shadowRoot.innerHTML = `
<div>
B:
<button id="btn2">按扭B</button>
</div>
`
this.shadowRoot.querySelector('#btn2')
.addEventListener('click',()=>{
const event = new CustomEvent('custom-b',{
bubbles: true,//允许冒泡
})
this.dispatchEvent(event)
})
}
})
监听
document.addEventListener('custom-b',function(e){
console.log('组件B的事件',e.target)
})
但event.stopPropagation()
被阻止冒泡.可以在捕获阶段
document.addEventListener('custom-b',function(e){
console.log('组件B的事件',e.target)
},true)
原作者:阿金
本文地址:https://hi-arkin.com/archives/web-components-6.html