体で覚えるVue.js - グローバルメソッド編 〜 JSおくのほそ道 #025

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

今回も引き続き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)

# extend( options )

```html:SubVueクラスの実装
<script src="js/vue.js"></script>
<script>
  var SubVue = Vue.extend({
    tagName: 'div',
    attributes: {
      style: 'font-size:30px'
    }
  });

  var vm = new SubVue({
    data: {
      foo: 'FOO'
    }
    template: '{{foo}}',
  });
  vm.$appendTo(document.body);
</script>
```

# config( options | key, [value] )

```html:configを変更
<div class="sample">[[foo]]</div>
<script src="js/vue.js"></script>
<script>
  Vue.config({
    delimiters: ['[', ']'],
    debug: true
  });
  var vm = new Vue({
    el: '.sample',
    data: {
      foo: 'FOO'
    }
  });
</script>
```

|設定可能な項目|デフォルト値|内容|
|-----------|---------|---|
|prefix|'v'|ディレクティブのv-textのvにあたる部分|
|debug|false|trueにするとコンソールにデバッグメッセージが表示される|
|silent|false|trueにするとコンソールに警告メッセージが表示されなくなる|
|enterClass|'v-enter'|v-animationやv-transitionディレクティブ使用時の開始CSSクラス名|
|leaveClass|'v-leave'|v-animationやv-transitionディレクティブ使用時の終了CSSクラス名|
|interpolate|true|{{foo}}の様なマスタッシュテンプレート記法でのデータバインディングを許可するか|
|delimiters|['{', '}']|マスタッシュテンプレート記法の囲み文字|

# directive( id, [definition] )

特定のビューモデルに依存しないカスタムディレクティブを生成できる。
ディレクティブの第二引数には関数とオブジェクトを渡す２ケースがある。
関数渡しケースはデータバインドが更新される度に関数が実行される。
オブジェクト渡しケースは`bind``update``unbind`の３つの関数が定義でき、それぞれ初期化時/更新時/破棄時($destroyメソッド実行)のタイミングで実行される。

```html:関数渡しパターン
<div id="sample" v-foo="Arg: bar"></div>
<script src="js/vue.js"></script>
<script>
  Vue.directive('foo', function(value) {
    this.el.innerHTML = value.toLowerCase();
  });
  var vm = new Vue({
    el: '#sample',
    data: {
      bar: 'BAR'
    }
  });
</script>
```

```html:オブジェクト渡しパターン
<div id="sample" v-foo="Arg: bar"></div>
<script src="js/vue.js"></script>
<script>
  Vue.directive('foo', {
    bind: function(value){
      this.el.style.fontSize = '30px';
    },
    update: function(value) {
      this.el.innerHTML =
        'key:' + this.key + ' value:' + value + ' arg:' + this.arg;
    },
    unbind: function(value) {
      console.log('unbind');
    }
  });
  var vm = new Vue({
    el: '#sample',
    data: {
      bar: 'BAR'
    }
  });
  setTimeout(function() {
    vm.$destroy();
  }, 5000);
</script>
```

# filter( id, definition )

特定のビューモデルに依存しないカスタムフィルタを生成できる。

```html:配列のソートを行うフィルタ
<div id="sample">
  <div v-text="foo | mysort"></div>
</div>
<script src="js/vue.js"></script>
<script>
  Vue.filter('mysort',  function(value) {
    return value.sort();
  });
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: [4,  2,  3,  1,  5]
    }
  });
</script>
```

# component( id, definition )

特定のビューモデルに依存しないカスタムコンポーネントを生成できる。
コンポーネント使用時には各ビューに対してビューモデルの生成は行う必要がある。
また、`el`要素自体に`v-component`ディレクティブは指定できず、内側の要素に指定する必要がある

```html:複数のビューモデルの共通項目にコンポーネントを使用する
<div id="sample1">
  <div v-component="foo"></div>
</div>
<div id="sample2">
  <div v-component="foo"></div>
</div>
<script src="js/vue.js"></script>
<script>
  Vue.component('foo', {
    className: 'components',
    template: 'Hello, {{msg}}',
    attributes: {
      style: 'font-size:30px'
    }
  });
  var vm1 = new Vue({
    el: '#sample1',
    data: {
      msg: 'First'
    }
  });
  var vm2 = new Vue({
    el: '#sample2',
    data: {
      msg: 'Second'
    }
  });
</script>
```

# effect( id, definition )

特定のビューモデルに依存しないエフェクト(`v-if`と組み合わせて対象値変更時に特定処理を行う)を生成できる。

```html:1秒おきに表示を切り替えてコンソールに出力
<div id="sample">
  <div v-effect="foo" v-if="bar">message</div>
</div>
<script src="js/vue.js"></script>
<script>
  Vue.effect('foo', {
    enter: function(el,  insert,  timeout){
      insert();
      console.log('inserted');
    },
    leave: function(el,  remove,  timeout){
      remove();
      console.log('removed');
    },
  });
  var vm = new Vue({
    el: '#sample',
    data: {
      bar: false
    }
  });
  setInterval( function() {
    vm.bar = vm.bar ? false : true
  }, 1000);
</script>
```

# partial( id, definition )

DOM要素の内側をコンポーネントで置換する
クエリーセレクタで既存のDOM要素を引っ張ってくる事も出来る
`v-partial`ディレクティブを使わずに`{{> foo}}`という記法で呼び出す事も出来る

```html:クエリーセレクタとテンプレート的な使い方の両方を実行
<div id="sample">
  <div v-partial="foo"></div>
  <div>{{> bar}}</div>
</div>
<div id="other">other</div>
<script src="js/vue.js"></script>
<script>
  Vue.partial('foo', '#other');
  Vue.partial('bar', '<p>Partial</p>');
  var vm = new Vue({
    el: '#sample',
  });
</script>
```

# nextTick( callback )

コールバック関数を非同期バッチで実行する。
`window.requestAnimationFrame`が使える環境では使うが、それ以外の環境では`setTimeout( callback, 0)`が内部的に使用される。
`setTimeout( callback, 0)`と同じと思っておくと解釈しやすいかも？


下記の例は2だけを出力する。
`vm.foo = 1`も実行されるがバッチ実行により$watchの監視には引っかからない。

```html:データバインドを三回実行して$watchで監視
<div id="sample" v-text="foo"></div>
<script src="js/vue.js"></script>
<script>
  Vue.nextTick(function(){
    vm.foo = 1;
  });
  Vue.nextTick(function(){
    vm.foo = 2;
  });
  var vm = new Vue({
    el: '#sample',
    created: function() {
      this.$watch('foo', function(value) {
        console.log(value); // 2つのNextTickはバッチで実行され$watchが認識するのは最終的な2の値。
      });
    }
  });
</script>
```

# require( module )

Vue.jsの内部的なモジュールにアクセス出来る。

```html:内部モジュールを取得
<script src="js/vue.js"></script>
<script>
  var utils = Vue.require('utils');
  var config = Vue.require('config');
  var transition = Vue.require('transition');
  var observer = Vue.require('observer');
</script>
```

===

あと`use`というプラグインを使うメソッドがありますが、環境がらみの話が出て来てややこしいので今回は無視します。

今回は以上です。次回はフィルターをやります。