Vue3のComposition APIを使っています。
Options APIも使っていましたが、Composition APIはなんかストレスが溜まります。
開発していても「罠」が多くてハマりやすく、あまり気持ちよく開発できていません。
ストレスがたまると健康に悪いので、この記事で発散することにします。
refが意味不明すぎる
データをリアクティブにする方法の1つとしてrefがありますが、これの挙動が謎すぎます。
const ref_data = ref(1)
まあこれはいいです。わかります。データをラップするオブジェクトなんだなと伝わります。
<MyComponent :ref_data="ref_data">
こうするとrefが渡されるかと思いますが、実際は自動アンラップされてNumberが渡されます。
基本的に設計では「ユーザーに隠れてごにょごにょする」という設計は、嫌われることが多いです。
これは「暗黙の了解」の設計で、ユーザーがその設計を学習しないといけません。
この自動アンラップの挙動を知ってから嫌な予感がうっすらしていました。
では次のコードはどうでしょうか。
<input type="text" @input="$emit('something', ref_data)" />
$emit()
です。実はこれもref_data
は自動アンラップされます。実際にはref_data.value
が渡されます。
私はこの挙動を知ったとき「ああ、これは君からの挑戦状なんだね?」という感想が湧いてきました。
ユーザーに隠れてごにょごにょするのが大好きなら、君は神秘主義者だね? ということです。
まぁ、これらはまだ私が学習すればいいんです。ここまでは堪忍袋の緒もまだ余裕があります。
しかし次の挙動です。
class Model {
constructor () {
this.ref_data = ref(1)
}
}
こんなモデルを書いたとします。で、使います。
const model = new Model()
<MyComponent :ref_data="model.ref_data" />
これはref_data
は展開されるでしょうか?
正解は「展開されない」です。
model
はリアクティブじゃないため、Vueは自動アンラップを行わないようです。
これを自動アンラップするには
const model = reactive(new Model())
としなければいけません。
しかしどういうわけか、reactive()
で包まなくても、
<div>{{ model.ref_data }}</div>
という参照はリアクティブになります。はぁ???
つまりこういうことです。
プレーンなオブジェクトはリアクティブじゃない。リアクティブにするにはreactive()
でラップする必要がある。
プレーンなオブジェクトのプロパティをリアクティブにすると、:ref_data="model.ref_data"
などのバインドは自動アンラップされないが、{{ model.ref_data }}
などの参照はリアクティブになり自動アンラップされる。
親のオブジェクトをリアクティブにすると:ref_data="model.ref_data"
も自動アンラップされる。
ちょっといいですか?
私は、Vue3に対する恋心が急激に冷めつつあります。
ずっとVue3で開発してきましたが、どうも最近はソリが合わないようです。
あー!!!!むかつくなぁーーー!!!!がーーー!!!!