css的pointer-events属性(禁止div点击)

本文介绍了一种使用CSS3属性禁用按钮的新方法,替代了传统的通过JS变量控制按钮点击状态的做法。通过动态添加CSS类实现组件禁用,提高了用户体验和代码效率。

之前写项目经常会碰到某个组件需要禁用的要求,之前一直会用一个变量来代替保存按钮的点击状态,今天才发现css3新出的一个属性,顺便试了试

 

最近刚好在研究vue,直接以vue为案列吧

 

以前的的方法:

//html
<div class="btn" @click="click()">快来点击我</div>

//js
data:{
    isclick: 0,
}

//通过设置一个变量来判断按钮是否执行点击事件的操作(这种方法实际上按钮是可以点击只是阻止了事件的操作)
    click() {
      var that = this;
      if (that.isclick == 1) return;  
      setTimeout(() => {
        that.isclick = 1;
      }, 1000);
    }

动态添加属性来设置组件禁用

//html
 <div class="btn" @click="click()" :class="isclick==1?'disable':''">快来点击我</div>


//css

.btn.disable {
  pointer-events: none;
}

//js

data:{
   isclick:0,
}


 // 添加属性的方法
    click() {
      console.log("可点击,1秒之后之后禁止点击");
      var that = this;
      setTimeout(() => {
        that.isclick = 1;
      }, 1000);
    },

 

<think>我们正在解决用户的问题:如何在IE9及以下浏览器中使用pointer-events: none的替代方法。 根据引用[3]:pointer-events: none可以让元素不响应鼠标事件,事件会穿透到下方的元素。 但是IE9及以下不支持该属性,因此需要寻找替代方案。 常见的替代方案: 1. 使用条件注释或检测浏览器,为IE9及以下提供替代的JavaScript方案。 2. 通过JavaScript模拟事件穿透:当事件发生在禁用元素上时,将其隐藏,然后获取下方元素并触发同样的事件,再显示回来。 引用[4]中提供了一种JS替代实现pointerEvents穿透的方法: ```javascript function noPointerEvents (element) { $(element).bind(&#39;click mouseover&#39;, function (evt) { this.style.display = &#39;none&#39;; var x = evt.pageX, y = evt.pageY; var under = document.elementFromPoint(x, y); this.style.display = &#39;&#39;; evt.stopPropagation(); evt.preventDefault(); $(under).trigger(evt.type); }); } ``` 但是,这种方法需要隐藏元素,可能会引起闪烁,并且需要绑定多个事件。 另一种思路是:在需要穿透的元素上覆盖一个透明的遮罩层(例如一个透明的div),然后在这个遮罩层上处理事件,将事件转发到下层元素。但是这样需要额外的元素。 考虑到用户的需求是“禁用”元素的事件(即让事件穿透),我们可以结合引用[2]中的思路:在IE9及以下,我们可以通过动态设置元素的事件处理函数,并判断元素的状态来决定是否阻止事件。 然而,对于禁用效果,我们通常希望元素不仅不响应事件,而且外观上看起来是禁用的(比如灰色)。我们可以这样: - 使用CSS设置禁用的样式(如灰色、透明度等) - 对于事件穿透,使用上述JS方法或者使用一个覆盖层。 具体步骤: 替代方案1:使用覆盖层(推荐,简单可靠) - 在需要禁用(并穿透事件)的元素上覆盖一个透明的div(绝对定位,大小相同),并设置这个div的z-index高于该元素。 - 这样事件会由这个覆盖层接收,然后我们可以在这个覆盖层上触发下层元素的事件(或者直接移除覆盖层,让事件自然发生,但这样就不能穿透到下层了?)。实际上,覆盖层本身不处理事件的话,事件会穿透到覆盖层下面的元素吗?不会,因为覆盖层挡住了,所以我们需要在覆盖层上触发下面元素的事件。 替代方案2:使用JavaScript模拟(如引用[4]的方法) - 绑定事件到需要穿透的元素(设为A),当事件触发时,临时隐藏A,获取下方元素B,触发B的同样事件,然后阻止A的默认行为和冒泡。 但是替代方案2在性能上可能有问题,而且隐藏再显示可能会引起闪烁。 因此,我们给出一个使用覆盖层的具体例子: 假设我们有一个按钮,需要禁用并穿透事件: HTML结构: ```html <div class="container"> <button class="real-button">我是被覆盖的按钮</button> <div class="overlay"></div> </div> ``` CSS: ```css .container { position: relative; display: inline-block; } .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; /* 透明 */ z-index: 10; /* 在支持pointer-events的浏览器中,我们不需要覆盖层,所以默认隐藏 */ display: none; } /* 针对IE9及以下显示覆盖层 */ .ie9-and-below .overlay { display: block; } ``` 然后,我们可以通过条件注释给html添加ie9-and-below类: ```html <!--[if lte IE 9]> <html class="ie9-and-below"> <![endif]--> <!--[if gt IE 9]><!--> <html> <!--<![endif]--> ``` 这样,在IE9及以下,覆盖层会显示,并且覆盖在按钮上。但是,覆盖层会挡住事件,我们想让事件穿透到下面的按钮?实际上,覆盖层挡住了,按钮接收不到事件。所以我们需要在覆盖层上绑定事件,然后模拟触发按钮的事件。 但是,我们也可以让覆盖层不阻挡事件,而是将事件传递给下面的元素?在IE9及以下,我们可以使用`pointer-events:none`的替代JS方法,但这里我们已经在覆盖层上了,所以可以: 在覆盖层上绑定事件,然后阻止默认行为,并触发下面元素的事件。但是这样需要知道下面具体是什么元素,而且事件类型很多,处理起来复杂。 另一种思路:在覆盖层上不绑定任何事件,然后通过JS将覆盖层上的事件直接传递给下面的元素。我们可以使用类似以下代码: ```javascript // 假设覆盖层有类名&#39;overlay&#39; $(&#39;.overlay&#39;).on(&#39;click&#39;, function(e) { // 找到覆盖层下面的按钮(这里假设是.real-button,实际可能需要根据结构调整) var button = $(this).siblings(&#39;.real-button&#39;)[0]; // 触发按钮的点击事件 $(button).click(); }); ``` 但是这样只能处理点击事件,而且如果按钮有多个,或者下面有其他元素,我们需要更通用的方法。 考虑到通用性,我们可以使用document.elementFromPoint方法,如引用[4]中的方法,但这里我们不需要隐藏覆盖层,因为覆盖层已经挡住了,我们只需要在覆盖层的事件处理函数中,获取覆盖层下方的元素(即被覆盖的元素),然后触发该元素的同样事件。 但是注意:覆盖层本身就在最上层,我们获取覆盖层下方的元素,需要临时隐藏覆盖层,然后获取该坐标下的元素,再显示覆盖层,然后触发那个元素的事件。 所以,我们可以这样写覆盖层的事件处理: ```javascript $(&#39;.overlay&#39;).on(&#39;click mouseover mousedown mouseup&#39;, function(e) { // 临时隐藏覆盖层 $(this).hide(); var under = document.elementFromPoint(e.clientX, e.clientY); $(this).show(); // 触发下方元素的事件 if (under) { var evt = document.createEvent(&#39;MouseEvents&#39;); evt.initMouseEvent(e.type, true, true, window, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, under); under.dispatchEvent(evt); } e.stopPropagation(); e.preventDefault(); }); ``` 但是,这种方法同样会有闪烁(虽然时间很短),而且事件传递可能不完全一致。 考虑到性能和复杂性,我们可能只需要处理点击事件,并且根据实际情况调整。 因此,我们建议根据实际需求选择方案: 1. 如果只需要屏蔽鼠标事件,且不需要穿透到下层,只是希望元素不响应事件,那么可以直接在元素上设置`disabled`属性(对于表单元素)或者用JS阻止事件(例如在事件处理函数中判断状态并阻止)。 2. 如果需要穿透事件,且可以接受使用覆盖层,那么使用覆盖层,并配合JS事件转发(仅转发点击事件等必要事件)。 另外,引用[1]中提到:pointer-events:none + disabled = 完美禁用。在支持pointer-events的浏览器中,我们可以用CSS禁用样式的元素的鼠标事件屏蔽,同时设置disabled属性。在IE9及以下,我们可以只使用disabled属性,并添加一个禁用的样式。但是,disabled属性只适用于表单元素,对于div等元素不适用。 所以,对于非表单元素,我们可以用以下方案: - 在支持pointer-events的浏览器中,使用pointer-events:none来禁用事件。 - 在IE9及以下,使用一个覆盖层(透明,但阻止事件,然后通过JS转发事件到下层)或者使用JS完全模拟事件穿透(如引用[4]的方法)。 由于引用[4]的方法需要隐藏元素,可能会引起闪烁,因此我们推荐使用覆盖层,并且只转发必要的事件(如点击事件),同时避免在频繁触发的事件(如mousemove)上使用。 总结步骤: 1. 为IE9及以下浏览器添加标识(如条件注释给html添加类名)。 2. 在需要禁用事件穿透的元素上,添加一个覆盖层(通过CSS控制在IE9及以下显示)。 3. 为覆盖层绑定需要穿透的事件(如click),并在事件处理函数中: - 临时隐藏覆盖层 - 获取鼠标位置下方的元素 - 显示覆盖层 - 触发下方元素的相同事件 4. 注意:如果下方元素是表单元素,且需要disabled状态,那么还要结合disabled属性。 但是,如果用户希望完全模拟pointer-events:none(即不需要覆盖层,而是让事件自然穿透到下层),那么引用[4]的方法更接近,但性能开销较大。 因此,我们提供两个方案供用户选择: 方案一(覆盖层+事件转发): 优点:不会频繁闪烁(因为事件触发时隐藏覆盖层的时间很短),实现相对简单。 缺点:需要额外的元素,且需要为每个事件绑定转发。 方案二(完全JS模拟): 优点:不需要额外的元素,事件直接穿透。 缺点:隐藏再显示可能导致闪烁,且绑定的事件类型多,性能开销大。 根据实际需求选择。 最后,我们给出一个覆盖层方案的完整代码示例: HTML: ```html <div class="disable-layer"> <button class="btn">我是按钮</button> <!-- 覆盖层,在支持pointer-events的浏览器中不显示 --> <div class="ie-shield"></div> </div> ``` CSS: ```css .disable-layer { position: relative; display: inline-block; } .ie-shield { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 10; display: none; /* 默认隐藏 */ } .ie9-and-below .ie-shield { display: block; /* 在IE9及以下显示 */ } ``` JS (使用jQuery): ```javascript $(document).ready(function() { $(&#39;.ie-shield&#39;).on(&#39;click&#39;, function(e) { // 临时隐藏自己 $(this).hide(); // 获取当前鼠标位置下的元素 var under = document.elementFromPoint(e.clientX, e.clientY); $(this).show(); // 触发该元素的点击事件 if (under) { $(under).trigger(&#39;click&#39;); } // 阻止事件冒泡和默认行为,因为我们手动触发了下层元素的事件 e.stopPropagation(); return false; }); }); ``` 注意:这个示例只处理了点击事件,如果需要处理其他事件,可以类似绑定。 但是,这种方法在快速连续点击时可能存在问题(因为隐藏和显示覆盖层是同步的,所以一般不会有大问题)。另外,如果下层元素的位置在覆盖层隐藏的瞬间发生了变化,那么获取到的元素可能不是预期的。因此,这种方法适用于页面结构稳定的情况。 如果用户不需要覆盖层,而是希望完全模拟pointer-events:none,那么可以使用引用[4]中的方法,直接绑定在需要穿透的元素上。 我们提供引用[4]中的方法(使用jQuery): ```javascript function noPointerEvents (element) { $(element).bind(&#39;click mouseover&#39;, function (evt) { this.style.display = &#39;none&#39;; var x = evt.pageX, y = evt.pageY; var under = document.elementFromPoint(x, y); this.style.display = &#39;&#39;; evt.stopPropagation(); evt.preventDefault(); $(under).trigger(evt.type); }); } // 使用:对需要穿透的元素调用 noPointerEvents($(&#39;.target-element&#39;)); ``` 这种方法不需要额外的覆盖层,但会隐藏元素再显示,可能会引起闪烁,且绑定的事件类型有限(这里只绑定了click和mouseover)。 用户可以根据实际情况选择。 最后,我们强调:在支持pointer-events的浏览器中,应该使用CSS属性pointer-events:none,而只在IE9及以下使用这些替代方案。 因此,我们可以通过条件注释或者JS检测,仅对IE9及以下应用这些替代方法。 检测浏览器是否支持pointer-events的JS(如引用[2]): ```javascript var supportsPointerEvents = (function() { var element = document.createElement(&#39;div&#39;); element.style.cssText = &#39;pointer-events:auto&#39;; return element.style.pointerEvents === &#39;auto&#39;; })(); ``` 然后,如果支持,我们就不做处理,否则应用替代方案。 例如,使用覆盖层方案时,我们可以动态添加覆盖层,而不是一开始就写在HTML里。 综上所述,我们提供了两种替代方案,并给出了代码示例。用户可以根据实际场景选择。</think>### IE9及以下浏览器中`pointer-events: none`的替代方案 `pointer-events: none`是CSS3属性,用于阻止元素响应鼠标/触摸事件(点击、悬停等),实现事件穿透效果[^3]。**IE9及以下版本不支持此属性**,需通过JavaScript模拟类似行为。以下是兼容方案: --- ### 一、JavaScript 事件穿透方案 通过临时隐藏元素并触发下层元素事件实现: ```javascript function simulatePointerEvents(element) { element.addEventListener(&#39;click&#39;, function(evt) { // 1. 临时隐藏当前元素 this.style.display = &#39;none&#39;; // 2. 获取鼠标位置下方的元素 var underElement = document.elementFromPoint(evt.clientX, evt.clientY); // 3. 恢复当前元素显示 this.style.display = &#39;&#39;; // 4. 触发下层元素事件 if (underElement) { underElement.dispatchEvent(new MouseEvent(evt.type, evt)); } evt.stopPropagation(); evt.preventDefault(); }); } // 使用示例 var target = document.getElementById("disabled-element"); simulatePointerEvents(target); ``` **原理**: 点击时隐藏当前元素→获取下方元素→触发其事件→恢复显示[^4]。 --- ### 二、覆盖层 + 条件注释方案 通过透明覆盖层拦截事件并转发: ```html <!-- HTML --> <div class="ie-overlay-container"> <button id="underlying-btn">底层按钮</button> <!-- IE9-专用覆盖层 --> <!--[if lte IE 9]> <div class="ie-event-overlay" data-target="underlying-btn"></div> <![endif]--> </div> ``` ```css /* CSS */ .ie-event-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; /* 透明 */ z-index: 10; } ``` ```javascript // JavaScript - 覆盖层点击转发 document.querySelectorAll(&#39;.ie-event-overlay&#39;).forEach(function(overlay) { overlay.addEventListener(&#39;click&#39;, function() { var targetId = this.getAttribute(&#39;data-target&#39;); document.getElementById(targetId).click(); }); }); ``` --- ### 三、禁用状态组合方案 结合CSS禁用样式与事件阻止: ```css /* 禁用样式 */ .disabled { opacity: 0.6; cursor: not-allowed; } ``` ```javascript // 检测浏览器是否支持pointer-events var supportsPointerEvents = (function() { var el = document.createElement(&#39;div&#39;); el.style.cssText = &#39;pointer-events:auto&#39;; return el.style.pointerEvents === &#39;auto&#39;; })(); // 事件处理 function handleDisabledClick(el) { if (!supportsPointerEvents && el.classList.contains(&#39;disabled&#39;)) { el.addEventListener(&#39;click&#39;, function(e) { e.stopPropagation(); e.preventDefault(); }); } } ``` --- ### 方案对比 | **方案** | 优点 | 缺点 | |------------------------|--------------------------|-------------------------------| | JavaScript事件穿透 | 无需额外元素 | 闪烁问题;需绑定多个事件类型 | | 覆盖层+条件注释 | 无闪烁;精确控制转发目标 | 需添加额外DOM元素 | | 禁用状态组合 | 简单易用 | 需手动管理禁用状态逻辑 | > **推荐选择**: > - 简单场景 → **禁用状态组合方案** > - 精确事件穿透 → **覆盖层方案** > - 动态元素 → **JavaScript事件穿透方案** ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值