html A标签target属性修改后无效的问题分析

背景

html a标签的target属性修改后,会以不同的方式展示新页面。target=_self时会在当前窗口展示新页面,target=_blank时会在新标签页展示网页。

我们在chrome的编辑模式下可以在线对这些属性修改,观察效果。但有时候
会发现,修改了target属性后,点击目标,并未按预期方式打开窗口。例如将target修改为self,点击目标元素后,却仍然打开了新窗口。
在这里插入图片描述

分析

由于点击是一个动作,因此涉及到了事件。接着考虑看看事件触发时发生了什么?通过增加一个事件监听器来进行观察问题。

function interceptClickEvent(e) {
    var href;
    var target = e.target || e.srcElement;
    if (target.tagName === 'A') {
        href = target.getAttribute('href');
        e.preventDefault();
    }
}

document.body.addEventListener('click', interceptClickEvent);

增加事件拦截代码后,点击目标对象,接着观察事件对象。事件对象中有两个重要属性target及path。target告诉我们这个事件是哪个对象产生,而path则描述了事件冒泡的路径。通过这些属性就可以看到真正产生事件的元素是哪个。因此点击不生效一定就是页面中某个位置埋了Javascript代码,对其进行了修改。但通过事件对象我们可以找到产生事件的源头。

在这里插入图片描述

虽然我们编辑模式下修改了html代码,删除了事件处理器的代码,但实际上这个绑定关系并没有删除。这样导致单击链接后依然被相关的js代码所处理。

通过chrome选择元素,然后查看元素关联的事件监听器。并删除这些关联的事件监听器,随后通过将target修改为self来验证是否能在当前页跳转。删除并修改后发现可以在当前页面跳转。说明窗口打开动作被相关js处理后才执行,导致与观察的情况不符。

在这里插入图片描述
接着我们可以增加一段代码来验证。通过hook addEventListener可以找到被拦截的方法,最终可以观察到,由于添加了额外的Listener才导致修改不生效。

EventTarget.prototype.addEventListener = (function() {
    let originEventListener = EventTarget.prototype.addEventListener;
    return function(type, listener, option) {
        if (type === "click" && this.constructor.name === 'HTMLDocument' && listener.toString().indexOf('yourKeyWord') < 0) {
            console.log(listener.toString());
            debugger ;return;
        }
        return originEventListener.call(this, type, listener, option);
    }
}
)();

另外当一个窗口始终是弹窗方式打开,那么很肯定调用了window.open方法。不管是react还是vue,我们关注对应虚拟结点上绑定的函数就可以找到问题。如果是window.open,依然可以通过hook形式验证。

window.open = (function(){
    debugger;
  let originWindowOpen = window.open;
  return function(strUrl, strWindowName,strWindowFeatures) {
      originWindowOpen.call(this,strUrl,"_self",strWindowFeatures);
  }  
})();

//或通过proxy实现hook
window.open = new Proxy(window.open,{
   apply: function(target, ctx, args) {
       target.call(ctx,args[0],"_self",args[1])
   }
})

总结

  • 事件类的问题可以通过分析事件对象来溯源,最终快速找到目标。
  • 其次一个元素上的发生了某个事件,但事件源又不是该对象时,通过分析该元素的事件监听器列表可以找到答案。
  • 善于使用hook进行分析。
  • window.open也可以打开窗口
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值