Help us understand the problem. What is going on with this article?

Vue.js 2.0のFeaturesを訳してみる

More than 3 years have passed since last update.

Vue.js 2.0 がリリース

 prismrismと申します。唐突な初投稿は Vue.js についてです。
 この1年半ほど Vue.js 1.x と遊び続けていたのですが、先日 Vue.js 2.0 がリリースされました。まだ α 版なので確定していないことも多いようですが、2.0にはまだリファレンスに相当するものが無いので自己満足のために「新機能の情報が知りたいけど英語読みたくない…」という方々の助力となるべくMarkdown記法の練習も兼ねて和訳を書いてみようと思い至りました。

 2.0 でどのような変更があったのかは公式 Github ページの issues に記載されています。今回は一番情報がまとまっている Features の投稿を訳していきたいと思います。ちょうど 6/13 に alpha.2のリリースに併せて編集した旨が書いているのでホットな情報ですね。この記事投稿して数時間後にあっさりalpha.3が出てますね…。相変わらずの開発速度に脱帽です。

 逐語訳で日本語が崩壊してしまうのが好きじゃないのでところどころ意訳していますが、生まれてこの方まるっと日本人なので英語が得意なわけでもないですし、プログラマーとしてはひよっこなので用語を適切に使用している自信もありません。
 Qiitaの作法も存じ上げていないのですが、なにかあればツッコミを頂ければと思います。
 正直なに書いてるかわからないところがチラホラ


 ※この翻訳の初版は 2016/06/15 に作成されました。
 ※投稿して6時間くらいにalpha.3が出てしまったので、今後は気付いたら随時更新します。


 以下、翻訳


これは随時更新される文書です。最終更新日: 2016/08/17 最新版 2.0.0-rc.2

注意事項

  • チェックが付された項目はver 2.0 の開発ブランチに実装されていることを表します
  • 開発中は Features のトップ( subject )を随時更新します
  • 破壊的な変更のリストアップについて、開発中はその決定を保証するものではありません
  • 更新に関するヒントが末尾にあります

主要な変更点

  • テンプレートの構文解析が DOM に依存しなくなりました(テンプレートとして実体 DOM を使用していない場合)。文字列型のテンプレート(<script type="text/xtemplate>タグ、埋め込まれたJavaScript文字列、あるいは単一ファイルのコンポーネントを通じてコンパイルされたテンプレート)を使用している限り、1.x のテンプレートの構文解析における制約を受けることはありません。しかしながら、(el オプションを用いて)現存しているコンテンツをテンプレートとして要素にマウントしている場合、引き続きこれらの制約に従わなければなりません。

  • コンパイラ(テンプレートとなる文字列をレンダー関数に置換する部分)とランタイムは分轄が可能となりました。2つの異なるビルドが提供されます。

    • 独立ビルド:コンパイラ及びランタイムの両方を含みます。これらは基本的には Vue 1.x とほぼ同様に機能します。
    • ランタイム単体ビルド:こちらはコンパイラを含まないため、コンパイル時にプリコンパイルされたテンプレートか自作のレンダー関数が必要です。npm から Vue を扱っている場合、vueifyvue-loaderがテンプレートのプリコンパイルを行うような(Browserify か Webpack による)コンパイル手順を踏んでいるはずなので、npm パッケージはこちらのビルドをデフォルトで出力するようになっています。

グローバル設定

  • Vue.config.silent
  • Vue.config.optionMergeStrategies
  • Vue.config.devtools
  • Vue.config.errorHandler 新規 : コンポーネントのレンダーとウォッチャの間で補足できなかったエラーを扱うグローバルフックです( デフォルトではエラースタックを記録します 所定の場所でスローします)
  • Vue.config.keyCodes 新規 : v-on でのキー入力に対応するカスタムエイリアスを設定します
  • Vue.config.debug 非推奨 : デフォルトで スタックトレースに警告を表示するため実用性を失いました
  • Vue.config.async 非推奨 : レンダリング処理には非同期であることが必須です
  • Vue.config.delimiters コンポーネントのオプションとして作り直されました
  • Vue.config.unsafeDelimiters 非推奨 : v-html を使用してください

グローバル API

  • Vue.extend
  • Vue.nextTick
  • Vue.set
  • Vue.delete
  • Vue.directive
  • Vue.component
  • Vue.use
  • Vue.mixin
  • Vue.compile 新規 (独立ビルドのみ)
  • Vue.transition
    • stagger 非推奨 : 代わりに elへdata-index属性値を設定し、アクセスしてください
  • Vue.filter
  • Vue.elementDirective 非推奨 : コンポーネントを使用してください
  • Vue.partial 非推奨 : 関数コンポーネント(functional components)を使用してください

オプション

data

  • data
  • props
    • prop validation
    • default value
    • coerce 非推奨 : Propを変換したい場合、それを用いたローカルの算出プロパティを作成してください
    • prop binding modes 非推奨(コンポーネントに対してv-modelが使用できます)
  • propsData 新規:インスタンス作成時のみ
  • computed
  • methods
  • watch

DOM

  • el
  • template
  • render 新規
  • replace 非推奨 : コンポーネントはただ1つのルート要素が必須となりました

ライフサイクルフック

  • init beforeCreate
  • created
  • beforeDestroy
  • destroyed
  • beforeMound 新規
  • mounted 新規
  • beforeUpdate 新規
  • updated 新規
  • activated 新規( keep-alive 用)
  • deactivated 新規( keep-alive 用)
  • ready 非推奨 : mounted を使用してください(document内での存在を保証できません)
  • activate 非推奨 : vue-router へ移行されました
  • beforeCompile 非推奨 : created を使用してください
  • compiled 非推奨 : mounted を使用してください
  • attached 非推奨 : 他のフックに DOM 内部での存在チェックを自作してください
  • detached 非推奨 : 同上

アセット

  • directives
  • components
  • transitions
  • filters
  • partials 非推奨
  • elementDirectives 非推奨

その他

  • parent
  • mixins
  • name
  • extends
  • delimiters 新規 : 元のグローバル設定から置換されました。独立ビルドでのみ有効です
  • functional 新規 : コンポーネントをステートレスおよびインスタンスレスにします(仮想ノードを返すだけの単なるレンダー関数です)
  • events 非推奨 : イベント伝播が起こらなくなりました

インスタンスプロパティ

  • vm.$data
  • vm.$el
  • vm.$options
  • vm.$parent
  • vm.$root
  • vm.$children
  • vm.$refs
  • vm.$els 非推奨 : $refs に統合されました

インスタンスメソッド

data

  • vm.$watch
  • vm.$get 非推奨 : 値を直接取得してください
  • vm.$set 非推奨 : Vue.set を使用してください
  • vm.$delete 非推奨 : Vue.delete を使用してください
  • vm.$eval 非推奨 : 実用性がありません
  • vm.$interpolate 非推奨 : 実用性がありません
  • vm.$log 非推奨 : デベロッパーツールを使用してください

events

  • vm.$on
  • vm.$once
  • vm.$off
  • vm.$emit
  • vm.$dispatch 非推奨 : グローバルなイベントバスか Vuex を使用してください(後述)
  • vm.$broadcast 非推奨 : 同上

DOM

  • vm.$nextTick
  • vm.$appendTo 非推奨 : vm.$elからDOM API を直接使用してください
  • vm.$before 非推奨
  • vm.$after 非推奨
  • vm.$remove 非推奨

ライフサイクル

  • vm.$mount
  • vm.$destroy

ディレクティブ

  • v-text
  • v-html {{{}}}による省略記法は非推奨となりました
  • v-if
  • v-show
  • v-else
  • v-for
    • key ( track-by から変更)
    • オブジェクトによる v-for
    • 範囲による v-for
    • 引数の順序を変更: (value, index) in arr, (value, key, index) in obj
    • \$index と \$key 非推奨
  • v-on
    • 修飾子の利用
    • 子コンポーネントでの使用
    • カスタムキーコード(Vue.directive('on').keyCodesではなく Vue.config.keyCodesで設定します)
  • v-bind
    • prop での使用
    • xlink
    • オブジェクトのバインド
  • v-bind:style
    • ベンダープレフィックスの検出 (prefix sniffing)
  • v-bind:class
  • v-model
    • lazy (修飾子)
    • number (修飾子)
    • コンポーネント構造におけるイベント(compositon events)を無視
    • debounce 非推奨 : v-on:input とサードパーティ製のデバウンス関数を使用してください
  • v-cloak
  • v-pre
  • v-once 新規
  • v-ref 特別な属性値refとして使用してください
  • v-el 非推奨 ( ref に統合されました)

特別な要素

  • <component>
    • :is
    • 非同期コンポーネント
    • インラインテンプレート
  • <transition>
  • <transition-group>
  • <keep-alive>
  • <slot>
  • partial 非推奨

特別な属性値

  • key
  • ref
  • slot

サーバーサイドレンダリング

  • renderToString
  • renderToStream
  • クライアント側での配列変換 ( client-side hydration )

その他の破壊的な変更点

v-for 反復構文の変更

  • $index$key の非推奨化
     名前付きのインデックスとキーをより明確にするのが良いため、この両方が非推奨となりました。この構文は入れ子になったループ内では少々把握が難しいものであり、制約があります。おまけとして、初心者が学習する構文が2つ少なくて済みます。

  • 新たな配列構文

    • value in arr
    • (value, index) in arr (JavaScriptの forEachmap を用いて引数の順番をより一貫したものに切り替えます)
  • 新たなオブジェクト構文

    • value in obj
    • (value, key) in obj ( lodash のような多くの一般的なオブジェクトイテレータにより、引数の順番をある程度一貫性を持たせたものへ切り替えます)
    • (value, key, index) in obj (表のストライプ表示のような外観上の目的として、オブジェクトの反復にインデックスが使用できるようになりました)

ディレクティブインターフェイスの変更

 概して、2.0ではディレクティブの責任範囲が大きく削減されています。ディレクティブは低レベルで直接的なDOM操作に対して使用されるようになりました。多くの場合、コードを再利用するための抽象化にはコンポーネントを使用する方が適切です。

 ディレクティブはインスタンスを持たなくなりました。これは即ち、ディレクティブのフック内でのthisがこれまでのように機能しなくなり、bindupdateunbindがあらゆるものを引数として受け取るようになったことを意味します。( binding オブジェクトはイミュータブルであることに注意してください。どうしても必要なのであれば el によってディレクティブの状態を維持することができます。)

<div v-example:arg.modifier="a.b"></div>
// ディレクティブの例
export default {
  bind (el, binding, vnode) {
    // binding オブジェクトはvalue, oldValue, arg および modifiers を吐き出します。
    binding.expression // "a.b"
    binding.arg // "arg"
    binding.modifiers // { modifier: true }
    // コンテキストとなる Vue インスタンスへは vnode.context からアクセスすることができます。
  },

  // update は少し変更があります。以下をご覧ください。
  update (el, binding, vnode, oldVnode) { ... },


  // componentUpdated は全体のコンポーネントが現在の更新サイクルを完了した"後"で呼び出される新たなフックです。
  // 即ち、このフックを呼び出された時点で全てのDOMは最新の状態であることを意味します。
  // また、このフックはディレクティブの値が変更されたか否かに関わらず必ず呼び出されます。
  componentUpdated (el, binding, vnode, oldVNode) { ... },

  unbind (el, binding, vnode) { ... }
}

 値を考慮するだけの場合は分割代入が使用できます。

export default {
  bind (el, { value }) {
    // ...
  }
}

さらに、updateフックに少し変更が加わりました。

  1. bindの後に自動で呼び出されなくなりました。
  2. バインドされている値が変更されたかに関わらずコンポーネントが再レンダリングされた時必ず呼び出されるようになりました。不必要な更新をスキップするためにbinding.value === binding.oldValueの比較を利用することが出来ますが、常に更新を適用したい場合もあります。例えば置換( replace )ではなく変更( mutation )が行われた Object がディレクティブにバインドされている場合です。

 elementDirective とディレクティブのパラメータは非推奨となりました。

フィルターの用法と構文の変更

 Vue 2.0ではフィルターシステムがいくつか変更されています。

  1. フィルターはテキスト展開({{}}タグ)の内部でのみ使用可能となりました。以前、v-modelv-onなどのディレクティブへフィルターが使用されていると、便利ではなくむしろ複雑になってしまうことに気付きました。また、v-forにおけるリストのフィルタリングでは算出プロパティとしてJavaScriptへ処理を移行するのがより適切です。
  2. Vue 2.0 は内蔵フィルタを一切持ちません。特定領域の問題解決を目的とした、独立ライブラリーの使用を推奨します。例えば書式を日付型に変換する moment.js や通貨型に変換する accounting.js などです。自作のフィルターパックを作成してコミュニティで共有することも歓迎します!
  3. フィルター構文は、スペース区切りの引数によるものから、JavaScriptの関数実行に近いものに変更されました。

    {{ date | formatDate('YY-MM-DD') }}
    

トランジションシステム

トランジションのCSSクラスを変更

常に適用されていたv-transitionクラスは追加されなくなり、また Vue では Angular や ReactのCSSTransitionGroup と同じクラス名を使用することになりました。

  • v-enter:要素が挿入される前に適用され、1チック後に除去されます。(enter の開始時)

  • v-enter-active:要素が挿入される前に適用され、トランジションまたはアニメーションが終了した時に削除されます。(enter の実行中および終了時)

  • v-leave:leave トランジションが発火したのと同時に適用され、1チック後に除去されます。(leave の開始時)

  • v-leave-active:leaveトランジションが発火したのと同時に適用され、トランジションまたはアニメーションが終了した時に除去されます。(leave の実行中および終了時)

    v-enter-activev-leave-activeは enter/leave でそれぞれ異なるイージングカーブの設定を可能にします。ほとんどの場合更新は単に今あるv-leavev-leave-activeとの入れ替えを意味します。( CSS アニメーションではv-enter-activev-leave-activeを使用してください)

v-enter-activev-leave-activeがあれば enter / leave トランジションに異なるイージングカーブを明示できるようになります。更新するには、大抵は現在使用しているv-leavev-leave-activeに書き換えるだけです。

トランジション API の変更

  • <transition>コンポーネント
     全ての単一要素へ適用するトランジション効果は、対象となる要素およびコンポーネントを組み込みのコンポーネントである<transition>でラップすることによって適用します。これは抽象コンポーネントであり、追加のDOM要素をレンダリングすることもなければ検出されたコンポーネント階層の中に現れることもないことを意味します。単にラップした内側にある要素のトランジションにおける振る舞いを適用するだけです。
     簡単な用例:

    <transition>
      <div v-if="ok">toggled content</div>
    </transition>
    

    コンポーネントは以前のトランジションオプション定義に直接対応する、いくつかの props と events を定義します。

    Props

    • name: String
       CSS クラス名を自動出力する際に使用します。例えばname: 'fade'とすると.fade-enterfade-enter-activeなどに自動で拡張されます。デフォルトは"v"です。
    • appear: Boolean
       初期レンダーにトランジションを適用するかを設定します。デフォルトはfalseです。
    • css: Boolean
       CSS トランジションクラスを適用するかを設定します。デフォルトはtrueです。falseに設定した場合、コンポーネントイベント経由で登録された JavaScript フックのみが発火されます。
    • type: String
       トランジションの終了タイミングを決定するために、トランジションイベントのタイプを特定します。使用可能な値は"transition""animation"です。デフォルトでは継続時間がより長い方のタイプを自動で検出します。
    • mode: String
       leaving/entering トランジションのシーケンスタイミングを操作します。使用可能な値は"out-in""in-out"です。デフォルトは同時に起こります。
    • enterClass, leaveClass, enterActiveClass, leaveActiveClass, appearClass, appearActiveClass: String
       個別にトランジション CSS クラス名を指定できます。

    動的コンポーネントにトランジションを適用した例です。

    <transition name="fade" mode="out-in" appear>
      <component :is="view"></component>
    </transition>
    

    Events

    1.x API で使用可能であった JavaScript フックと対応しています。
    - before-enter
    - enter
    - after-enter
    - before-leave
    - leave
    - after-leave
    - before-appear
    - appear
    - after-apper

    例:

    <transition @after-enter="transitionComplete">
      <div v-show="ok">toggled content</div>
    <transition>
    

    entering トランジションが完了した時、トランジションした DOM 要素を引数としてコンポーネントのtransitionCompleteメソッドが呼び出されます。

    注意

    • leave-cancelledは挿入や削除に使用できなくなりました。一度 leave トランジションが開始するとキャンセルできません。しかしながら、v-showでのトランジションにおいては引き続き有効です。
    • 1.0 のように、enterleaveフックにおいて、第二引数のcb存在は、ユーザーがトランジションの終了タイミングを明示的に操作可能なことを示しています。


  • <transition-group>コンポーネント
     全ての複数要素に対するトランジション効果は、要素を組み込みコンポーネントの<transition-group>でラップすることによって適用します。<transition>が提供するものと同じ props と events を提供しますが、違いは以下の通りです。

    1. <transition>とは異なり、<transition-group>は実体DOMをレンダリングします。デフォルトでは 単一の<span>ですが、<tag>プロパティでどの要素をレンダリングするか設定できます。また、<ul is="transition-group">のようにis属性値も使用可能です。
    2. <transition-group>modeプロパティをサポートしません。
    3. <transition-group>の内部にある全ての子はユニークな key を持たなければなりません。

    例:

    <transition-group tag="ul" name="slide">
      <li v-for="item in items" :key="item.id">
        {{ item.text }}
      </li>
    </transition>
    

移動トランジション

 <transition-group>は CSS の transform によって移動トランジションをサポートします。更新後に子のスクリーン上での位置が変更されている場合、移動 CSS クラス ( nameプロパティから自動生成されたものか、moveClassプロパティで指定したもの) が適用されます。移動 CSS クラスが適用された時に CSS のtransformプロパティが "トランジション可能"であるならば、要素は FLIP technique を用いて目標の位置へと滑らかにアニメーション動作を行います。

 実際の動作例を確認してみてください。



- 再利用可能なトランジションの作成
 トランジションはコンポーネントを通じて適用されるようになり、アセットタイプと見なされなくなったため、グローバルのVue.transiton()メソッドとtransitionオプションの両方が非推奨となりました。コンポーネントの props と events をインラインで書き込むことでトランジションの設定が可能です。しかし再利用性のあるトランジション効果を作るには、特にカスタム JavaScript フックを用いたものである場合に、一体どのようにすればよいのでしょう。その答えは、自身でトランジションコンポーネントを作成することです( とりわけ関数コンポーネントが適しています )。

Vue.component('fade', {
  functionl: true,
  render (createElement, { children }) {
    const data = {
          props: {
        name: 'fade'
      },
      on: {
        beforeEnter () { /* ... */ }, // 注意: フックは JavaScript ではキャメルケースを用いて下さい( 1.x 系と同様 )。
        afterEnter () { /* ... */ }
      }
    }
    return createElement('transition', data, children)
  }
})

 そうするとこのように再利用ができるようになります。

<fade>
  <div v-if="ok"> toggled content</div>
</fade>

v-model の変更

  • lazynumberパラメータは修飾子になりました。

    <input v-model.lazy="text">
    
  • .trimの追加 - その名の通り、入力値を切り取ります。

  • debaounce パラメータは非推奨となりました。(後述の更新に関するヒントを参照してください)

  • v-modelvalue属性による初期値を無視するようになりました。常にVue インスタンスが持つ data を信頼できる情報源として取り扱います。これは以下の例で値が2ではなくて1を表示することを意味します。

    data: {
      val: 1
    }
    
    <input v-model="val" value="2">
    

    既存のコンテントを持つ<textarea>も同様に振る舞います。以下ではなく、

    <textarea v-model="val">hello world</textarea>
    

    以下のようにしてください。

    data () {
      return {
        val: 'hello world'
      }
    }
    
    <textarea v-model="val"></textarea>
    

    テンプレートではなくJS側が信頼できる情報源となるべきである、というのが主な考え方です。

  • v-modelv-forによって反復されたプリミティブな値に対して使用することができなくなりました。

    <input v-for="str in strings" v-model="str">
    

    これは以下の JavaScript 処理に相当するため機能しません。

    strings.map(function (str) {
      return createElement('input', ...)
    })
    

    お分かりの通り、strは関数スコープの内部においては単なるローカル変数であるため反復関数内で別の値に代入しても何も起きません。その代わり、v-modelがオブジェクト上のフィールドを更新できるようオブジェクトの配列を使用すべきです。

    <input v-for="obj in objects" v-model="obj.str">
    

Prop の振る舞い

  • .once.syncは非推奨です。Prop は単一方向バインディングとなりました。親のスコープにおける副作用を引き起こすため、コンポーネントは暗黙的なバインディグに頼らずに明示的なイベント発火を必要とします。

  • 局所的な Prop の変更はアンチパターンと見なされるようになりました。例えば、aというPropを宣言した後にコンポーネント内でthis.a = someOtherValueと代入するような手順です。新たなレンダリング機構により、親コンポーネントが再レンダリングされるとき、必ず子コンポーネントでのローカルな変更は上書きされます。概して、2.0においてはPropをイミュータブルとして扱ってください。Propの変更に関する用例のほとんどは、data プロパティか算出プロパティのいずれかで置き換えることができます。

keep-alive

keep-aliveは特別な属性値ではなくなり、<transition>に似たラッパーコンポーネントとなりました。

<keep-alive>
  <component :is="view"></component>
</keep-alive>

<transition>と併用する場合には、確実に内側に入れて下さい。

<transition>
  <keep-alive>
    <component :is="view"></component>
  </keep-alive>
</transition>

スロット

  • 同名、同テンプレートの重複した<slot>はサポートされなくなりました。スロットがレンダリングされたとき、それは"使い切り"であり、同一レンダリングツリー内のどの位置にもレンダリングされません。
  • 名前付きの<slot>で挿入されたコンテンツはslot属性値を保持しません。それらの体裁を整えるにはラッパー要素を使用するか、より応用的な事例としては、レンダー関数を用いて挿入されたコンテンツをプログラム的に修正してください。

Refs

  • v-refはディレクティブではなく、keytransitionのような特別な属性値となりました。

    <!-- before -->
    <comp v-ref:foo></comp>
    
    <!-- after -->
    <comp ref="foo></comp>
    

    また、動的な ref バインディングがサポートされました。

    <comp :ref="dynamivRef"></comp>
    
  • vm.$elsvm.$refsは統合されました。通常の要素に対して使用している場合は ref は DOM 要素を、コンポーネントに対して使用している場合はコンポーネントのインスタンスとなります。

  • vm.$refsはレンダープロセスの間に登録 / 更新されるためリアクティブではなくなりました。これらをりアクティブにすると、毎回の変更で重複したレンダリングを行うことになります。

    一方で、$refsは JavaScript からのプログラム的なアクセスを第一として設計されています。必然的にインスタンスそれ自体には属さない状態を参照しているため、テンプレート内で$refsに依存するのは推奨されません。

その他

  • track-bykeyに置き換えられました。属性値のバインディングに関するルールと同じものに従います。即ち、v-bind:の接頭辞が無い場合は値をリテラル文字列として扱います。ほとんどの場合に動的バインディングとして扱いたいはずですが、そのためには文字列によるキーではなく完全な表記が必要です。例えば以下の通りです。

    <!-- 1.x -->
    <div v-for="item in items" track-by="id">
    
    <!-- 2.0 -->
    <div v-for="item in items" :key="item.id">
    
  • 属性値内でのストリング展開は非推奨となりました。

    <!-- 1.x -->
    <div id="{{ id }}">
    
    <!-- 2.0 -->
    <div :id="id">
    
  • 属性値バインディングの挙動が変更されました。nullundefined、およびfalseのみがバインディングされた属性においてfalseとして評価されます。これは、0や空文字列がそのままレンダリングされることを意味します。列挙属性の場合も同じです(For enumerated attributes)。:draggable="''"draggable="true"としてレンダリングされることになります。
     また、列挙属性においては上記のfalse 判定値に加えて、文字列値 "false" も attr="false" としてレンダリングされます。

  • カスタムコンポーネントに対して使用している場合、v-onはそのコンポーネントの $emit によって発火されたカスタムイベントのみを受け取ります(DOM のイベント通知を受け取りません)。

  • v-elsev-showと併用できません。単に否定表現を使用してください。

  • ワンタイムバインディング({{* foo}})は非推奨です。代わりにv-onceを使用してください。

  • Array.prototype.\$set/\$remove は非推奨となりました(Vue.set か Array.prototype.splice を使用してください)。

  • :styleは埋め込みの!importantをサポートしません。

  • ルートインスタンスはテンプレートのPropを使用できません(propsDataを使用してください)。

  • elオプションはVue.extendで使用できません。インスタンス作成時のオプションでのみ使用可能です。

  • Vue.setVue.deleteはVueインスタンス上で動作しません。最上位のリアクティブなプロパティはdataオプションにおいて適切に宣言されることが必須となりました。

  • また、コンポーネントインスタンスがもつルートの$dataを置換することは禁止されました。これはリアクティブシステムで起こるいくつかのエッジケースを防止し、(特に型チェックシステムと共に使用する際に)コンポーネントの状態をより予測可能なものにします。

  • vm.$watchから作成されたユーザー定義の監視は、関連するコンポーネントの再レンダリングの前に発火するようになりました。これによりユーザーはコンポーネントが再レンダリングする前に他の状態を更新する機会が得られ、不必要な更新を回避することができます。例えば、コンポーネントの prop を監視し、prop に変更があった場合にコンポーネント自身の data を更新することができます。

    コンポーネント更新後にDOMに関与する操作を行いたい場合は、単にupdated ライフサイクルフックを使用して下さい。

更新に関するヒント

$dispatch$broadcast の非推奨化への対処

 $distpatch$broadcast を非推奨とした理由は、コンポーネントのツリー構造に依存したイベントフローは、ツリー構造が巨大になった場合に把握が困難になってしまうことです(簡単に言えば、大規模アプリでの影響の大きさは見通せません(doesn't scale well)し、皆さんを後々痛い目に遭わせてしまうような真似はしたくないのです)。また、$dispatch$broadcastは兄弟コンポーネントとの通信を解決することができません。その代わりにNode.js における EventEmitter パターンに似た手法を取り入れられます。これは互いがコンポーネントツリー構造内のどの位置にあっても、コンポーネント間の通信を可能にする中央集権的なイベントの中枢となります。 Vue インスタンスはイベントエミッターのインターフェイスとして用を満たすので、実際に空の Vue インスタンスを使用して実装することが出来ます。

var bus = new Vue()
// コンポーネントAのメソッド
bus.$emit('id-selected', 1)
// コンポーネントBでの created フック
bus.$on('id-selected', function (id) {
  // ...
})

 このパターンは単純なシナリオによって$dispatch$broadcastの代役を果たします。しかし、より複雑なケースでは Vuex による専用のステート管理層を導入することをお勧めします。

配列フィルタの非推奨化への対処

 v-forにおけるリストのフィルタリング(フィルターの最もありふれた用法の1つ)では、元の配列を成形したコピーを返す算出プロパティの使用を推奨します(詳細はupdated data grid exampleを参照)。これにはフィルタが持つ恣意的な構文/APIの制約を受けない利点があります。算出プロパティであれば通常のJavaScriptですし、当然ながらフィルタリングの結果にアクセスすることもできるのです。

こちらの議論スレッドもご覧ください。

v-modelにおけるdebounceの非推奨化への対処

 以前までデバウンスは Ajax リクエストやその他高コストな処理の実行回数を制限をしていました。 Vue のv-modelに用意されたdebouce属性パラメータはこれを容易に可能にしていましたが、高コストな処理そのものよりもむしろステート更新に対してデバウンスをしており、これが制限を生んでいます。

 これらの制限は、検索状態表示 を設計する際に明白になります。例をご覧ください。これまで、debounce属性を使用していると input のリアルタイムな状態へのアクセスを失っているため、検索が始まる前では入力の逐一を検知する方法がありませんでした。 Vue からデバウンス関数を分離することで、制限したい処理だけをデバウンスすることができるようになります。

 デバウンスが本当に適切なラッパー関数とならない別の場合があります。検索候補の API が行き当たるごくありふれた例では、ユーザーがキー入力を止めた後まで候補の表示を待つのは理想的な実装ではありません。その代わりに使用したいものはスロットリング関数でしょう。既に lodash のようなユーティリティライブラリをdebounceに使用しているのですから、throttleを使用したものへ修正するのに数分しかかかりません!

prismrism
主に JavaScript 周辺をいじっているフロントエンドエンジニアもどきです。Vue.js とよく遊んでいます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away