最近vue.jsを使っている. 今日のは感想なんで,解決策とか対処法は一切ない.ただだらだらと感想が並ぶだけである.
今までずっとReactばかりだったんだけど,書いてみると普通にかける.Reactからvueに転身するのはハードル低い感じがした.
ただ,やっぱり状態管理はしたいなーと思って最初からvuexを入れたんだ.
嬉しかったこと
非同期処理は楽
redux-thunkとかredux-sageのような別のライブラリに巻き込まれることなく,actionsとmutatonsが書ければ,非同期処理もラクラクできる.
この点は圧倒的にvuexの方が楽だった.
算出プロパティは良い
vueのcomputedというやつだけど,こいつはなかなか良い.
依存関係に基づいてキャッシュされるので,computed内で,vuexのstoreを参照していれば,storeの更新に伴ってキャッシュがクリアされ再計算され,必要であれば再描画される. vuexのstoreから値を取るときに,ここでいろんなことを挟み込めるので,とても便利.
単一ファイルコンポーネントは扱いやすい
コンポーネントのファイルがひとつにまとまっているのは非常に良い.
まぁ,vuexを入れると,vuexの状態管理がコンポーネントファイル外に出るのだが.
styleをコンポーネントファイルに書けるのは最高だ.
Reactの時に感じていた,「このコンポーネントにだけこのcssを当てたいから,頑張ってコンポーネント名をクラスに埋め込むか」とか「好きじゃないけどcss modules使うか」,みたいなことを考えなくて良い.
scoped
は素晴らしい.
ただ,一つのファイルに,html, js, cssの文法が混ざって出てくるのでエディタの設定は大変だろう.
emacsを使うなら,vue-mode
はかなりおすすめだった.
mmm-modeで1ファイル内にありながら言語ごとに切り替えてくれる.
なれるとjsxよりは書きやすいよね
本当にこれは慣れだと思う. 最初,vue.jsのtemplateを見た時に,
- 「まじかー,v-ifとか新しい記法生み出すのか」
- 「まじかー,しかもv-ifの中身,文字列で記述するんか.シンタックスハイライトできなそうだし,エラーに気付きにくそう」
と思った.
jsxは本当にピュアなjavascriptな演算子ばかり出てくる代わりに,if文すら書けないけどな.
なれると,まぁjsxよりは書きやすいかもしれないって思えてくる.
つらいところ
vuexで状態管理しながらフォームを作るの難しい
つまりはこういう問題なんだけど.
公式では双方向算出もおすすめしている.が,mutations
を書くのも,getter
, setter
書くのもだるいよねっていう話.
結局俺も納得はしていない.
フォームの値をvuexで管理しないという手もあるのだが,それをやってしまうとデバッグしにくい. というのと,例えば,画像を非同期アップロードしてその結果をフィールドに埋めてPOSTしたい,みたいな要求が出てきた時,画像の非同期アップロードと結果格納も全てコンポーネント側で持たないといけない.
そうなるとvuexを使っている意味をあまり感じなくなってくる.
それなら,そもそもフォームに関してはvuex一切使わなくていいじゃない.
Redux Formってすごかった
この点,React ReduxではRedux Formという解決策がある.
こういう話を聞いているとRedux Formってすごく便利だなーと改めて認識する.
Redux Formはフォームの値をReduxのstoreで管理しつつ,それを全てRedux Form内で隠蔽してくれる.だから,フォームを追加する際に,俺がいちいちreducerにメソッドを追加したり,actionを新たに作ったりする必要がない. 基本的にコンポーネントにRedux Formに沿った記述をすれば,その中身はRedux Form側で管理してくれる.
vuexもこういうのがあったらいいのに.
routerへのアクセスがめんどくさい
vue-routerも使っている.
例えば,
/hoge
というURLにPOSTし,正常にPOSTが成功したら /
にリダイレクトしたいとしよう.
これをvuexのactionsで書いていると,routerにアクセスできなくて困る.
vuex内では,vueコンポーネントと違って this.$router
でrouterにアクセスできない.
というのもあるのだが,重要なことで, store.state.route
is immutableとある.
そう,URLパラメータを取得するようなことはできるが,リダイレクトのためにURLを書き換えることは出来ない.
仕方ないので,こうやるしかない.
わりかし好きなのは,コンポーネントのメソッドで,
logInUser () { this.$store.dispatch('logInUser', this.user).then(() => { this.$router.push({'path': '/app'}) }).catch((err) => { console.log(err) }) }
のパターンだけど,これだと,通信結果を使うことが出来ない.
たとえば,
/items
にPOSTして,itemのidが帰ってくるとしよう.で,POST成功後に /items/:id
にリダイレクトしたい場合には,これを使うことは出来ない.
そういう場合は,vuex側でやっぱりなんとかするしかない.
import router from '../router' // ... createItem ({ commit }, item) { axios.post('/items`, item).then((res) => { router.push(`/items/${res.data.item.id}`) }) }
まとめ
ここに書いてあるほどの感動は得なかった.
確かにReduxみたいに,action, reducerをそれぞれ書かなきゃいけないめんどくささはなくなったけど,そういう気持ちはvuexとフォームの話で相殺された気がする.
そもそも俺はReact Reduxをやっていたので,学習コスト面で躓くことはなかった. まっさらな状態から始めたら,まぁvueやvuexの方が扱いやすいかもね,くらい.
Reactのjsxが嫌という話もよくわかるし,このへんは好みで決めたらいいんじゃないかなーと思う.
ただ,最近国内ではvue.jsへの関心が高いような気がする(気がするだけ,観測範囲の問題かも)ので,vueの不便だと思う点も改善されていくかもしれない.