こんにちは、Webフロントエンドエンジニアの爲本、山本です。
先日開催された 「Vue Fes Japan 2024」にて、LINEヤフー株式会社はゴールドスポンサーを務めさせていただきました。LINEヤ フー企業ブースでは、Vue.js に関するクイズを実施しました。この記事では、今回出題した全 6 問について解説します。
LINEヤフーでは、「LYPプレミアム」や「LINE公式アカウント」「LINEギフト」など、さまざまなプロダクトでVue.jsを使用しています。さらに、LINEヤフーはVue.jsのゴールドスポンサーとして、月500ドルの支援を行なっています。この支援を通じて、Vue.jsコミュニティの成長と発展に貢献しています。今回のVue Fes Japan 2024 では、選択問題から記述問題まで、Vue.jsに関する問題を時間を区切って全部で6つ出題しました。ブースに来ていただいた方には、付箋を貼っていただくことで、クイズを通じて LINEヤフーのスタッフとコミュニケーションを図りました。
問 1
設問
設問それぞれのコードはすべて正常に動作します。 Vue における SFC の記述方法で推奨されている書き方はどれでしょうか?(複数選択可)
(1)
<template>
<!-- ... -->
</template>
<script lang="ts">
/* ... */
</script>
<style scoped>
/* ... */
</style>
(2)
<script lang="ts">
/* ... */
</script>
<template>
<!-- ... -->
</template>
<style scoped>
/* ... */
</style>
(3)
<script lang="ts">
/* ... */
</script>
<style scoped>
/* ... */
</style>
<template>
<!-- ... -->
</template>
(4)
<template>
<!-- ... -->
</template>
<style scoped>
/* ... */
</style>
<script lang="ts">
/* ... */
</script>
解答
(1)、(2)
解説
Vue.js におけるシングルファイルコンポーネント(SFC)の書き方では、style セクションが最後にあることが重要です。これさえ守られていれば、template と script の順序については、どちらも推奨される形となっています。Vue 2.x の時代には、多くのプロジェクトで template が最初に書かれることが一般的でした。しかし、Vue 3.2 では script setup 構文が多く使われるようになり、Vue.js の公式ドキュメントでも script を最初に置いています。また、ファイルによって template が最初のものと、script が最初のものとが混在すると、管理が難しくなります。そのため、チーム内で統一したルールを決めることが重要です。筆者としては、エンジニアとデザイナーがそれぞれの作業を効率よく行えるように、script, template, style の順序で記述することをおすすめしています。この順番は、エンジニア/デザイナーの作業分担が明確で、エンジニアが主に script と template を担当し、デザイナーが template と style を担当するようなケースに適しています。この配置により、それぞれの作業エリアが隣接するため、従来の template, script, style の順序よりも、共同作業やコードの理解が向上します。
問 2
設問
下記コードはどの順番で実行されるでしょうか? また、その理由を記述してください。
- (1)1、4、5、2、3
- (2)1、5、4、2、3
- (3)1、2、3、4、5
- (4)1、4、2、5、3
<script setup lang="ts">
import { nextTick, onMounted } from "vue";
(async () => {
console.log(1);
await new Promise((resolve) =>
setTimeout(() => {
console.log(2);
return resolve("ok");
})
).then((_v) => {
console.log(3);
});
})();
nextTick(() => {
console.log(4);
});
onMounted(() => {
console.log(5);
});
</script>
解答
答え:(2)理由:(例)nextTick は非同期処理でありマイクロタスクとして実行されるため、onMounted が先に実行され、nextTick に渡されたコールバック関数が実行されます。
こちらの問題は Vue.js のライフサイクルと非同期が絡む問題です。アプリ開発の中で、API からデータを取得し、それをインタラクティブに画面に反映するシーンは多いかと思います。この問題はその際にライフサイクルが関与するときの処理の実行順序を問います。なお、実行理由はいろいろな切り口で存在するため、スポンサーブース内では一部の実行処理部分の理由だけでも記載いただきました。
解説
最初に実行されるのは、即時関数内の console.log(1)です。これにより、まず 1 が出力されます。次に、Vue の onMounted フックが実行されます。onMounted はコンポーネントがマウントされた後に実行されるため、この時点で console.log(5)が呼び出されます。その結果、次に 5 が出力されます。その後、nextTick に登録されたコールバックが実行されます。nextTick はマイクロタスクとして実行されるため、通常の非同期タスクよりも優先されます。したがって、4 が出力されます。続いて、setTimeout 内のコールバック関数が実行されます。これはマクロタスクとして非同期に処理されるため、先に述べた処理がすべて終わった後に実行され、2 が出力されます。最後に、Promise の then メソッドが呼び出されます。これは setTimeout の後に実行され、最後に 3 が出力されます。
問 3
設問
A と B のコードを使い分ける場合、それぞれどういったユースケースが適切でしょうか?
<script setup lang="ts">
import { ref } from "vue";
const inputTextA = ref("");
const inputTextB = ref("");
</script>
<template>
<form @submit.prevent>
A: this is {{ inputTextA }}<br />
<input v-model="inputTextA" />
</form>
<form @submit.prevent>
B: this is {{ inputTextB }}<br />
<input :value="inputTextB" @input="(e) => (inputTextB = e.target.value)" />
</form>
</template>
解答
A:(例)日本語入力時、v-model は確定するまでバインディングされないため、日本語に対して適切なイベントが期待できる。B:(例)IME の中間状態(未確定状態)であってもイベントが発火するため、IME の入力を適切に扱えない場合があり、例えば入力値に対してバリデーションを行う場合、意図しない入力に対して作用する可能性がある。
フォームコンポーネントを実装する場合、データのバインディングを行う際に v-model で行うか v-bind+@input で迷ったご経験はないでしょうか?本設問は特にフォームコンポーネントでのバリデーション処理を想定したものになってます。
解説
v-model を使用したバイン ディングは、フォームの入力データとコンポーネントの状態を簡単に同期させる方法です。v-model は、特に日本語などの IME(Input Method Editor)を用いる場合に強力です。IME による入力では、v-model はテキストが確定した後にだけデータを更新します。これにより、未確定の入力段階で誤ってバリデーションやロジックが働くのを防ぐことができるため、日本語入力の際の動作が重要なケースでは v-model が適切であると考えられます。一方、v-input のバインドによる管理は、入力データにリアルタイムで反応する必要があるユースケースに適しています。入力イベントを直接監視することで、入力が行われるたびにデータを即時に更新し、フィードバックやバリデーションをリアルタイムで行うことが可能です。
問 4
設問
ref/reactive でデータを管理した際に、それぞれの特徴や注意点、使い分けなどを教えてください。
解答
以下解答例です。
ref
- (例 1)どの値でも管理することが可能。オブジェクトが定義された際は内部で reactive でラップされる
- (例 2)公式では ref での管理を推奨されている
- (例 3).value 参照により、そのデータがリアクティブかどうかの判別がしやすい
reactive
- (例 1)オブジェクトそのもののが常に存在することを担保したいとき
- (例 2)Options API のイメージで書ける
- (例 3)プリミティブの管理ができず、必ずオブジェクトで包まなければならない
- (例 4)値を更新する際は、オブジェクト全体を更新することができない。ただし、Object.Assign を使えば可能