プロジェクトでは、ターゲット要素以外の領域のクリックやマウスの出入りを監視する必要が生じることがよくあります。
たとえば、以下では、テーブル内にネストされたフォーム コンポーネントがあります。
n行目をクリックすると、n行目の要素が入力または選択用のフォーム要素になることを願っています。
他の領域の n 行をクリックすると、データ表示が復元されます。
それでは、この種の監視をどのように実装すべきかを考えてみましょう。
含まれています
この方法について聞いたことがあるならcontains
、突然ピンとくるでしょう。このメソッドの目的は、要素に別の要素が含まれているかどうかを判断することです。したがって、イベント オブジェクトを通じて現在のイベントの対象要素を取得し、contains
その対象要素が監視する必要がある要素内にあるかどうかを判断すれば、簡単に目的を達成できます。
アップコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
background-color: aqua;
width: 100vw;
height: 100vh;
}
.parent {
width: 100px;
height: 100px;
background-color: yellow;
}
.son {
position: relative;
left: 30px;
top: 30px;
width: 30px;
height: 30px;
background-color: red;
}
</style>
</head>
<body>
<div class="parent">
<div class="son"></div>
</div>
<script>
const parentEle = document.querySelector('.parent')
document.body.addEventListener('click', e => {
const target = e.target
if (parentEle.contains(target)) {
alert('点击了元素包含区域')
} else {
alert('点击了元素以外区域')
}
})
</script>
</body>
</html>
もちろん、もっと便利にすることもできます。Vue プロジェクト内の場合は、カスタム命令を作成して監視効果を簡単に実現できます。
export default function install(Vue) {
Vue.directive('clickoutside', {
bind(el, {
value: fun, arg }) {
console.log(arg)
arg = arg || 'click'
document.addEventListener(arg, handleFun.bind(null, el, fun))
},
unbind(el, {
arg }) {
document.removeEventListener(arg, handleFun)
},
})
}
function handleFun(el, fun, e) {
let flag = el.contains(e.target)
if (!flag) {
fun()
}
}
<button v-clickoutside="fn">按钮</button>
上記は、デフォルトでクリック イベントをリッスンする非常に単純なカスタム命令で、クリックされた要素が監視対象の要素内にあるかどうかを検出するために使用できます。それ以外の場合は、命令にバインドされたメソッドが実行されます。
最後にもう 1 つ、element-ui を使用すると、実際には内部的にこのようなメソッドが付属します。
このように参照できます
import clickoutside from 'element-ui/src/utils/clickoutside'