著者:大津 真
JavaScriptフレームワークの中でも、学びやすさと柔軟さで人気を集めている「Vue.js」。本連載では、Vue.jsの基礎から実践的な使い方までを、分かりやすく丁寧に解説していきます。一緒にフロントエンド開発の楽しさを体験してみましょう。第4回では、v-onディレクティブの活用と、VueアプリケーションからDOM(Document Object Model)を操作する方法について説明します。
シェルスクリプトマガジン Vol.99は以下のリンク先でご購入できます。![]()
![]()
図1 「event-props/src/App.vue」ファイルのコード
|
1 2 3 4 5 6 7 8 9 10 11 |
<script setup> import { ref } from 'vue' function eventTest(e) { console.log(e) } </script> <template> <button @click="eventTest">Click me</button> </template> |
図1 「event-props/src/App.vue」ファイルのコード
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<script setup> import { ref } from 'vue' const event = ref(null) function eventTest(e) { event.value = e } </script> <template> <div id="back" @click="eventTest" @dblclick="eventTest"> <h1>Event Test</h1> <div id="box" @mouseover="eventTest" @mouseout="eventTest"> <p>My Box</p> </div> <p>Event type: {{ event?.type }}</p> <p>x:{{ event?.clientX }} y: {{ event?.clientY }}</p> </div> </template> <style scoped> #back { width: 100vw; height: 100vh; } #box { width: 100px; height: 100px; background-color: #f00; margin: 0 auto; } </style> |
図6 「src/style.css」ファイルの変更例
|
1 2 3 4 5 6 7 8 |
(略) #app { max-width: 1280px; margin: 0 auto; /* padding: 2rem; */ ←コメントにする text-align: center; } (略) |
図7 useTemplateRef関数でDOM要素を取得するコードの例
|
1 2 3 4 5 6 7 8 9 10 |
<template> (略) <img ref="fish" id="fish" src="./assets/fish1.jpg" /> (略) </template> <script setup> (略) const fish = useTemplateRef("fish"); (略) </script> |
図8 「event-test2/src/App.vue」ファイルのコード
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
<!-- App.vue --> <template> <div id="back" @click="moveImg"> <img ref="fish" id="fish" src="./assets/fish1.jpg" /> </div> </template> <script setup> import { useTemplateRef, onMounted } from 'vue' // テンプレート参照を取得 const fish_ref = useTemplateRef("fish") function moveImg(e) { // transitionの設定 const duration = "1s" // 移動時間 fish_ref.value.style.transition = `\ left ${duration} ease, top ${duration} ease, \ transform 0.3s ease` // クリック位置に移動 const x = e.clientX - fish_ref.value.width / 2 const y = e.clientY - fish_ref.value.height / 2 fish_ref.value.style.left = `${x}px` fish_ref.value.style.top = `${y}px` // クリック方向に応じて向きを変える if (e.clientX < fish_ref.value.offsetLeft) { fish_ref.value.style.transform = 'scaleX(-1)' // 左向き } else { fish_ref.value.style.transform = 'scaleX(1)' // 右向き } } </script> <style scoped> #back { position: fixed; inset: 0; } #fish { position: absolute; width: 100px; left: 100px; /* 初期位置 X */ top: 100px; /* 初期位置 Y */ } </style> |
図10 HTMLテンプレート部分の変更箇所
|
1 2 3 4 5 6 |
(略) <div id="back" @click="moveImg(false, $event)" @contextmenu="moveImg(true, $event)"> <img ref="fish" id="fish" src="./assets/fish1.jpg" /> </div> (略) |
図11 JavaScript部分の変更箇所(抜粋)
|
1 2 3 4 5 6 7 8 9 10 |
(略) function moveImg(isFast, e) { e.preventDefault(); // 右クリックメニューを防ぐ (略) const duration = isFast ? "0.3s" : "0.8s"; el.style.transition = `left ${duration} ease, \ top ${duration} ease, \ transform 0.3s ease`; (略) |
図12 不適切なコードの例
|
1 2 3 4 5 6 7 8 9 10 |
(略) <script setup> import { useTemplateRef, onMounted } from 'vue'; const fish = useTemplateRef("fish"); const el = fish.value el.style.left = '100px' // 左端の座標を設定 el.style.top = '100px' // 上端の座標を設定 (略) |
図13 書き換えた部分のコード
|
1 2 3 4 5 6 7 8 9 10 11 12 |
onMounted(() => { const el = fish.value; if (el) { // 親要素の位置とサイズを取得 const parentRect = el.offsetParent.getBoundingClientRect(); // 初期位置を画面中央に設定 const x = parentRect.width / 2 - el.width / 2; const y = parentRect.height / 2 - el.height / 2; el.style.left = `${x}px`; el.style.top = `${y}px`; } }); |
※「< 」を「<」に置き換えてください。