ReactからVueへ移行して苦労したこと & Vueで今年知ったこと
これは Aizu Advent Calendar 2019 の 6 日目の記事です。(大遅刻してすみません 🙇♂️) 5 日目は @4rotsugd さんでC++ SSE/AVX 入門の記録、 6 日目は @acomagu さんのmakepkg-template で PKGBUILD の管理をちょっとだけ楽にするです。
去年も遅れてましたね...
(技術的に浅い話だけど許して)
React から Vue
なぜ React から Vue へ
普段私は Vue を使った Web アプリケーションを作成したりしなかったりしています。 某プロジェクトで私はとあるアプリケーションを作成することになったのですが、完全に個人開発だったのと静的ファイルを配信するだけだったため、普段とは違う React で実装を勧めました。
~某日~
私 「7 割ぐらい実装終わったぞ!(余裕の表情)」
天の声 「他で Vue 使ってるから Vue 使ってください」
私 「()」
こうして React から Vue への移行作業が始まったのです...
簡単にですが一瞬でも移行で詰まったことを少しだけ書いていきます。
子要素の定義
React では子コンポーネントを以下のようにすることで<MyComponent><div>hoge</div></MyComponent>
といったことができます。
const MyComponent = ({ children }) => { return <div>{children}</div>; };
何もおかしなことはしていませんね。特に難しくもないです。基本。
<template> <div> <slot /> </div> </template> <script> export default { name: "MyComponent" }; </script>
とすることで同じことができます。
React では Props を利用して、Vue では Slot を利用しています。
移行の際に <slot />
を思い出せなかった記憶があります...。
イベント
TypeScript を使って Vue を書いていて以下のようなコードを書いたことがある方いると思います。
methods: { handleInput(event: Event) { if (event.target instanceof HTMLInputElment) { console.log(event.target.value); }; // as 使っちゃう ver console.log(event.target as HTMLInputElment).value); } }
React だとこうなります。
const handleChange = (event: React.FormEvent<HTMLInputElement>) => { console.log(event.target.value); };
大きな違いではありませんが、React から Vue へ移行した際に便利な型生えてて欲しかった気持ちがあった気がします()
値の監視
Vue では watch
を利用して値が変更されたら実行される関数を定義できます。
data() { hoge: false }, watch: { hoge(newHoge) { console.log(newHoge) } }
React では useEffect
を利用して似たことができます。
const [hoge, setHoge] = useState(false); useEffect(() => { console.log(hoge); }, [hoge]); // hogeが変更されるような処理 ...
React から Vue へ移行した際に useEffect
を利用したコードをどうするかといったことは悩みませんでした。
ただ、本質的には watch
, useEffect
は別物なので同じことができるだけで混同しないように気をつけたいところです。
今年始めて知った/使った Vue の API など
Composition API
Vue 3.x から導入される予定の API で以下のようにすれば 今でも利用できます。
$ npm install @vue/composition-api
ここでは解説しないので気になる方はこちら を読んでください。
Vue でおなじみの this.xxx
といった書き方をせず setup
関数内に変数やイベント、ライフサイクルフックなどを書いていく感じで props
に関しても TypeScript を利用する際に type
や interface
を利用した型定義をしっかりできるのは便利。
v-slot
私が知っていたのは slot
、 slot-scope
でした。これらが非推奨になり、統合されたのが v-slot
です。
以下のように利用します。
<!-- 定義側 --> <template> <div> <div> <slot /> </div> <div> <slot name="piyo" /> </div> </div> </template> <!-- 利用する側 ---> <template> <my-layout> <div>something</div> <template v-slot:piyo> <div>piyo</div> </template> </my-layout> </template>
slot
の name
は動的に割り当てたりすることも可能ですが、スペースや記号が入っていると利用する側で素直に v-slot:xxx
と書けなくなるので個人的にはできれば避けたいです。
v-slot:[something]
といった書き方もできます(something は data)。 v-for
などを利用して子のスロットの name
に値を渡すなどする場合やスペース、記号が混入する場合などはこちらを利用しましょう。
model
v-model
がどの値をプロパティとして持ち、どのイベントを利用するか変更できます。
通常は value
とinput
イベントの組み合わせですが、change
イベントを利用したかったりする場合などに利用します。
model: { prop: "value", event: "change" }
ドキュメントの API の部分を探さないと出てこない(多分)のでchagne
イベントで呼び出した関数の中で input
を emit するか input
を emit する関数を呼んでいた人もいるはずです。(いてくれ...)