こんにちは。
echoesチームの加藤です。
Webの業界に飛び込んで約3年、BEをメイン開発をしてきたのですが、ここ半年ちょっとFEを担当することが増えてきました。
その半年の間に自分が学習した中で、躓いて印象的だったことについて今回は記事を書いてみようと思います。
何をしていたのか
Vue2を使ったこんなイメージの画面を作っていました。
動きとしては、フォームに文字を入力すると、入力した文字列が入力に合わせて下の表示部分に表示されるというものです。
この画面のデータをVueのcomponentで実装したイメージがこんな感じです。
(説明用のイメージなので、かなりミニマムにしています)
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 |
<template> <div class="contents"> <div class="forms" style="margin-bottom: 50px:"> <h2>Forms</h2> <label> {{ "Form1" }} <input type="text" v-model="formContents.form1.contents"/> </label> </div> </div> </template> <script> export default { name: "ReactiveSample", data() { return { formContents: {} created() { this.formContents.form1 = {contents: ''} } } </script> <style scoped> .contents { display: flex; flex-direction: column; } </style> |
問題
先ほど書いたように、フォームに入力した文字列が入力に合わせて表示される想定だったのですが、入力し終わっても表示部分は真っ白なままでした。
原因・解決策
原因と答えは全てここに記載されていました。
https://v2.ja.vuejs.org/v2/guide/reactivity#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6
Vue2では、インスタンスの初期化以降に発生するObjectのプロパティの追加・削除を検出することができず、
1 2 3 |
created() { this.formContents.form1 = {contents: ''} } |
動的に追加したりしたいからといって、このように初期化以降の処理でプロパティの追加をしてもObjectには追加することができなかったのです。
じゃあどうするか?というと
1 2 3 |
created() { this.$set(this.formContents, 'form1', {contents: ''}) } |
このようにVueのsetメソッドを使うことで、プロパティの追加ができます。
修正して追加した画面がこちら。
ちゃんとフォームに入力した文字列が、入力と合わせて表示されるようになりました。
ちなみに先ほど貼り付けたVue2のドキュメントに記載がありますが、Objectだけでなく配列でも同じような仕様があるようです。
なお、こちらの仕様はVue3では変更されていて、修正前のコードのようにsetメソッドを使わなくてもプロパティの追加・削除を検出できるようになっています。
まとめ
VueどころかFEの知識がほとんどない状態で躓いてばかりの半年間で、特に大きく躓いて解決に時間がかかったことを今回記事にしてみました。
最初からドキュメントを読めという話ではありますが、今回の件については原因が全く見当も付かず、ネットの海を彷徨ってもなかなか同じようなことに躓いた方がいらっしゃらなかった(ググるの下手なだけかも)ので、同じような悩みにぶつかった人の目に留まって、解決に繋がれば幸いです。