|
| 1 | +# データプロパティとメソッド |
| 2 | + |
| 3 | +## データプロパティ |
| 4 | + |
| 5 | +コンポーネントの `data` オプションは関数です。Vue は新しいコンポーネントのインスタンスを作成する際に、この関数を呼び出します。これはオブジェクトを返すもので、 Vue はオブジェクトをそのリアクティブシステムでラップして、コンポーネントのインスタンスに `$data` として格納します。便宜上、そのオブジェクトのトップレベルのプロパティは、コンポーネントのインスタンスを介して直接公開されます: |
| 6 | + |
| 7 | +```js |
| 8 | +const app = Vue.createApp({ |
| 9 | + data() { |
| 10 | + return { count: 4 } |
| 11 | + } |
| 12 | +}) |
| 13 | + |
| 14 | +const vm = app.mount('#app') |
| 15 | + |
| 16 | +console.log(vm.$data.count) // => 4 |
| 17 | +console.log(vm.count) // => 4 |
| 18 | + |
| 19 | +// vm.count に値を代入すると、 $data.count も更新 |
| 20 | +vm.count = 5 |
| 21 | +console.log(vm.$data.count) // => 5 |
| 22 | + |
| 23 | +// ... 逆もまた同様 |
| 24 | +vm.$data.count = 6 |
| 25 | +console.log(vm.count) // => 6 |
| 26 | +``` |
| 27 | + |
| 28 | +これらのインスタンスプロパティは、インスタンスの初回作成時にのみ追加されます。そのため、 `data` 関数から返されたオブジェクトに、それらがすべて含まれていることを確認する必要があります。必要に応じて、必要な値がまだ利用できないプロパティには、 `null` や `undefined` 、またはその他のプレースホルダーの値を使ってください。 |
| 29 | + |
| 30 | +新しいプロパティを `data` に含めずに、コンポーネントのインスタンスに直接追加することはできます。しかし、このプロパティはリアクティブな `$data` オブジェクトによって支えられていないので、 [Vue のリアクティブシステム](reactivity.html) によって、自動的に追跡されることはありません。 |
| 31 | + |
| 32 | +Vue は、コンポーネントのインスタンスを介して自身のビルトイン API を公開する際に、 `$` をプレフィックスとして使います。 また、内部プロパティのために `_` を予約しています。トップレベルの `data` プロパティの名前に、これらの文字からはじまる名前を使うことは避けるべきです。 |
| 33 | + |
| 34 | +## メソッド |
| 35 | + |
| 36 | +コンポーネントのインスタンスにメソッドを追加するには、 `methods` オプションを使います。これは必要なメソッドを含むオブジェクトでなければなりません: |
| 37 | + |
| 38 | +```js |
| 39 | +const app = Vue.createApp({ |
| 40 | + data() { |
| 41 | + return { count: 4 } |
| 42 | + }, |
| 43 | + methods: { |
| 44 | + increment() { |
| 45 | + // `this` はコンポーネントインスタンスを参照 |
| 46 | + this.count++ |
| 47 | + } |
| 48 | + } |
| 49 | +}) |
| 50 | + |
| 51 | +const vm = app.mount('#app') |
| 52 | + |
| 53 | +console.log(vm.count) // => 4 |
| 54 | + |
| 55 | +vm.increment() |
| 56 | + |
| 57 | +console.log(vm.count) // => 5 |
| 58 | +``` |
| 59 | + |
| 60 | +Vue は、 `methods` の `this` を自動的に束縛して、常にコンポーネントのインスタンスを参照します。これにより、メソッドがイベントリスナやコールバックとして使われる際に、正しい `this` の値を保持することができます。Vue が適切な `this` の値を束縛するのを防ぐため、 `methods` を定義する際にはアロー関数を使うのは避けるべきです。 |
| 61 | + |
| 62 | +コンポーネントのインスタンスの他のすべてのプロパティと同様に、 `methods` はコンポーネントのテンプレート内からアクセスできます。テンプレート内からはよくイベントリスナとして使われます: |
| 63 | + |
| 64 | +```html |
| 65 | +<button @click="increment">Up vote</button> |
| 66 | +``` |
| 67 | + |
| 68 | +上の例では、 `<button>` がクリックされると、 `increment` メソッドが呼ばれます。 |
| 69 | + |
| 70 | +また、テンプレートから直接メソッドを呼び出すこともできます。後で説明しますが、通常は変わりに [算出プロパティ](computed.html) を使うのがよいです。しかし、メソッドを使うことは算出プロパティが実行可能なオプションではない場合に役に立ちます。テンプレートが JavaScript の式をサポートしていれば、どこでもメソッドを呼び出すことができます: |
| 71 | + |
| 72 | +```html |
| 73 | +<span :title="toTitleDate(date)"> |
| 74 | + {{ formatDate(date) }} |
| 75 | +</span> |
| 76 | +``` |
| 77 | + |
| 78 | +`toTitleDate` や `formatDate` メソッドがどれかリアクティブなデータにアクセスすると、あたかもテンプレートで直接使われていたかのように、それはレンダリングの依存関係として追跡されます。 |
| 79 | + |
| 80 | +テンプレートから呼び出されたメソッドは、データの変更や非同期処理の発火などの副作用があってはなりません。もしそのようなことをしたくなったら、代わりに [ライフサイクルフック](instance.html#lifecycle-hooks) を使うべきです。 |
| 81 | + |
| 82 | +### Debounce (デバウンス) と Throttle (スロットル) |
| 83 | + |
| 84 | +Vue は、 Debounce や Throttle のサポートが組み込まれていませんが、 [Lodash](https://lodash.com/) などのライブラリを使って実装することができます。 |
| 85 | + |
| 86 | +コンポーネントが一度しか使われない場合には、 `methods` の中で直接 Debounce を適用することができます: |
| 87 | + |
| 88 | +```html |
| 89 | +< script src= "https://unpkg.com/[email protected]/lodash.min.js"></ script> |
| 90 | +<script> |
| 91 | + Vue.createApp({ |
| 92 | + methods: { |
| 93 | + // Lodash による Debounce |
| 94 | + click: _.debounce(function() { |
| 95 | + // ... クリックに反応 ... |
| 96 | + }, 500) |
| 97 | + } |
| 98 | + }).mount('#app') |
| 99 | +</script> |
| 100 | +``` |
| 101 | + |
| 102 | +しかし、この方法ではコンポーネントが再利用される場合に、すべてのコンポーネントが同じ Debounce 関数を共有するため、問題が起きる可能性があります。コンポーネントのインスタンスをお互いに独立させるために、 `created` ライフサイクルフックに Debounce 関数を追加することができます: |
| 103 | + |
| 104 | +```js |
| 105 | +app.component('save-button', { |
| 106 | + created() { |
| 107 | + // Lodash によるDebounce |
| 108 | + this.debouncedClick = _.debounce(this.click, 500) |
| 109 | + }, |
| 110 | + unmounted() { |
| 111 | + // コンポーネントが削除されたらタイマーをキャンセル |
| 112 | + this.debouncedClick.cancel() |
| 113 | + }, |
| 114 | + methods: { |
| 115 | + click() { |
| 116 | + // ... クリックに反応 ... |
| 117 | + } |
| 118 | + }, |
| 119 | + template: ` |
| 120 | + <button @click="debouncedClick"> |
| 121 | + Save |
| 122 | + </button> |
| 123 | + ` |
| 124 | +}) |
| 125 | +``` |
0 commit comments