体で覚えるVue.js - インスタンスメンバ編 〜 JSおくのほそ道 #024

こんにちは、ほそ道です。

今回も引き続きVue.jsのインスタンスメンバを体で覚えます。
前回まで同様、シンプルなサンプルに沢山触れる事でどんな道具があるのかをバンバン体験していくスタイルでやってまいります。

[ViewModel生成編](http://qiita.com/setzz/items/3faf74b7141081731a75)
[ディレクティブ編](http://qiita.com/setzz/items/25041c1d46452de84aa6)
[インスタンスメンバ編]
(http://qiita.com/setzz/items/ebbfcc3565bcd27f344c)
[グローバルメソッド編]
(http://qiita.com/setzz/items/8f06f2fe6049173b17f9)
[フィルター編]
(http://qiita.com/setzz/items/e37c47d3f22e5738eb84)
[v-repeatネスト編]
(http://qiita.com/setzz/items/6f22ebd15bcc0afe1ab0)
[全体の目次はこちら](http://qiita.com/setzz/items/ad9a9c99a4fda041a563)

# プロパティ

## $el

- Type: HTMLElement
- Read only

ビューモデルと関連付いているDOMを指す。

```html:$elを表示
<div id="sample" v-text="foo"></div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'FOO',
    }
  });
  console.log(vm.$el); // <div id="sample">FOO</div>
</script>
```

## $data

- Type: Object

データバインド等に使用されるデータオブジェクト。
アクセス時、$dataは省略できる。

```html:$dataの表示
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    data: {
      foo: 'FOO',
    }
  });
  console.log(vm.$data.foo); // FOO
  console.log(vm.foo);       // FOO
</script>
```

## $options

- Type: Object

ビューモデル生成時の引数にあたるオプションオブジェクト。

```html:$optionの表示
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    lazy: true,
    data: {
      foo: 'FOO',
    }
  });
  console.log(vm.$options); // Object {lazy: true,  data: Object}
</script>
```

## $

- Type: Object
- Read only

`v-ref`で指定したコンポーネントのデータオブジェクト。

```html:$の表示
<div id="sample">
  <div v-ref="foo" v-component="bar">value</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    components: {
      bar: {
        data: {
          x: 100,
          y: 200
        },
      }
    }
  });
  console.log(vm.$.foo.x); // 100
  console.log(vm.$.foo.y); // 200
</script>
```

## $index

- Type: Number

`v-repeat`と組み合わせたときに配列インデックスにアクセス出来る

```html:v-repeatしながらインデックスと値をレンダリング
<div id="sample">
  <div v-repeat="foo">{{$index + ':' + $value}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data:{
      foo: [100,  200,   300,   400,   500]
    }
  });
  console.log(vm.$index);
</script>
```

## $parent

- Type: Object ViewModel
- Read only

親となるビューモデル。

```html:childからみたparentデータの表示
<script src="js/vue.js"></script>
<script>
  var parent = new Vue({
    data: {
      foo: {
        x: 100,
      }
    }
  });
  var child = new Vue({
    parent: parent
  });
  console.log(child.$parent.foo.x);  // 100
</script>
```

## $root

- Type: Object ViewModel
- Read only

親ビューオブジェクトをたどった最も親なビューモデル。

```html:$rootのデータを表示(途中に居る親のデータにはアクセス出来ない)
<script src="js/vue.js"></script>
<script>
  var grand_parent = new Vue({
    data: {
      foo: {}
    }
  });
  var parent = new Vue({
    parent: grand_parent,
    data: {
      bar: {}
    }
  });
  var child = new Vue({
    parent: parent
  });
  console.log(typeof child.$root.foo);  // object
  console.log(typeof child.$root.bar);  // undefined
</script>
```

## $compiler

- Type: Object Compiler
- Read only

ビューモデルコンパイラ。データバインドに関する内部情報を保持しているが公式ドキュメントによると使用は避けるべしとの事。

```html:$compilerのデータにアクセス(vmやelを保持している)
<div id="sample" v-text="foo"></div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: "#sample",
    data: {
      foo: 'FOO'
    }
  });
  console.log(vm === vm.$compiler.vm);      // true
  console.log(vm.$el === vm.$compiler.el);  // true
</script>
```

# メソッド

## $watch( keypath, callback )

値の変更を監視させ、変更時にはコールバック関数を実行する。
配列の要素変更時にはコールバックが第二引数`mutation`を受け取り、このオブジェクトは変更に関する情報(`method`, `args`, `result`, `inserted`, `removed`)を保持している。

```html:配列内容変更とデータ変更の監視
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    data: {
      foo: [],
      bar: 100
    }
  });
  vm.$watch('foo',  function(value, mutation) {
    console.log(vm.foo === value);
    console.log(mutation.method);
    console.log(mutation.inserted);
  });
  vm.foo.push(10000); // trueと'push'と[10000]がコンソールに表示

  vm.$watch('bar',  function(value) {
    console.log(value);
  });
  vm.bar = 12345; // 12345がコンソールに表示
</script>
```

## $unwatch( keypath )

$watchにより行われている変更監視を止める。

```html:監視停止
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    data: {
      foo: 10,
    }
  });
  vm.$watch('foo',  function(value) {
    console.log(value);
  });
  vm.foo = 100; // 100がコンソールに表示

  vm.$unwatch('foo');
  vm.foo = 1000; //　なにも表示されない
</script>
```

## $get( keypath ) / $set( keypath, value )

$dataが保持するデータの取得/上書きを行う。

```html:値の設定と取得
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    data: {
      foo: 10,
    }
  });
  console.log(vm.$get('foo')); // 10

  vm.$set('foo', 100);
  console.log(vm.$get('foo')); // 100
</script>
```

## イベント処理メソッド

### $on( event, callback ) / $emit( event, [args…] )

$onはイベントリスニングを開始し、イベントの発生を待ち受ける。
$emitはイベントを発生させる。引数を渡す事が出来る。

```html:fooイベントをreadyとクリック時に発生させる
<div id="sample" v-on="click: bar">click here</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    created: function() {
      this.$on('foo', function(x){
        console.log(x);
      });
    },
    ready: function() {
      this.$emit('foo', 'ready event');
    },
    methods: {
      bar: function() {
        this.$emit('foo', 'click event');
      }
    }
  });
</script>
```

### $dispatch( event, [args…] ) / $broadcast( event, [args…] )

$dispatchはイベントを発生させ、親ビューモデルの方向に伝播する。(言い方を変えると親が同じ名前のイベントリスニングを行っていれば実行される)

$broadcastは$dispatchとは逆に子ビューモデルの方向に伝播する。
※$broadcastは自身のイベントは発生させず、子側のイベントだけが発生する

```html:$dispatchと$broadcastを発生/伝播させる
<script src="js/vue.js"></script>
<script>
  var parent = new Vue({
    created: function() {
      this.$on('foo', function() {
        console.log('parent event');
      })
    }
  });
  var child = new Vue({
    parent: parent,
    created: function() {
      this.$on('foo', function() {
        console.log('child event');
      })
    }
  });
  var grandchild = new Vue({
    parent: child,
    created: function() {
      this.$on('foo', function() {
        console.log('grandchild event');
      })
    }
  });
  grandchild.$dispatch('foo'); // grandchild/child/parentのイベント処理が実行される
  parent.$broadcast('foo'); // child/grandchildのイベント処理が実行される
</script>
```

### $once( event, callback )

イベントリスニングを開始し、そのイベントは一度だけしか実行されない

```html:2つめのemitは無視される
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    created: function() {
      this.$once('foo', function(){
        console.log('event');
      });
    }
  });
  vm.$emit('foo');　
  vm.$emit('foo');
```

### $off( [event, callback] )

イベントリスニングをやめる

```html:最後のemitは無視される
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    created: function() {
      this.$on('foo', function(){
        console.log('event');
      });
    }
  });
  vm.$emit('foo');
  vm.$off('foo');
  vm.$emit('foo');
</script>
```

## DOM操作メソッド

### $appendTo( element | selector )

指定した要素内にelを追加する

```html:bodyに追加
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    template: 'Hello'
  });
  vm.$appendTo(document.body);
</script>
```

### $before( element | selector ) / $after( element | selector )

$before指定した要素の前にelを追加する
$afterは指定した要素の後にelを追加する

```html:#middleの要素前後にelを追加
<div id="middle">Middle</div>
<script src="js/vue.js"></script>
<script>
  var first = new Vue({
    template: 'First'
  });
  var last= new Vue({
    template: 'Last'
  });
  first.$before('#middle');
  last.$after('#middle');
</script>
```

### $remove()

elを削除する

```html:表示の一秒後に削除
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    template: 'Hello'
  });
  vm.$appendTo(document.body);
  setTimeout(function() {
    vm.$remove();
  }, 1000);
</script>
```

## $destroy()

elを破棄する
$removeとの違いとして$destroy実行後にビューモデルをページに追加するとディレクティブの関連付けが失われる

```html:destroyによってv-onの関連付けが破棄される(removeは破棄されない)
<div id="sample" v-text="foo" v-on="click: bar">Hello</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'FOO'
    },
    methods: {
      bar: function() {alert('bar');}
    }
  });
  vm.$destroy();
  vm.$appendTo(document.body);
</script>
```

今回は以上です。次回はグローバルメソッド編です。