ジンジャー研究室

長めのつぶやき。難しいことは書きません。

JavaScriptでMVC実装してみた その4

リスナ登録

ちょっと方針を変えました。
今まで「一部のModelが更新されたら全体のViewを更新」みたいな感じでやってたのですが、本当に細かな変更でも拾ってしまってコストが高そうなので必要な分だけ描画してもらうように変更してみます。

var Model = function(){
  this.listeners = [];
}
Model.prototype.addListener = function(f){
   this.listeners.push(f);
};
Model.prototype.set = function(key, value){
  this[key] = value;
  this.render();
};
Model.prototype.render = function(){
  var self = this;
  $.each(this.listeners, function(){
    this(self);
  });
};

Modelは変更して、自分に登録されている分だけリスナを呼ぶようにします。
それに伴って、Modelを変更するときは必ずsetメソッドを使ってねというルールがつきました。忘れたらどうするんだという感じですが、とりあえず保留。
めでたくモデル単位で画面が更新されるようになりました。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>
        var Model = function(){
          this.listeners = [];
        }
        Model.prototype.addListener = function(f){
          this.listeners.push(f);
        };
        Model.prototype.set = function(key, value){
          this[key] = value;
          this.render();
        };
        Model.prototype.render = function(){
          var self = this;
          $.each(this.listeners, function(){
            this(self);
          });
        };
        //ここまでフレームワーク
        
        //ここから実装
        var profile = new Model();
        profile.firstName = 'Homura';
        profile.lastName = 'Akemi';
        
        var addComponent1 = function(profile){
          // M -> V
          profile.addListener(function(p){
            $("#firstName").val(p.firstName);
            $("#lastName").val(p.lastName);
            $("#fullName").text(p.firstName + ' ' + p.lastName);
          });
          // V -> M
          $('#firstName').on('keyup', function(){
            profile.set('firstName', $(this).val());
          });
          $('#lastName').on('keyup', function(){
            profile.set('lastName', $(this).val());
          });
        };
        $(document).ready(function(){
          addComponent1(profile);
          profile.render();
        });
    </script>
  </head>
  
  <body>
    <div id='component1'>
      <dt>First Name:</dt><dd><input id="firstName" type="text"></input></dd>
      <dt>Last Name:</dt><dd><input id="lastName" type="text"></input></dd>
      <dt>Full Name:</dt><dd id="fullName"></dd>
    </div>
  </body>

</html>

そしてControllerが要らない子になりました。


動くサンプルはこちら。
http://jsfiddle.net/jinjor/CetwW/1/