レスポンシブ原則の詳細


目次


変更を追跡する方法


通常の JavaScript オブジェクトを data オプションとして Vue インスタンスに渡すと、Vue はオブジェクトのすべてのプロパティを反復処理し、Object.defineProperty を使用してすべてのプロパティを変換します。これらのプロパティを getter/setter に設定します。 Object.defineProperty は ES5 の機能でシム化できません。そのため、Vue は IE8 以前のブラウザをサポートしません。

これらのゲッター/セッターはユーザーには見えませんが、内部的には Vue が依存関係を追跡し、プロパティがアクセスされ変更されたときに変更を通知できるようにします。ここで注意すべき点は、コンソールにデータ オブジェクトを出力する際、ブラウザーによってゲッター/セッターの形式が異なるため、データを検査するためのより使いやすいユーザー インターフェイスを取得するために vue-devtools をインストールすることをお勧めします。

各コンポーネント インスタンスは watcher インスタンスに対応し、コンポーネントのレンダリング プロセス中に「タッチされた」データ属性を依存関係として記録します。その後、依存関係のセッターが起動すると、ウォッチャーに通知され、関連するコンポーネントが再レンダリングされます。

1568871314181366.png


#変更の検出に関する注意事項


期限最新の JavaScript の制限により (

Object.observe も非推奨になりました)、Vue はオブジェクト プロパティの追加または削除 を検出できません。 Vue はインスタンスの初期化時にプロパティのゲッター/セッター変換を実行するため、Vue がリアクティブに変換するにはプロパティが data オブジェクトに存在する必要があります。例:

var vm = new Vue({
  data:{
    a:1
  }
})

// `vm.a` 是响应式的

vm.b = 2
// `vm.b` 是非响应式的

すでに作成されたインスタンスの場合、Vue ではルートレベルのリアクティブ プロパティを動的に追加できません。ただし、

Vue.set(object, propertyName, value) メソッドを使用して、ネストされたオブジェクトにリアクティブ プロパティを追加できます。たとえば、次の場合:

Vue.set(vm.someObject, 'b', 2)

また、グローバル

Vue.set メソッドのエイリアスでもある vm.$set インスタンス メソッドを使用することもできます。 ##

this.$set(this.someObject,'b',2)

Object.assign()_.extend() を使用するなど、複数の新しいプロパティを既存のオブジェクトに割り当てる必要がある場合があります。ただし、この方法でオブジェクトに追加された新しいプロパティは更新をトリガーしません。この場合、ブレンドしたいオブジェクトのプロパティとともに、元のオブジェクトから新しいオブジェクトを作成する必要があります。

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

配列関連の考慮事項もいくつかあります。これについては、リストのレンダリングで説明しました。


リアクティブ プロパティを宣言する


Vue ではルートレベルの動的追加が許可されていないため、リアクティブ プロパティのプロパティであるため、たとえそれが null 値であっても、インスタンスを初期化する前にすべてのルートレベルのリアクティブ プロパティを宣言する必要があります。

var vm = new Vue({
  data: {
    // 声明 message 为一个空值字符串
    message: ''
  },
  template: '<div>{{ message }}</div>'
})
// 之后设置 `message`
vm.message = 'Hello!'

data で宣言しない場合 オプション メッセージ、Vue は、レンダー関数が存在しないプロパティにアクセスしようとしていると警告します。

この制限の背後には技術的な理由があり、依存関係追跡システムの一種のエッジ ケースが排除され、Vue インスタンスが型チェック システムとより適切に連携できるようになります。しかし同時に、コードの保守性の観点から重要な考慮事項があります。data オブジェクトはコンポーネント状態のスキーマのようなものです。すべてのリアクティブ プロパティを前もって宣言すると、コンポーネント コードが将来変更されるとき、または他の開発者が読み取るときに、コンポーネント コードが理解しやすくなります。


#非同期更新キュー


まだ気づいていないかもしれませんが、Vue は更新中です。 DOM は非同期で実行されます。データ変更をリッスンしている限り、Vue はキューを開き、同じイベント ループ内で発生するすべてのデータ変更をバッファーに入れます。同じウォッチャーが複数回トリガーされた場合、キューにプッシュされるのは 1 回だけです。バッファリング中のこの重複排除は、不必要な計算や DOM 操作を回避するために重要です。次に、次のイベント ループ「ティック」で、Vue はキューをフラッシュし、実際の (重複排除された) 作業を実行します。 Vue は内部的に、非同期キューにネイティブの

Promise.thenMutationObserver、および setImmediate を使用しようとします。実行環境がそれをサポートしていない場合、setTimeout(代わりに fn, 0) を使用してください。

たとえば、

vm.someData = '新しい値' と設定すると、コンポーネントはすぐには再レンダリングされません。キューがフラッシュされると、コンポーネントは次のイベント ループ「ティック」で更新されます。ほとんどの場合、このプロセスについて心配する必要はありませんが、更新された DOM 状態に基づいて何かを実行したい場合は、少し注意が必要になる可能性があります。 Vue.js は通常、開発者が「データ駆動型」の方法で考え、DOM との直接の接触を避けることを推奨していますが、そうしなければならない場合もあります。データ変更後に Vue が DOM の更新を完了するのを待つには、データ変更直後に Vue.nextTick(callback) を使用します。こうすることで、DOM の更新が完了した後にコールバック関数が呼び出されます。例えば:###

<div id="example">{{message}}</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: '123'
  }
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
})

コンポーネント内で vm.$nextTick() インスタンス メソッドを使用すると、グローバル Vuethis が必要ないため、特に便利です。コールバック関数は現在の Vue インスタンスに自動的にバインドされます。

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: '未更新'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = '已更新'
      console.log(this.$el.textContent) // => '未更新'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => '已更新'
      })
    }
  }
})

$nextTick()Promise オブジェクトを返すため、新しい ## を使用できます。 #ES2016 async/await 構文は同じことを実現します:

methods: {
  updateMessage: async function () {
    this.message = '已更新'
    console.log(this.$el.textContent) // => '未更新'
    await this.$nextTick()
    console.log(this.$el.textContent) // => '已更新'
  }
}