ガイド
基本的な使い方
- インストール
- はじめに
- Vue インスタンス
- テンプレート構文
- 算出プロパティとウォッチャ
- クラスとスタイルのバインディング
- 条件付きレンダリング
- リストレンダリング
- イベントハンドリング
- フォーム入力バインディング
- コンポーネントの基本
コンポーネントの詳細
- コンポーネントの登録
- プロパティ
- カスタムイベント
- スロット
- 動的 & 非同期コンポーネント
- 特別な問題に対処する
トランジションとアニメーション
- Enter/Leave とトランジション一覧
- 状態のトランジション
再利用と構成
- ミックスイン
- カスタムディレクティブ
- 描画関数とJSX
- プラグイン
- フィルター
ツール
- 単一ファイルコンポーネント
- テスト
- TypeScript のサポート
- プロダクション環境への配信
スケールアップ
- ルーティング
- 状態管理
- サーバサイドレンダリング
- セキュリティ
内部
- リアクティブの探求
移行
- Vue 1.x からの移行
- Vue Router 0.7.x からの移行
- Vuex 0.6.x から 1.0 への移行
その他
- 他のフレームワークとの比較
- Vue.js コミュニティへ参加しましょう!
- チームに会おう
v2.x 以前のドキュメントです。 v3.x のドキュメントを見たい場合はこちら
Vue 1.x からの移行
最終更新日: 2020年3月7日
FAQ
わお、このページは非常に長いですね!ということは、バージョン 2.0 は従来と全く異なっていて、私は全てを基礎からもう一度学ぶ必要があるのでしょう。その上で、移行は不可能ということでしょうか?
よくぞ聞いてくれました!その答えは No です。 API のおおよそ 90% が同じで、かつ基本となるコンセプトは変わっていません。 このセクションは、非常に詳しい説明と、多くの例を提供したいため、非常に長いです。 ですが、安心してください、 このセクションは、上から下まで全て読むようなものではありません!
どこから移行をはじめるべきですか?
現在のプロジェクト上で、移行ヘルパーを実行します。私たちは以前の Vue 開発を単純なコマンドライン インターフェースに最小構成で注意深く詰め込みました。それは、廃止された機能を認識するたびに移行をサジェストし、その上で詳しい情報へのリンクを提供します。
その後、このページのサイドバーの目次より、あなたが影響を受ける可能性のあるトピックを参照してください。移行ヘルパーが何も検出していない場合、それは素晴らしいことです。
もし、テストがある場合は、それらを実行し、失敗したものを参照してください。テストがない場合は、ブラウザ上でアプリケーションを開き、警告やエラーに対して、あなた自身の目で確認してください。
そろそろ、あなたのアプリケーションは完全に移行されるべきでしょう。もし、あなたがよりいっそう飢えている場合は、このページを残りの部分を読む、もしくは新しく、かつ改良されたガイドに「はじめに」から飛び込むこともできます。あなたは既に基本となるコンセプトに精通しているので、多くの場合、拾い読みすることとなります。
Vue 1.x のアプリケーションを 2.0 に移行するにはどのくらいの時間がかかりますか?
移行期間は、いくつかの要因に依存します:
アプリケーションの規模(小〜中規模アプリケーションの場合、おそらく1日かからないでしょう)
新しい機能を使う場合は、何度も混乱したことがあるでしょう。😉 特に差別をしているわけではなく、 Vue 2.0 で作る際も、同様のことは起こるでしょう。
将来的に廃止される機能を使用している場合、大半は検索と置換でアップグレードできますが、一部は少し時間がかかるかもしれません。もしあなたが、現在のベストプラクティスを踏襲していない場合、 Vue 2.0 はあなたにそれを強制します。これは、長期的に見ると良いことですが、大幅(though possibly overdue)なリファクタリングを意味するかもしれません。
もし Vue 2.0 へアップグレードする場合、 Vuex および Vue Router もアップグレードする必要がありますか?
Vue Router 2 は、Vue 2.0 のみに互換性があるため、アップグレードする必要があります。同様に、Vue-Router 向けの移行パス に従う必要があります。
幸いなことに、ほとんどのアプリケーションは、ルーターに関するコードが多くないため、この作業が 1 時間以上かかることはおそらくありません。
Vuex については、バージョン 0.8 は Vue 2.0 との互換性があるため、アップグレードは強制ではありません。
Vuex 2 に導入された、新たな機能やボイラープレートを使用したい場合でないかぎり、直ちにアップグレードする必要はないでしょう。
テンプレート
フラグメントインスタンス 削除
すべてのコンポーネントは、1つのルート要素を持っている必要があります。フラグメントインスタンスは、もはや許されません。もし、あなたが以下のようなテンプレートを使用している場合:
<p>foo</p>
<p>bar</p>
単に全体を新しい要素で囲うことを推奨します。
例えば、このような形となります:
<div>
<p>foo</p>
<p>bar</p>
</div>
移行ガイド
アップグレード後に end-to-end のテストスイートや、それに準ずるアプリケーションを実行し、テンプレート内の複数のルート要素に対してのコンソールの警告を探します。
ライフサイクルフック
beforeCompile
削除
代わりに、 created
フックを使用します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
compiled
置き換え
代わりに、新たに mounted
フックを使用します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
attached
削除
他のフックで DOM チェックをカスタムして使用します。 例えば、以下の場合:
attached: function () {
doSomething()
}
このように置き換えます:
mounted: function () {
this.$nextTick(function () {
doSomething()
})
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
detached
削除
他のフックで DOM チェックをカスタムして使用します。 例えば、以下の場合:
detached: function () {
doSomething()
}
このように置き換えます:
destroyed: function () {
this.$nextTick(function () {
doSomething()
})
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
init
置き換え
代わりに新しい beforeCreate
フックを使用します。これは本質的には同じものです。
他のライフサイクルメソッドとの整合性のために改名されました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
ready
置き換え
かわりに、新しい mounted フックを使用します。ただし、マウントされたとしてもドキュメントに存在する保証はありません。 そのため、Vue.nextTick/vm.$nextTick
で包む必要があります。 例えば、以下のようになります:
mounted: function () {
this.$nextTick(function () {
// this.$el がドキュメント内にあることを前提としたコードを書きます
})
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、このフックを全て見つけます。
v-for
配列においての v-for
の引数の順序 変更
index
を含む場合、引数を (index, value)
の順序で使用していました。それは今は、 (value, index)
となり、 JavaScript ネイティブの forEach
や map
と一貫性を持つようになりました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、非推奨な引数の順序を見つけます。
position
や num
のような、あまり使われないような名称をインデックスの引数につけた場合、ヘルパーはそれを検出できないことがありますが、ご了承ください。
オブジェクトにおいての v-for
の引数の順序 変更
プロパティ名/キーを含む場合、引数を (name, value)
の順序で使用していました。それは今は、 (value, name)
となり、 lodash などの一般的なオブジェクトのイテレータと一貫性を持つようになりました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、非推奨な引数の順序を見つけます。
もしキーとなる引数に name
や property
のような、名称をつけていた場合、ヘルパーはそれを検出できないことがありますが、ご了承ください。
$index
および $key
削除
暗黙的に割り当てられていた $index
および $key
変数が、 v-for
にて明示的にそれらを定義するために廃止されました。
これは、 Vue の経験が浅い開発者がネストされたループを扱う場合に、コードを読むことが容易になります。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、これらの非推奨な変数を見つけます。もし間違いがある場合以下のような、 console errors などが表示されます: Uncaught ReferenceError: $index is not defined
track-by
置き換え
track-by
は key
に置き換えられました。
他の属性と同様に、 v-bind
または :
接頭辞がない場合は文字列として処理されます。
殆どの場合、式として動的なバインディングを行いたいでしょう。その場合、例えば、以下の代わりに
<div v-for="item in items" track-by="id">
このように使用します:
<div v-for="item in items" v-bind:key="item.id">
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 track-by
を見つけます。
v-for
の値の範囲 変更
以前は、 v-for="number in 10"
がもつ number
は 0 ではじまり、9 で終わっていましたが、1 ではじまり、10 で終わるようになりました。
移行ガイド
あなたのコードから /\w+ in \d+/
の正規表現を探し出します。
そして、それが v-for
内で使われている場合、あなたが影響を受ける可能性があるかどうかを確認してください。
プロパティ
coerce
プロパティオプション 削除
もしあなたがプロパティに対して coerce
オプションを利用したい場合、その代わりとしてコンポーネント内の算出プロパティで算出された値で設定してください。例えば、以下の代わりに:
props: {
username: {
type: String,
coerce: function (value) {
return value
.toLowerCase()
.replace(/\s+/, '-')
}
}
}
このように使用します:
props: {
username: String,
},
computed: {
normalizedUsername: function () {
return this.username
.toLowerCase()
.replace(/\s+/, '-')
}
}
これには、いくつかの利点があります:
- プロパティの元の値にアクセスし続けることができます。
- 強制された値に別名をつけることによって、よりはっきりとプロパティで与えられた値とは違うことがわかるようになります。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 coerce
オプションを見つけます。
twoWay
プロパティオプション 削除
プロパティは今や、全て単方向となりました。
親スコープ内への副作用を生成するために、コンポーネントは暗黙のバインディングの代わりに、明示的にイベントを発生させる必要があります。
より詳細な情報については、以下を参照します:
- カスタムイベント
- カスタム入力コンポーネント (コンポーネントイベントを使用)
- 状態管理
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 twoWay
オプションを見つけます。
v-bind
への .once
と .sync
修飾子 削除
プロパティは今や、全て単方向となりました。
親スコープ内への副作用を生成するために、コンポーネントは暗黙のバインディングの代わりに、明示的にイベントを発生させる必要があります。
より詳細な情報については、以下を参照します:
- カスタムイベント
- カスタム入力コンポーネント (コンポーネントイベントを使用)
- 状態管理
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 .once
と .sync
修飾子を見つけます。
プロパティの変更 非推奨
ローカルでのプロパティの変更は、今はアンチパターンとみなされます。例えば、 プロパティを宣言した後に、コンポーネントに対して this.myProp = 'someOtherValue'
設定することなどです。新しいレンダリングシステムによって、親コンポーネントを再描画するたびに、子コンポーネントのローカルな変更は上書きされます。
プロパティの変更のユースケースのほとんどの場合は、以下のオプションのいずれかで置き換えることができます:
- デフォルト値を設定したデータプロパティ
- 算出プロパティ
移行ガイド
アップグレード後に end-to-end のテストスイートや、それに準ずるアプリケーションを実行し、プロパティの変更に関するコンソールの警告を探します。
ルートインスタンス上でのプロパティ置き換え
ルートの Vue インスタンス(言い換えれば、 new Vue({ ... })
によって作成されたインスタンス)においては、 props
の代わりに propsData
を使用します。
移行ガイド
もしあれば、 end-to-end のテストを走らせます。 失敗したテストについては、ルートインスタンスに渡されたプロパティはもはや動かないということをあなたに警告します。
算出プロパティ
cache: false
非推奨
将来のメジャーバージョンの Vue では、算出プロパティのキャッシュ無効化が削除されます。キャッシュされていない算出プロパティを、同じ結果を持つメソッドに置き換えます。
例:
template: '<p>message: {{ timeMessage }}</p>',
computed: {
timeMessage: {
cache: false,
get: function () {
return Date.now() + this.message
}
}
}
または、コンポーネントメソッドで:
template: '<p>message: {{ getTimeMessage() }}</p>',
methods: {
getTimeMessage: function () {
return Date.now() + this.message
}
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 cache: false
オプションを見つけます。
組み込みディレクティブ
v-bind
においての 真/偽 変更
v-bind
を使用する時、偽となりうる値は null
, undefined
, そして false
のみとなります。これは、 0
や空の文字列は、真となりうる値として描画されることを意味します。例として、 v-bind:draggable="''"
は draggable="true"
として描画されます。
列挙された属性については、上記の偽となりうる値に加え、文字列の "false"
は、 attr="false"
として描画されます。
その他のディレクティブ(たとえば、 v-if
や v-show
)は、 JavaScript の一般的な真がまだ適用されます。
移行ガイド
もしあれば、 end-to-end のテストを走らせます。 失敗したテストについては、上記の変更によって影響を受ける可能性があり、その可能性があるアプリケーションの箇所を警告します。
コンポーネントにおける v-on
を用いたネイティブイベントの購読 変更
コンポーネントを使用している時、 v-on
は、そのコンポーネントに向けて発生したカスタムイベントのみを購読するようになりました。ルート要素上でネイティブの DOM イベントを購読したい時は、 .native
修飾子によって実現できます。以下がその例です:
<my-component v-on:click.native="doSomething"></my-component>
移行ガイド
もしあれば、 end-to-end のテストを走らせます。 失敗したテストについては、上記の変更によって影響を受ける可能性があり、その可能性があるアプリケーションの箇所を警告します。
v-model
の debounce
削除
デバウンスは、 Ajax リクエストやその他の高負荷な処理の実装頻度を制限するために使用されます。Vue の v-model
の debounce
属性パラメータは、非常に単純な用法を想定し、簡潔に作りましたが、それによって実際の状態の更新ではなく、自身をデバウンスする仕組みとなっています。これは、小さな違いではありますが、アプリケーションの規模が大きくなるに連れて、この手法には限界がきます。
例えば、このように、検索ボックスを設計する際にこれらの限界が明らかになります:
デバウンス属性を使用している場合、入力の状態に関するリアルタイムなアクセス権を失うため、「タイピング中」の状態を検出する方法がないと思います。
しかし、 Vue からデバウンス機能を切り離すことによって、将来的な開発での制限を取り除くことができます。
<!--
lodash もしくは他の専用のユーティリティライブラリのデバウンス機能を用いてデバウンスを行うことが最も良いでしょう。また、それを Vue ではあらゆる箇所で利用することが可能です。
そしてそれは、テンプレート内に限った話ではありません。
-->
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
<div id="debounce-search-demo">
<input v-model="searchQuery" placeholder="Type something">
<strong>{{ searchIndicator }}</strong>
</div>
new Vue({
el: '#debounce-search-demo',
data: {
searchQuery: '',
searchQueryIsDirty: false,
isCalculating: false
},
computed: {
searchIndicator: function () {
if (this.isCalculating) {
return '⟳ Fetching new results'
} else if (this.searchQueryIsDirty) {
return '... Typing'
} else {
return '✓ Done'
}
}
},
watch: {
searchQuery: function () {
this.searchQueryIsDirty = true
this.expensiveOperation()
}
},
methods: {
// これが、実際のデバウンスが書かれているところです。
expensiveOperation: _.debounce(function () {
this.isCalculating = true
setTimeout(function () {
this.isCalculating = false
this.searchQueryIsDirty = false
}.bind(this), 1000)
}, 500)
}
})
この方法のもう1つの利点として、デバウンスが完全なるラッパー関数でないことが挙げられます。例えば、検索候補の為の API を叩く時、ユーザーが入力の手を止めてから候補を提供することは、理想的な体験とは言えません。その代わりに欲しいのは、スロットリング関数になるでしょう。現状、既にあなたが lodash のようなユーティリティライブラリを利用している場合、 throttle
関数を使用する形に置き換えます。これは、数分もあれば終わることです。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 debounce
属性を見つけます。
v-model
への lazy
や number
属性 置き換え
lazy
と number
の属性値は修飾子となりました。それは、以下のように置き換えることを意味します:
<input v-model="name" lazy>
<input v-model="age" type="number" number>
このように置き換えます:
<input v-model.lazy="name">
<input v-model.number="age" type="number">
移行ガイド
あなたのコード上で移行ヘルパーを実行し、これらの非推奨の属性を見つけます。
v-model
においてのインライン value
削除
v-model
はもはや、 インラインの value
属性を尊重しません。予測可能性のため、それは代わりに、常に Vue インスタンスをデータをソースとして扱います。
これは、以下のような要素を意味します:
<input v-model="text" value="foo">
このようなデータに裏付けられる場合:
data: {
text: 'bar'
}
“foo” の代わりに “bar” が描画されます。これは、既に内容を持つ場合の <textarea>
においても同じことが言えます。以下の場合:
<textarea v-model="text">
hello world
</textarea>
text
の初期値が “hello world” となることが確認できます。
移行ガイド
アップグレード後に end-to-end のテストスイートや、それに準ずるアプリケーションを実行し、 v-model
においてのインライン value 属性に対してのコンソールの警告を探します。
v-model
への v-for
プリミティブ値の反復 削除
このようなケースは、もはや動作しません:
<input v-for="str in strings" v-model="str">
その理由は、以下の <input>
にコンパイルされる JavaScript と同等の処理をおこなっているためです:
strings.map(function (str) {
return createElement('input', ...)
})
これを見てわかるように、 v-model
による双方向バインディングは、ここでは意味がありません。それは、関数内のローカルスコープのみの変数なので、イテレータにて str
に別の値を設定した場合にも何もしません。
代わりに、 v-model
が、オブジェクトのフィールドを更新できるようにするためには、 オブジェクト の配列を使用する必要があります。例えば以下となります:
<input v-for="obj in objects" v-model="obj.str">
移行ガイド
もしあれば、テストスイートを走らせます。 失敗したテストについては、ルートインスタンスに渡されたプロパティはもはや動かないということをあなたに警告します。
v-bind:style
においての オブジェクトおよび !important
構文 削除
もはや、これは動かなくなります:
<p v-bind:style="{ color: myColor + ' !important' }">hello</p>
もしあなたが本当に !important
をオーバーライドする必要がある場合、文字列の構文として使用します:
<p v-bind:style="'color: ' + myColor + ' !important'">hello</p>
移行ガイド
あなたのコード上で移行ヘルパーを実行し、オブジェクトへのスタイルのバインディングにおいての !important
を見つけます。
v-el
と v-ref
置き換え
わかりやすくするために、 v-el
と v-ref
は コンポーネントのインスタンスよりアクセス可能な $refs
として、 ref
属性に統合されました。これは、 v-el:my-element
は ref="myElement"
となり、 v-ref:my-component
もまた ref="myComponent"
となることを意味します。通常の要素で使用する場合、 ref
は DOM 要素となり、コンポーネント内で使用する場合、 ref
はコンポーネントのインスタンスになります。
v-ref
は、もはやディレクティブではありません。しかし、特別な値で、動的な定義が可能となっています。これは、 v-for
との組み合わせで使用する場合に、特に役にたちます。例えば、以下のような場合:
<p v-for="item in items" v-bind:ref="'item' + item.id"></p>
以前は、 v-el
や v-ref
と組み合わせた v-for
の各項目に対して、一意な名前をつけること方法はなかったため、要素やコンポーネントの配列を生成していたと思います。各項目に同じ参照が与えられることによって、現在でもその動作を実現することが可能です。
<p v-for="item in items" ref="items"></p>
1.x とは異なり、これらの $refs
は、それら自身の描画に登録および更新をおこなっているため、リアクティブではありません。それらを重複して反応させる際は、変更があるたびに描画します。
一方で、 $refs
は JavaScript によるプログラム的なアクセスとして主に利用するために設計されているため、テンプレートでそれらに依存することは推奨しません。それは、インスタンス自体に属していない状態を指すこととなるので、 Vue のデータ駆動な ViewModel の設計に違反することとなります。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 v-el
and v-ref
を見つけます。
v-else
への v-show
削除
v-else
はもはや、 v-show
では動作しません。代わりに、 v-if
の否定式を使用してください。例えば、このような場合代わりに:
<p v-if="foo">Foo</p>
<p v-else v-show="bar">Not foo, but bar</p>
このように使用します:
<p v-if="foo">Foo</p>
<p v-if="!foo && bar">Not foo, but bar</p>
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 v-else
への v-show
を見つけます。
カスタムディレクティブ 単純化
ディレクティブはその責任範囲を大幅に削減しました: ディレクティブは、今やローレベルの直接な DOM 操作を適用するためにのみ使用されます。ほとんどの場合、メインのコード再利用可能にし、抽象化したコンポーネントを使用するべきです。
顕著な違いとして、以下のようなものがあります:
- ディレクティブはもはや、インスタンスを持ちません。これは、もはや
this
内部にディレクティブのフックがないことを意味します。その代わり、それらは引数として必要なものを全て受け取ります。もし、あなたが本当にフック間で状態を保持する必要がある場合、el
上にて行うことができます。 acceptStatement
,deep
,priority
などのようなオプションは全て非推奨となりました。- 一部のフックが異なる振るまいをおこなっており、また、新たなフックと対になっているものもあります。
twoWay
なディレクティブを置き換えるためには、この example を参照してください。
新しいディレクティブははるかにシンプルなので、幸いにも、より簡単に習得することができます。より多くを学ぶには、新しい カスタムディレクティブガイド をお読みください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 定義済みのディレクティブを見つけます。 ヘルパーによって検出された箇所は、ほとんどの場合、将来的にコンポーネントにリファクタリングしたくなる部分となります。
.literal
ディレクティブの修飾子 削除
.literal
修飾子は、値として文字列リテラルを提供することによって、同じ事が容易に達成できるため、削除されました。
例えば、以下のように更新できます:
<p v-my-directive.literal="foo bar baz"></p>
これは、以下のようにできます:
<p v-my-directive="'foo bar baz'"></p>
移行ガイド
あなたのコード上で移行ヘルパーを実行し、ディレクティブの`.literal`
修飾子を見つけます。
トランジション
transition
属性 置き換え
Vue のトランジション機構は大幅な変更を遂げました。transition
属性ではなく、 <transition>
および <transition-group>
ラッパー要素を使用します。より多くを学ぶためには、新しいトランジションガイドを読むことをおすすめします。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 transition
属性を見つけます。
再利用可能なトランジションへの Vue.transition
置き換え
新しいトランジション機構の 再利用可能なトランジションへのコンポーネントの使用 によって実現することができます。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.transition
を見つけます。
stagger
トランジション属性
もしあなたがリストのトランジションを遅延させたい場合、その要素の設定やデータのインデックス(もしくは同様の属性)にアクセスすることによって、そのタイミングを制御することができます。詳しくは、こちらにあるサンプルを参照してください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 transition
属性を見つけます。
アップデートの間に、(これはダジャレですが、)新たなかつスタガリングな遷移手法へ置き換えることが可能です。
イベント
events
オプション削除
events
オプションは非推奨になりました。代わりに、イベントハンドラは created
フックで登録すべきです。詳細な example 向けとして$dispatch
と $broadcast
のマイグレーションガイド を確認してください。
Vue.directive('on').keyCodes
置き換え
keyCodes
を設定するための、より新しくかつ簡潔な方法は、Vue.config.keyCodes
を介して行うことです。例えば、以下のようなものとなります:
// v-on:keyup.f1 を有効化します。
Vue.config.keyCodes.f1 = 112
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 古い keyCode
の設定が用いられた属性見つけます。
$dispatch
および $broadcast
置き換え
$dispatch
および $broadcast
については、 Vuex などような、よりはっきりとしたコンポーネント間の通信及び状態管理のソリューションを支持するかたちで廃止となりました。
これまでの問題として、コンポーネントツリーが肥大化した際、その動作を推論することが非常に困難となり、また、コンポーネントのツリー構造に依存する、非常に脆いイベントフローがありました。それは、単純にうまくスケールしませんし、後々に痛みを伴う変更となってはなりません。$dispatch
および $broadcast
に関しても、兄弟コンポーネント間の通信を解決するものではありません。
これらの方法の最も一般的な用途の 1 つは、親とその直接の子供との間の通信です。このような場合、実際に v-on
で子から $emit
によって購読できます。これにより、明示的に追加されたイベントの利便性を保つことができます。
しかしながら、遠い子孫/祖先の間で通信するとき、$emit
はあなたを助けないでしょう。代わりに、最も簡単なアップグレードは、集中型のイベントハブを使用することです。これはコンポーネントツリー内のどこにあっても(兄弟間だとしても)、コンポーネント間で通信できるという利点があります。Vue インスタンスは event emitter インタフェースを実装しているため、実際にはこの目的で空の Vue インスタンス ($mount
で DOM にマウントしない状態のこと)を使用できます。
例えば、このような ToDo アプリケーションがある場合:
Todos
├─ NewTodoInput
└─ Todo
└─ DeleteTodoButton
これらを単一のイベントハブによって、コンポーネント間の通信を管理することができるようになりました:
// これは、あらゆる場合に使用されるイベントハブです。
// コンポーネントは、これを介して通信します。
var eventHub = new Vue()
そして、コンポーネントにて、それによって $emit
や $on
、 $off
を用いてイベントを発行させることや、新たに購読すること、そしてそれらを初期化することができます。
以下がそれぞれの例となります:
// NewTodoInput
// ...
methods: {
addTodo: function () {
eventHub.$emit('add-todo', { text: this.newTodoText })
this.newTodoText = ''
}
}
// DeleteTodoButton
// ...
methods: {
deleteTodo: function (id) {
eventHub.$emit('delete-todo', id)
}
}
// Todos
// ...
created: function () {
eventHub.$on('add-todo', this.addTodo)
eventHub.$on('delete-todo', this.deleteTodo)
},
// 以下は、コンポーネントの削除前に
// イベントリスナーをクリアするための良い手法です。
beforeDestroy: function () {
eventHub.$off('add-todo', this.addTodo)
eventHub.$off('delete-todo', this.deleteTodo)
},
methods: {
addTodo: function (newTodo) {
this.todos.push(newTodo)
},
deleteTodo: function (todoId) {
this.todos = this.todos.filter(function (todo) {
return todo.id !== todoId
})
}
}
単純なシナリオ上では、 $dispatch
および $boardcast
を代替品に置き換えるパターンで動かすことができますが、より複雑なケースを想定して、 Vuex のような専門的な状態管理層を設けることをおすすめします。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 $dispatch
and $broadcast
を見つけます。
フィルタ
フィルタ外でのテキスト展開 削除
フィルタは、今やテキスト内での補完({{ }}
タグ)のみで使用することができます。今までの v-model
や v-on
ディレクティブ上でのフィルタリングは、それ自体の利便性よりも、コードの複雑化につながることのほうが多いことに気がつきました。v-for
上でのリストのフィルタリングについては、それをコンポーネント上で再利用可能とするために、算出プロパティとして JavaScript 上のそのロジックを移動させるようにしても良いでしょう。
行いたい処理がプレーンな JavaScript で実現可能な場合は、基本的には同じ結果をもたらすフィルタのような特殊な構文を導入しないようにしたいです。この項で紹介する方法によって、 Vue の内蔵のディレクティブフィルタを置き換えることができます。具体的な方法は以下のとおりです:
debounce
フィルタの置き換え
このような記述の代わりに:
<input v-on:keyup="doStuff | debounce 500">
methods: {
doStuff: function () {
// ...
}
}
lodash の debounce
メソッド(または可能ならば throttle
)を直接メソッドに対して使用します。上記のような挙動を望む場合、以下のように書くことで達成できます:
<input v-on:keyup="doStuff">
methods: {
doStuff: _.debounce(function () {
// ...
}, 500)
}
この方法に対するより詳細な利点はここの v-model
による example を参照してください。
limitBy
フィルタの置き換え
このような記述の代わりに:
<p v-for="item in items | limitBy 10">{{ item }}</p>
JavaScript 組み込みの .slice
メソッドを算出プロパティへ使用します:
<p v-for="item in filteredItems">{{ item }}</p>
computed: {
filteredItems: function () {
return this.items.slice(0, 10)
}
}
filterBy
フィルタの置き換え
このような記述の代わりに:
<p v-for="user in users | filterBy searchQuery in 'name'">{{ user.name }}</p>
JavaScript 組み込みの .filter
メソッド を算出プロパティへ使用します:
<p v-for="user in filteredUsers">{{ user.name }}</p>
computed: {
filteredUsers: function () {
var self = this
return self.users.filter(function (user) {
return user.name.indexOf(self.searchQuery) !== -1
})
}
}
算出プロパティに対しては、完全なるアクセス権があるため、 JavaScript 組み込みの .filter
は、非常に複雑なフィルタリングの管理を行うことができます。例えば、もしあなたがすべてのアクティブユーザーを見つけるために、大文字小文字を区別せず、名前と E メールアドレスの両方を調べたい場合は、以下のようになります:
var self = this
self.users.filter(function (user) {
var searchRegex = new RegExp(self.searchQuery, 'i')
return user.isActive && (
searchRegex.test(user.name) ||
searchRegex.test(user.email)
)
})
orderBy
フィルタの置き換え
このような記述の代わりに:
<p v-for="user in users | orderBy 'name'">{{ user.name }}</p>
算出プロパティへ、lodash の orderBy
(もしくは sortBy
)を使用します。
<p v-for="user in orderedUsers">{{ user.name }}</p>
computed: {
orderedUsers: function () {
return _.orderBy(this.users, 'name')
}
}
複数のカラムを用いた並び替えも可能です:
_.orderBy(this.users, ['name', 'last_login'], ['asc', 'desc'])
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 ディレクティブ内部で使用されているフィルタを見つけます。 もし間違いがある場合、 consoleのエラーを参照してください。
フィルタ引数の構文 変更
JavaScript の関数を呼び出す際、引数のフィルタがより良い構文となります。例えば、スペースで区切る形には以下のように置き換えることができます。
<p>{{ date | formatDate 'YY-MM-DD' timeZone }}</p>
カッコで引数を囲んだ上で、カンマを用いて引数を区切ります:
<p>{{ date | formatDate('YY-MM-DD', timeZone) }}</p>
移行ガイド
あなたのコード上で移行ヘルパーを実行し、古いフィルタが用いられているコードを見つけます。 もし間違いがある場合、 consoleのエラーを参照してください。
組み込みテキストフィルタ 削除
テキストを展開するためのフィルタは、現状はまだ利用できますが、すべてのフィルタが削除されました。それらの代わりに、(例えば日付のフォーマットには date-fns
、通貨処理には accounting
と言った形で) より専門的なライブラリの使用を推奨します。
Vue に組み込まれたテキストフィルタ群は、それぞれ以下のように置き換えることができます。これらの例には、カスタムヘルパーや関数、メソッドの他、算出プロパティなどが含まれます。
json
フィルタの置き換え
Vue がうまい具合に文字列や数値、配列からオブジェクトまで、自動的にフォーマットした上で出力するようになったため、あなたがデバッグする必要はありません。
もし、あなたが JavaScript の JSON.stringify
と全く同じ機能が必要ならば、算出プロパティにて行うことが可能です。
capitalize
フィルタの置き換え
text[0].toUpperCase() + text.slice(1)
uppercase
フィルタの置き換え
text.toUpperCase()
lowercase
フィルタの置き換え
text.toLowerCase()
pluralize
フィルタの置き換え
npm 上にある pluralize パッケージによってこの目的を果たすことができますが、あなたがもし、特定の単語のみを複数形にしたい場合や、 0
のようなケースの場合に特別な出力を行いたい場合は、例えば、以下のように簡単に独自の複数形にする関数を定義することができます。:
function pluralizeKnife (count) {
if (count === 0) {
return 'no knives'
} else if (count === 1) {
return '1 knife'
} else {
return count + 'knives'
}
}
currency
フィルタの置き換え
非常に単純な実装例として、このような形で実現することができます:
'$' + price.toFixed(2)
しかしながら、ほとんどの場合、これらは奇妙な動作をする場合があります(例えば、 0.035.toFixed(2) の丸め誤差が 0.04 として評価されるにも関わらず、 0.045 の丸め誤差が 0.04と評価されるなどです)。これらの問題を解消するためには、より確実な 通貨のフォーマット管理のライブラリ などを使用します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、非推奨のフィルタを見つけます。 もし間違いがある場合、 consoleのエラーを参照してください。
Two-Way フィルタ 置き換え
あるユーザは、v-model
で two-way フィルタを使い、非常に小さなコードで面白い入力を作成するのを楽しんでいます。しかしながら、間違いなくシンプルですが、two-way フィルタは複雑さを大幅に隠すことができ、状態の更新を遅らせることで不十分な UX を奨励します。代わりに、カスタム入力を作成するための、より明示的で機能豊富な方法として、入力をラップするコンポーネントが推奨されます。
例として、two-way 通貨フィルタの移行について説明します:
ほとんどの場合うまく動作しますが、遅延状態の更新によって異常な動作が発生する可能性があります。例えば、それらの入力の 1 つに 9.999
を入力してみてください。入力のフォーカスを失うと、その値は $ 10.00
に更新されます。計算された合計を見ると、9.999
がデータに格納されていることがわかります。ユーザーに見える現実のバージョンは同期していません!
Vue 2.0 を使用してより堅牢なソリューションに移行するには、最初に新しい <currency-input>
コンポーネントでこのフィルタをラップしましょう:
これにより、フォーカスのある入力の内容を選択するなど、フィルタだけでカプセル化できなかった動作を追加できます。次のステップは、フィルタからビジネスロジックを抽出することです。以下では、すべてを外部currencyValidator
オブジェクト にします:
このようにモジュール性が向上すると、Vue 2.0 への移行が容易になるだけでなく、通貨の解析と書式設定も可能になります:
- Vue コードから単体でテストされたユニット
- API エンドポイントへのペイロードの検証など、アプリケーションの他の部分で使用される
このバリデータを抽出することで、より堅牢なソリューションとしてより快適に構築できました。状態の不具合は解消されており、ユーザーが間違った入力を実際に行うことは不可能です。これは、ブラウザのネイティブ番号の入力と同様です。
ただし、フィルタと Vue 1.0 の一般的な制限はありますので、Vue 2.0 へのアップグレードを完了しましょう:
次のことに気付くかもしれません:
- two-way フィルタの隠された動作の代わりに、ライフサイクルフックと DOM イベントを使用して、入力のあらゆる側面がより明示的になります。
- 私たちはカスタム入力に
v-model
を直接使うことができます。これは通常の入力と一貫性があるだけでなく、私たちのコンポーネントが Vuex に優しいことを意味します。 - 返される値を必要とするフィルタオプションを使用しなくなったため、実際には非同期で通貨作業を行うことができます。つまり、通貨を使用しなければならないアプリがたくさんある場合、このロジックを簡単に共有してマイクロサービスにすることができます。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、ディレクティブにおいて v-model
のように使用されているフィルタの example を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
スロット
重複したスロット 削除
もはや、同じテンプレート内に、同名のスロットを持つことはサポートされません。スロットが描画されるとき、そのスロットは「使い果たされ」、同じレンダリングツリーの中で再度描画することはできません。もし、複数の場所で同一の内容を描画する必要がある場合は、プロパティとしてそのコンテンツを渡します。
移行ガイド
アップグレード後に end-to-end のテストスイートや、それに準ずるアプリケーションを実行し、 v-model
においての重複スロットに対してのコンソールの警告を探します。
slot
属性のスタイリング 削除
名前付きスロットを経由して挿入されたコンテンツは、もはや slot
属性を保持しません。
スタイル属性を付与したい場合は、なんらかのラップした要素に適用するか、複雑なユースケースの場合は、 render
関数 を用いて、プログラムにてコンテンツを変更してください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 名前付き slot を対象としているCSSのセレクタ(例えば、 [slot="my-slot-name"]
など)を見つけます。
特別な属性
keep-alive
属性 置き換え
keep-alive
はもはや、特別な属性ではなく、 むしろ <transition>
と同様に、コンポーネントのラッパーです。例えば以下の場合:
<keep-alive>
<component v-bind:is="view"></component>
</keep-alive>
これによって、 <keep-alive>
を複数条件下において使用することができます:
<keep-alive>
<todo-list v-if="todos.length > 0"></todo-list>
<no-todos-gif v-else></no-todos-gif>
</keep-alive>
<keep-alive>
が複数の子要素を持っているとき、 <keep-alive>
は単一の子要素のみを評価します。
最初のひとつ目の要素以外は、単純に無視されます。
<transition>
とともに用いるときは、それらをネストさせてください:
<transition>
<keep-alive>
<component v-bind:is="view"></component>
</keep-alive>
</transition>
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 keep-alive
属性を見つけます。
展開
属性内での展開 削除
属性内での展開は、もはや有効ではありません。例えば、以下の場合:
<button class="btn btn-{{ size }}"></button>
いずれかのインライン式を使用するように更新する必要があります:
<button v-bind:class="'btn btn-' + size"></button>
もしくはデータ/算出プロパティを使用します:
<button v-bind:class="buttonClasses"></button>
computed: {
buttonClasses: function () {
return 'btn btn-' + size
}
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、属性内で使用されている展開を見つけます。
HTML の展開 削除
新たな v-html
ディレクティブ を支持することによって、 HTML の展開({{{ foo }}}
) は非推奨となりました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 HTML の展開が行われているコードを検索します。
ワンタイムバインディング 置き換え
新たな v-once
ディレクティブ を支持することによって、ワンタイムバインディング ({{* foo }}
) は非推奨となりました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、ワンタイムバインディングを見つけます。
リアクティブ
vm.$watch
変更
vm.$watch
を経由して作成されたウォッチャーは、関連するコンポーネントの描画の前に発火します。これは、不要な更新を避けることと、描画前にコンポーネントの状態を更新する機会を与えてくれます。例えば、コンポーネントのプロパティや、それらの値の変更をウォッチすることができます。
これまで、 vm.$watch
を利用することでコンポーネントのアップデート後に DOM に対して何らかの操作をしていた場合、それを updated
ライフサイクルフックに置き換えることができます。
移行ガイド
もしあれば、 end-to-end のテストを走らせます。 失敗したテストについては、ウォッチャーが古い動作であることを警告します。
vm.$set
変更
vm.$set
は非推奨となっており、 Vue.set
という名称になっています。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、非推奨の用法を見つけます。
vm.$delete
変更
vm.$delete
は非推奨となっており、 Vue.delete
という名称になっています。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、非推奨の用法を見つけます。
Array.prototype.$set
削除
代わりに、 Vue.set を使用します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、配列に対しての .$set
を見つけます。
そうすることで、メソッドが見つからないエラーがコンソールに出力されているので確認してください。
Array.prototype.$remove
削除
例えば、代わりに Array.prototype.splice
を使用します:
methods: {
removeTodo: function (todo) {
var index = this.todos.indexOf(todo)
this.todos.splice(index, 1)
}
}
いっそのこと、削除メソッドに index を渡す方法も良いでしょう:
methods: {
removeTodo: function (index) {
this.todos.splice(index, 1)
}
}
移行ガイド
あなたのコード上で移行ヘルパーを実行し、配列に対しての .$remove
を見つけます。
そうすることで、メソッドが見つからないエラーがコンソールに出力されているので確認してください。
Vue インスタンス上での Vue.set
および Vue.delete
削除
Vue.set および Vue.delete はもはや、 Vue インスタンス上で動作することはできません。データオプション内で、全てのトップレベルのリアクティブなプロパティが必須となりました。もし、 Vue のインスタンス上で $data
を削除したい場合、単に null を代入します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue インスタンス上で使われている Vue.set
もしくは Vue.delete
を見つけます。
もし間違いがある場合、 consoleの警告を参照してください。
vm.$data
の置き換え 削除
現在では、コンポーネントのインスタンスのルートにある $data
を書き換えることは禁止されています。これは、リアクティブなシステムの上での極端なケースを防ぎ、(特に型チェックシステム上での)コンポーネントの状態をより予測しやすくします。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$data
が上書きされている箇所を見つけます。
もし間違いがある場合、 consoleの警告を参照してください。
vm.$get
削除
リアクティブなデータを直接取得します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$get
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
DOM を中心としたインスタンスメソッド
vm.$appendTo
削除
ネイティブの DOM API を使用します:
myElement.appendChild(vm.$el)
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$appendTo
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
vm.$before
削除
ネイティブの DOM API を使用します:
myElement.parentNode.insertBefore(vm.$el, myElement)
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$before
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
vm.$after
削除
ネイティブの DOM API を使用します:
myElement.parentNode.insertBefore(vm.$el, myElement.nextSibling)
もし myElement
が最後の要素の場合は、以下のように対処します:
myElement.parentNode.appendChild(vm.$el)
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$after
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
vm.$remove
削除
ネイティブの DOM API を使用します:
vm.$el.remove()
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$remove
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
メタインスタンスメソッド
vm.$eval
削除
この機能が実際に使用されることはありません。もしあなたがこの機能を利用する機会があり、それを回避する方法が思いつかない場合は、フォーラムにてアイデアを募ってください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$eval
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
vm.$interpolate
削除
この機能が実際に使用されることはありません。
もしあなたがこの機能を利用する機会があり、それを回避する方法が思いつかない場合は、フォーラムにてアイデアを募ってください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$interpolate
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
vm.$log
削除
最適なデバッグのために、 Vue Devtools を利用してください。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 vm.$log
を見つけます。
もし間違いがある場合、 consoleのエラーを参照してください。
インスタンス DOM オプション
replace: false
削除
コンポーネントは常に要素に紐付いて置き換えられます。 replace:false
の挙動を再現するには、コンポーネントのルートを置き換えたい要素で囲みます。例えば、このような場合は:
new Vue({
el: '#app',
template: '<div id="app"> ... </div>'
})
もしくは render 関数で行います:
new Vue({
el: '#app',
render: function (h) {
h('div', {
attrs: {
id: 'app',
}
}, /* ... */)
}
})
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 replace: false
を見つけます。
グローバル設定
Vue.config.debug
削除
警告に対して、必要に応じてデフォルトでスタックトレースが付随しています。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.config.debug
を見つけます。
Vue.config.async
削除
非同期処理は現在では、描画性能のために必要とされます。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.config.async
を見つけます。
Vue.config.delimiters
置き換え
コンポーネントレベルのオプション として作り直されました。これは、サードパーティのコンポーネントを壊すことなく、アプリケーション内で代替のデリミタを使用することができます。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.config.delimiters
を見つけます。
Vue.config.unsafeDelimiters
削除
v-html
を支持すること によって、 HTML の展開は非推奨となりました。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.config.delimiters
を見つけます。
その後、ヘルパーは v-html
に置き換えることができる HTML の展開が行われているコードを検索します。
グローバル API
Vue.extend
への el
削除
el オプションは、もはや Vue.extend
で使用することはできません。これは、インスタンスの作成オプションとしてのみ有効です。
移行ガイド
アップグレード後に end-to-end のテストスイートやアプリケーションを実行し、 Vue.extend
への el
に関するコンソールの警告を探します。
Vue.elementDirective
削除
代わりに components を使用します。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.elementDirective
を見つけます。
Vue.partial
削除
パーシャルは、プロパティを使用して、コンポーネント間のより明示的なデータフローを優先するため非推奨になりました。性能が重要な領域で部分的なものを使用している場合を除いて、単に通常のコンポーネントを代わりに使用することを推奨します。部分的に name
を動的に束縛する場合は、動的コンポーネントを使用できます。
アプリケーションの性能に重大な影響を及ぼす部分でパーシャルを使用する場合は、関数型コンポーネントにアップグレードする必要があります。それらはプレーンな JS / JSX ファイル (.vue
ファイルではなく)になければならず、パーシャルと同様に、ステートレスでインスタンスレスです。これにより描画が非常に高速になります。
パーシャル的なに関数型コンポーネントのメリットは、JavaScript のフルパワーにアクセスできるようになるため、より動的なものにできることです。しかし、この力にはコストがかかります。以前に描画関数を使ったコンポーネントフレームワークを使ったことがない人は、学習に少し時間がかかるかもしれません。
移行ガイド
あなたのコード上で移行ヘルパーを実行し、 Vue.partial
を見つけます。