MVCObject + events が超絶便利な件

Node.jsで管理画面やサーバーなどを作っている時にセッション管理などをすることはあると思います。

- ユーザーごとにイベントが発生して、それをイベントリスナーでキャッチしたい
- 値も保持したい
- 値が変化したら知りたい
- DBは使いたくない (DBを使う程でもない)
- once() とか off() とか使いたい

そうゆうときに便利なモジュールはないものか、と探したものの無かったので、オレオレモジュールを作りました。

# インストール

npmコマンドで一発インストールです。

```shell-session
npm install mvcobject
```

# MVCClassの基本

まずはインスタンスを作ります。
コンストラクタは、初期値を取ります。省略しても構いません。

```js
var mvcclass = require('mvcclass');

var initialValues = {
  value1: 'Hello World!',
  value2: 3
};
var myClass = new mvcclass(initialValues);
```

`value1`を取り出すには、`get()`メソッドを使います。

```js
console.log('value1 = ' + myClass.get('value1'));  // 'Hello World!'
```

書き換えるには`set()`メソッドです。

```js
myClass.set('value1', 'こんにちは');
```

このときに一緒に`value1_changed`イベントが発生します。
`on()`メソッドでキャッチできます。
イベントリスナーの第一引数には、変化したキー名が渡されるので、何が変化したのかを知ることが出来ます。

```js
myClass.on('value1_changed', function(key) {
  // key = 'value1'
  console.log("value1が変化した  new value = " + myClass.get(key)); 
});
```

# イベントを発行したい

普通のEventEmitterと同じように、`emit()`メソッドとか`once()`とかも使えます。

```js
myClass.once('login', function(userInfo) {
  console.log('--->onLogin', userInfo);
});

myClass.emit('login', {
  name: '山田太郎',
  email: 'taro@yamada.jp'
});
```

# ワイルドカードを使いたい

イベント毎に`on()`メソッドを書くのは面倒なので、ワイルドカードを使いましょう。
コンストラクタで`wildcard`と`delimiter`を指定してあげます。

`wildcard`, `delimiter`, `newListener`, `maxListeners`は初期値にセットしても
値としては設定されません。
代わりに親クラスである[EventEmitter2](https://github.com/asyncly/EventEmitter2)に渡されます。

```js
var myClass = new mvcclass({
  'wildcard': true,   // ワイルドカードの仕様を許可
  'delimiter': '_',   // 区切り文字
  'value1': 'Hello World',
  'value2': 3
});

myClass.on('*_changed', onValueChanged);

myClass.set('value1', 'こんにちは');
myClass.set('value2', myClass.get('value2') + 15);

// Outputs
//
// --> eventName: value1_changed, newValue: こんにちは
// --> eventName: value2_changed, newValue: 18

```

全部のイベントを取りたかったら、このようにも出来ます。

```js
var myClass = new mvcclass({
  'wildcard': true,   // ワイルドカードの仕様を許可
  'value1': 'Hello World',
  'value2': 3
});

myClass.on('*', function(arg) {
  var eventName = this.event;
  console.log();
  if (eventName.indexOf("_changed") > -1) {
    console.log("--> eventName: " + eventName + ", newValue: " + this.get(arg));
  } else {
    console.log("--> eventName: " + eventName);
  }
});

myClass.set('value1', 'こんにちは');
myClass.set('value2', myClass.get('value2') + 15);

myClass.emit('myEvent');

// Outputs
//
// --> eventName: value1_changed, newValue: こんにちは
// --> eventName: value2_changed, newValue: 18
// --> eventName: myEvent

```

# 他のオブジェクトとプロパティを連携させたい

テンプレートに反映させるのに、いくつかのオブジェクトから値を取ってきて、一つにまとめて、、、とかありますよね。
`bindTo(key, target, targetKey?, noNotify?)`メソッドでシンプルに書けます。

```js
var myClass = new mvcclass({
  'enable': true
});

// anotherObject.enable = myClass.enable になります
var anotherObject = new mvcclass();
myClass.bindTo('enable', anotherObject);

anotherObject.on('enable_changed', function(key) {
  console.log('--> (anotherObject) enable = ' + this.get(key));
});

myClass.set('enable', false);

// Outputs
//
// --> (anotherObject) enable = false
```

プロパティ名が異なるときは、こうします。

```js
// anotherObject.editable = myClass.enable;
myClass.bindTo('enable', anotherObject, 'editable');
```

`(key)_changed`イベントを発生させたくない時は、noNotifyをtrueにします。

```js

myClass.on('editable_changed', function(key) {
  console.log('editable_changed on myClass');  // これは出る
});

anotherObject.on('editable_changed', function(key) {
  console.log('editable_changed on anotherObject');  //これは出ない
});

// anotherObject.editable = myClass.enable;
myClass.bindTo('enable', anotherObject, 'editable', true);

myClass.set('editable', false);

setTimeout(function() {
  anotherObject.notify('editable'); // editable_changed を 後から通知する
}, 10000);
```

# 自分のモジュールを作りたい時

例えば セッションを保持するクラスを作ります。

```js:Session.js
var mvcclass = require("mvcclass"),
    util = require('util');

function Session(params) {
  mvcclass.call(this, params);

  this.on('login', this.onLogin);
}

util.inherits(Session, OwnClass);

Session.prototype.onLogin = function(data) {
  console.log('---> login', data);

  this.setValues(data);  // setValuesメソッドでまとめて値を保存もできる
};

module.exports = Session;
```

このクラスはこのように使えます。

```js

var Session = require('./Session'),
    session = new Session();

session.emit('login', {
  name: '山田太郎',
  email: 'taro@yamada.jp'
});

session.on('name_changed', function(key) {
  document.getElementById('username').value = this.get(key);
});
```

# 最後に

その他のメソッドは[EventEmitter2](https://github.com/asyncly/EventEmitter2)と[MVCObjet](https://github.com/Treri/MVCObject)を参照してください。