実装イメージ

今回は、「メニューボタン」と「選択肢メニュー」以外がクリックされた際に、選択肢メニューを非表示になるように実装します。

動作

実際の動作は「Result」タブからご確認ください。ボタンと選択肢メニュー以外がクリックされた際に、選択肢メニューを非表示にするように実装しています。

実際にボタンと選択肢メニューとは関係ない場所をクリックしてみてください。

コード解説

では実際にどのような処理を記述したら、特定要素以外のクリックを検知できるのかを解説します。

尚、HTML、CSS、Vueインスタンスの初期化などは重要ではないので、大事なところだけに絞って解説します。mounted()とmethodsに注目してください。

mounted: function() {
    window.addEventListener('click', this.checkClickElement);
},
methods: {
    checkClickElement(event) {
        if(this.menu_open)
        if(
            !this.$el.querySelector('.menu').contains(event.target) &&
                    !this.$el.querySelector('.menu-btn').contains(event.target)
        ) {
            this.menu_open = !this.menu_open
        }
    },
}

mounted()

mounted: function() {
    window.addEventListener('click', this.checkClickElement);
},

mounted()はインスタンスが DOM 要素にマウントされた後に実行したい処理を登録できます。今回はクリックされた要素を正確に検知したいのでmounted()を採用しました。

クリックイベントを検知して要素チェックの関数を実行しています。

methods

methods: {
    checkClickElement(event) {
        if(this.menu_open)
        if(
            !this.$el.querySelector('.menu').contains(event.target) &&
                    !this.$el.querySelector('.menu-btn').contains(event.target)
        ) {
            this.menu_open = !this.menu_open
        }
    },
}

要素チェックの関数では、まずメニューがアクティブであるかを判定します。

メニューがアクティブなら、this.$elを使ってマウントする要素を取得します。このthis.$elで取得できる要素は、例えばel: “#app”で定義した要素になります。

そして、下記の記述によってボタンと選択肢メニューがクリック要素に含まれていないかをチェックしています。「含まれていない」状態が正なので、論理否定 (!)を使用して条件判定を行なっています。

!this.$el.querySelector('.menu').contains(event.target)
!this.$el.querySelector('.menu-btn').contains(event.target)

contains()は、対象の要素(今回場合はボタンと選択肢メニュー)が、指定された要素(今回だとクリックターゲット要素)の子孫であるかをチェックし、true or falseを返します。

Node.contains()

今回紹介した方法を使えば、正確にクリックされた要素を取得できるので役に立つと思います。

質問があれば、コメントをいただければ幸いです。

カテゴリー: Vue.js