初めてフレームワークっぽいものを作ってMVVMで双方向データバインディングだヤッターと思っていたら一瞬で爆発四散した話です。
enjo.js
ひたすら設計を頑張ってたらいい感じにフレームワークっぽくなりそうと思って、ガガガっと書いたら それっぽいものが出来たので公開しました₍₍ (ง´・_・`)ว ⁾⁾
詳しい使い方は、READMEに譲ります。
MVVM?
当初のノリとしてはMVVMな感じで双方向なデータバインディングな何かになってるといいなーという感じでした。
しかし、調べたところMVVMの依存関係がどうも間違っているみたいです。
ViewはViewModelに依存し、ViewModelはModelに依存します。逆方向の依存はありません
MVVMパターンの常識 ― 「M」「V」「VM」の役割とは? − @IT
enjoではViewModelはModelに依存していて問題ないのですが、ViewModelがViewを知っちゃってるのでダメダメでした(´・_・`)
たしかに、knockoutやvueはHTMLにViewModelとのバインディング宣言や配列の描画方法の指定を書きますね・・。
enjoではViewModelのインスタンスを作る際に$viewを渡していますが、これはパラメータをバインディングする以外には内部では使わないので、ここは隠ぺいすることができそうです。
しかしarrayをデータバインディングして<ul><li>...</li></ul>
のようにforEachして描画するようなロジックをViewに書くことは現段階では出来ないのでやはりMVVMにはならなさそうです。render関数をView層として独立させる方向で現在作り直し中ですが、そのままやるとフレームワークっぽいサポートがほとんどできなくなりそうなので良いアイデアが出るまで待ちな感じです(´・_・`)
demoではViewModelのrender関数でViewを描画させているのですが、そうするとViewModelの責務が多すぎる(というか実際、Viewには<div id="hoge">
だけで良くなってしまうのでViewがいらなくなってしまう。)ということが、このへんの逆依存の弊害になります。
ということでenjo.jsはMVVMでないことが分かり一瞬で爆発四散しました(◞‸◟)
MVVMじゃないから使えないってことは無いんですが、ファットコントローラーならぬファットビューモデルなので、コードが大きくなると辛くなっていく感じになると思います。まさしくenjo...
双方向データバインディング
一応inputを書き換えるとViewModelのパラメータが書き換わるし、ViewModelのパラメータを書き換えるとinputも書き換えるようになっています。
このあたりはchangeイベントを$().on
で監視してやったり、ViewModelのパラメータを隠蔽してgetter/setter越しにアクセスしてもらうようにした後、値の変更時についでに$().val()
しているので単純です。
あと同じような仕組みで、modelの値が書き換わるとViewModelに通知が行くようになっています。
反省
上で述べた以外にも改善したい点があって、例えばパラメータのsetterが文字列でアクセスするようになってるのはもうちょっと工夫すればもっといいかんじに出来そうです。
後は命名規約についての議論があったりとか、みんなが使うと考えるといつもより注意しないといけなかったりすることが分かったりしたので、今後別のフレームワークを使う際に視点が変えられそうです。
全体的に、こういうのはどうやってつくるのかなーとか考えられたり、なんとなく理解しててダメダメだったところが発覚したり、そういうのを実装しながら学べたので面白かったです。(理解不足なところが次々発覚してややつらいですが(´;ω;`))
とりあえず勉強にはなったので、お試しでちょっと作ってみるのはおすすめかもしれません( ⁰⊖⁰)