该装饰器只会在当前组件生效,不需要考虑清除全局监听
前景: 表单某一项输入框 blur 事件需要更新右侧数据(调接口),为防止误触增加了loding弹层
需求: 修改表单这个值后未失焦时鼠标放到“按钮”上,并点击了按钮,需要触发“按钮”功能
原因: 因为blur事件添加了loading层,点击“按钮”被 loding层挡住了,现在要的效果是失焦时就需要触发该按钮的事件
import { Element } from '@angular/core';
import { HostListener} from '@angular/core';
// 判断是否触发值更新
valueStatus = false;
// 是否触发计算
triggerCalculation = false;
@ViewChild('btnView') btnView: ElementRef;
@HostListener('事件名称',['$event'])
public onClick(e) {
// if (event.key === 'Enter') {
//doning
//}
// 根据弹层类名 && 当前url && 定义的失焦状态值 判断点击的是失焦时弹出的弹层
if (e.target.className && e.target.className === 'ng-start-inserted' && this.valueStatus && window.location.herf.includes('/demo')) {
this.valueStatus = false;
const { clientWidth, clientHeight } = this.btnView.nativeElement;
// 因为层级嵌套加上定位/felx等布局影响,需要通多多次拿取外层高相加
function getElementPageOffset(el) {
// 距离该子元素最近的进行过定位的父元素, 用 el.parentElement 每一层都计算了但是计算出来的和并不是真正的高度
if (el?.offsetParent) {
const parent = getElementPageOffset(el?.offsetParent)
return {
top: parent?.top + el.offsetTop,
left: parent?.left + el.offsetLeft,
}
}
return {
top: el.offsetTop,
left: el.offsetLeft,
}
}
const pageOffset = getElementPageOffset(this.btnView.nativeElement)
// 找到按钮的位置,判断鼠标点击是否再按钮的范围
if (el.clientX >= pageOffset.left && el.clientX <= (pageOffset.left + clientWidth) && el.clientY >= pageOffset.top && && el.clientY <= (pageOffset.top + clientHeight)) {
this.triggerCalculation = true
}
}
}
onBlur = () => {
this.httpService.getData(params).subscribe((res: any) => {
this.viewData = res.data;
// 如果点击‘按钮位置’需要触发按钮事件
if (this.triggerCalculation) {
this.triggerCalculation = false
// 按钮事件执行
this.handlerChange()
}
})
}
onFocus = () => {
// 修改值需要监听点击事件
this.valueStatus = true;
}
参考文章,计算元素距离顶部距离,和评论第一条
https://blog.csdn.net/u013764814/article/details/83825479