capture修飾子

capture修飾子は、イベントがターゲット要素に到達する前に親要素でイベントハンドラを実行するために使用します。
※バブリングフェーズとは逆の順序でイベント処理

capture修飾子
記法

v-on:イベント.capture=”イベント名”
@イベント.capture=”イベント名”

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>capture修飾子の比較</title>
    <link rel="stylesheet" href="./main.css" />
  </head>
  <body>
    <div id="app">
      <div id="log">クリックされた要素: <span>{{ clickedElement }}</span></div>
      <div class="section">
        <p>capture有り</p>
        <div
          class="outer"
          @click.capture="handleOuterClick('capture有り: 外側の要素')"
        >
          外側の要素
          <div
            class="middle"
            @click.capture="handleMiddleClick('capture有り: 中間の要素')"
          >
            中間の要素
            <div
              class="inner"
              @click.capture="handleInnerClick('capture有り: 内側の要素')"
            >
              内側の要素
              <button
                class="click-button"
                @click="handleButtonClick('capture有り: ボタン')"
              >
                クリック
              </button>
            </div>
          </div>
        </div>
      </div>
      <hr />
      <div class="section">
        <p>capture無し</p>
        <div class="outer" @click="handleOuterClick('capture無し: 外側の要素')">
          外側の要素
          <div
            class="middle"
            @click="handleMiddleClick('capture無し: 中間の要素')"
          >
            中間の要素
            <div
              class="inner"
              @click="handleInnerClick('capture無し: 内側の要素')"
            >
              内側の要素
              <button
                class="click-button"
                @click="handleButtonClick('capture無し: ボタン')"
              >
                クリック
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- CDN -->
    <script src="CDNのURL"></script>
    <script src="./main.js"></script>
  </body>
</html>
// Vueアプリケーションの作成とマウント
Vue.createApp({
  data() {
    return {
      clickedElement: "",
    };
  },
  methods: {
    handleOuterClick(message) {
      this.clickedElement = message;
    },
    handleMiddleClick(message) {
      this.clickedElement = message;
    },
    handleInnerClick(message) {
      this.clickedElement = message;
    },
    handleButtonClick(message) {
      this.clickedElement = message;
    },
  },
}).mount("#app");
.section {
  margin-bottom: 40px;
}

.outer {
  padding: 20px;
  border: 2px solid #ff5722;
  margin-bottom: 20px;
}

.middle {
  padding: 20px;
  border: 2px solid #ff9800;
  margin-bottom: 20px;
}

.inner {
  padding: 20px;
  border: 2px solid #ffc107;
  margin-bottom: 20px;
}

.click-button {
  padding: 10px;
  background-color: #4caf50;
  color: white;
  border: none;
  cursor: pointer;
}

.click-button:hover {
  background-color: #388e3c;
}

#log {
  margin-bottom: 20px;
  padding: 10px;
  border-bottom: 1px solid #ccc;
}

#log span {
  font-weight: bold;
  color: #ff5722;
}
出力結果
クリックされた要素: {{ clickedElement }}

capture有り

外側の要素
中間の要素
内側の要素

capture無し

外側の要素
中間の要素
内側の要素