Object.observeに未来を感じたので、es5でもちょっとだけ動くようにしてみた
互換っぽいのを作った話。
今日なんとなくAngular.jsを触ってて、「いや、俺が欲しかったのはこれじゃないんだ!」という感がムンムンだったので、前々から気になっていたObject.Observeを試してみた。
詳細は次のエントリが詳しい。
次世代JavaScriptでデータバインディング: Object.observe() を試す - ぼちぼち日記 | Postolog http://postolog.com/bbbkL2
哲学の話
Object.observeのやってることはBackbone.Modelと変わらないんだが、Backbone.ModelはBackboneのデータ構造であることをユーザーに強いてくる。どのモデルか意識せずに、オブジェクトの変化をViewから監視したい。
MVCのMの部分、JSのやるべき仕事はデータモデリングがメインになると思っていて、とくに明記せずともデータ構造を持つオブジェクトであると捉える必要がある。
ES5でも使いたくなった
つくった
mizchi/es5observe · GitHub https://github.com/mizchi/es5observe
イテラブルなオブジェクトを誤魔化すために、Object.definePropertyの嵐です。
詳細はREADME。しかし適当に作りすぎたせいで全然仕様を満たせておらず、名前空間を汚す副作用も残っている。誰かPullReqください。
リークしてたらすいませんって感じなんだけど、きたるべき未来の為に updated だけでも動く環境を作りたかった。
なにができるか
JSのオブジェクトをモデルとして、Viewの実装を次のように行える。
上のコードを読み込んだ状態か、Chrome Dev版でObject.observeが実装されてる版なら、このコードはちゃんと動く。
""" HTML <p id='status'> <span class='hp'></span> <span class='x'></span> <span class='y'></span> </p> """ window.onload = -> player_status = hp: 10, x: 3, y: 0 renderer = new StatusView $('#status'), player_status class View binding: {} hook: {} constructor: (@$el, @model) -> Object.observe @model, @_handler @_initialize() _initialize: -> for key, val of @model if typeof val in ['string', 'number'] @_update_value(key) _handler: (events) => for e in events when e.type in ['updated', 'new'] @_update_value e.name for method_name, values of @hook for v in values when v is e.name @[method_name](events) break _update_value: (value_name) -> selector = @binding[value_name] or '.'+value_name @$el.find(selector).text @model[value_name] class StatusView extends View binding: hp: '.hp' # "default binding is '.' prefix" hook: render: ['x', 'y'] render: (events) => console.log 'called by hook', events
とにかくJSの仕事をデータモデリングにだけにすると色々と幸せになるはずなんです!