目次
Dep
Watcher
Observer
コアプロセス
observe 関数では、新しい Observer オブジェクトが作成されます。このオブジェクトでは、Observer.prototype.walk を使用してオブジェクト内の値を 1 つずつ応答的に処理し、defineReactive 関数は使用済み。
ホームページ ウェブフロントエンド Vue.js Vue の応答性の原則は何ですか?

Vue の応答性の原則は何ですか?

Jul 29, 2021 pm 05:42 PM
javascript vue.js フロントエンド

最近、Vue の原則に関する記事をたくさん読みました。これらの記事を参考に、自分自身で Vue のソース コードを理解しようと何度も試みました。いよいよ私自身がアウトプットしてみようと思いますが、他の記事とは違った視点で皆さんに Vue を知っていただければと思います。

Vue の応答性の原則は何ですか?

Dep

var Dep = function Dep() {
  this.id = uid++
  this.subs = []
}
ログイン後にコピー

Dep の意味は当然依存関係 (つまり依存、コンピュータ分野の名詞) です。

node.js プログラムを作成するのと同じように、npm ウェアハウスの依存関係がよく使用されます。 Vue では、依存関係は特にリアクティブに処理されるデータを指します。後で説明するように、リアクティブ処理の重要な機能の 1 つは、多くの Vue 原則に関する記事で言及されている defineReactive です。

Dep が各応答データにバインドされると、応答データは依存関係 (名詞) になります。以下で Watcher を紹介するときに、応答データが監視、計算、またはテンプレートで使用される可能性があることに言及します。依存(動詞)の 3 つのケース。

#subs

Dep オブジェクトの下に配列である subs 属性がありますが、これが購読者リストを意味していることは容易に推測できます。サブスクライバは、監視関数、計算関数、またはビュー更新関数の場合があります。

Watcher

Watcher は、Dep で言及されているサブスクライバです (後の Observer オブザーバと混同しないでください)。

Watcher の機能は、一部のアプリの購読プッシュと同じように、Dep の更新にタイムリーに応答することであるため、あなた (Watcher) が特定の情報 (Dep) を購読すると、次の情報を読むよう通知されます。情報が更新されたとき。

deps

Dep が subs 属性を持つのと同様に、Watcher オブジェクトにも deps 属性があります。これは、Watcher と Dep の間に多対多の関係を構成します。相互に記録する理由は、一方のパーティがクリアされると、関連するオブジェクトを適時に更新できるためです。

Watcher の生成方法

上で何度も説明した監視テンプレート、計算テンプレート、レンダリング テンプレートによって Watcher が生成されます。これらはすべて Vue ソース コードで簡潔で理解しやすいものです。 :

  • mountComponent の vm._watcher = new Watcher(vm, updateComponent, noop);
  • initComputed の watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions )
  • $watcher's var watcher = new Watcher(vm, expOrFn, cb, options);

Observer

Observer はオブザーバーであり、再帰的に実行する責任があります。リアクティブなオブジェクト (または配列) を観察 (または処理) します。印刷された例では、反応性オブジェクトに __ob__ が付いていることがわかります。これは、観察されたことの証拠です。オブザーバーは上記の Dep や Watcher ほど重要ではなく、少し理解するだけで十分です。

walk

Observer.prototype.walk は Observer の初期化時の再帰処理の中核となるメソッドですが、このメソッドはオブジェクトの処理に使用され、Observer もあります。 prototype.observeArray 配列を処理します。

コアプロセス

上記の概念間の関係に従って、それらをどのように一致させ、応答性の高いデータ更新を実現するか?

最初に目標を設定します。当然、データが更新されると、ビューが自動的に更新されて最新のデータが表示されます。

これは上記の Dep と Watcher の関係で、データは Dep、Watcher はページ レンダリング関数をトリガーします (これが最も重要な Watcher)。

しかし、新たな疑問が生じます。ウォッチャーが自分を依存していることを、デップはどのようにして知るのでしょうか?

Vue は非常に興味深い方法を採用しています:

  • Watcher のコールバック関数を実行する前に、まず現在の Watcher が何であるかを (Dep.target を通じて) 書き留めます

  • 実行中のコールバック関数でレスポンシブ データが使用されている場合、必然的にレスポンシブ データのゲッター関数が呼び出されます。 data 現在の Watcher を書き留めて、Dep と Watcher の間の関係を確立できます。

  • その後、レスポンシブ データが更新されると、必然的にレスポンシブ データの setter 関数が呼び出されます

  • 以前に確立された関係に基づいて、ウォッチャーに対応するコールバック関数をセッター関数でトリガーできます

  • コード

  • 上記のロジックはdefineReactive関数の途中にあります。この関数には多くの入り口がありますが、最初に、より重要な観察関数について説明しましょう。

observe 関数では、新しい Observer オブジェクトが作成されます。このオブジェクトでは、Observer.prototype.walk を使用してオブジェクト内の値を 1 つずつ応答的に処理し、defineReactive 関数は使用済み。

defineReactive 関数は非常に重要で長くないため、ここに直接投稿する方が便利です。

function defineReactive(obj, key, val, customSetter, shallow) {
  var dep = new Dep()
  depsArray.push({ dep, obj, key })
  var property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  var getter = property && property.get
  var setter = property && property.set

  var childOb = !shallow && observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      var value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter(newVal) {
      var value = getter ? getter.call(obj) : val
      // 后半部分诡异的条件是用于判断新旧值都是 NaN 的情况
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      // customSetter 用于提醒你设置的值可能存在问题
      if ('development' !== 'production' && customSetter) {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()
    },
  })
}
ログイン後にコピー

まず第一に、各応答値は「依存関係」であるため、最初のステップでは、クロージャーの機能を使用して各値の Dep を作成します。 (Vue 3 では、クロージャは必要ありません)

次に、3 つのコア パラメータを見てみましょう:

obj 現在、値を応答的に処理する必要があるオブジェクト

  • key value key

  • val current value

  • この値は、独自の値より前に定義されている可能性があります。 getter と setter が存在するため、Vue の応答処理を実行するときは、元の getter と setter が最初に処理されます。

  • コアプロセスで前述したように、ゲッター関数は、特に dep.depend() に依存して、Dep と Watcher の間の関係を確立します。

以下に、Dep と Watcher が相互に呼び出すためのいくつかのメソッドを示します。

Dep.prototype.depend = function depend() {
  if (Dep.target) {
    Dep.target.addDep(this)
  }
}
Watcher.prototype.addDep = function addDep(dep) {
  var id = dep.id
  if (!this.newDepIds.has(id)) {
    this.newDepIds.add(id)
    this.newDeps.push(dep)
    if (!this.depIds.has(id)) {
      dep.addSub(this)
    }
  }
}
Dep.prototype.addSub = function addSub(sub) {
  this.subs.push(sub)
}
ログイン後にコピー

通过这几个函数,可以领略到了 Dep 和 Watcher 错综复杂的关系……不过看起来迂回,简单来说,其实做的就是上面说的互相添加到多对多列表。

你可以在 Dep 的 subs 找到所有订阅同一个 Dep 的 Watcher,也可以在 Watcher 的 deps 找到所有该 Watcher 订阅的所有 Dep。

但是里面还有一个隐藏问题,就是 Dep.target 怎么来呢?先放一放,后会作出解答。先接着看看 setter 函数,其中的关键是 dep.notify()。

Dep.prototype.notify = function notify() {
  // stabilize the subscriber list first
  var subs = this.subs.slice()
  for (var i = 0, l = subs.length; i < l; i++) {
    subs[i].update()
  }
}
ログイン後にコピー

不难理解,就是 Dep 提醒他的订阅者列表(subs)里的所有人更新,所谓订阅者都是 Watcher,subs[i].update() 调用的也就是 Watcher.prototype.update。

那么来看一下 Watcher 的 update 做了什么——

Watcher.prototype.update = function update() {
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)
  }
}
ログイン後にコピー

在这里我觉得有两个点比较值得展开,所以挖点坑

以上がVue の応答性の原則は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ Mar 16, 2024 pm 12:09 PM

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ 今日のインターネットの急速な発展の時代において、フロントエンド開発はますます重要になっています。 Web サイトやアプリケーションのエクスペリエンスに対するユーザーの要求がますます高まっているため、フロントエンド開発者は、より効率的で柔軟なツールを使用して、応答性の高いインタラクティブなインターフェイスを作成する必要があります。フロントエンド開発の分野における 2 つの重要なテクノロジーである PHP と Vue.js は、組み合わせることで完璧なツールと見なされます。この記事では、PHP と Vue