ホームページ >ウェブフロントエンド >Vue.js >Vue のレスポンシブ データ処理方法の詳細な分析

Vue のレスポンシブ データ処理方法の詳細な分析

青灯夜游
青灯夜游転載
2023-03-28 19:14:402243ブラウズ

この記事は、vue を学習し、vue がレスポンシブ データをどのように処理するかについて説明するのに役立ちます。お役に立てれば幸いです!

Vue のレスポンシブ データ処理方法の詳細な分析

vue のレスポンシブ データについては多くの疑問があるかもしれません。

たとえば、なぜ代わりにプロキシを使用する必要があるのですか?

たとえば、なぜ 2 つの API (reactive と ref) があるのですか?

たとえば、vue はどのように応答性を実装するのでしょうか?

実際、これらに対する答えはソース コードの中にあります。

最初の記事「vue3 のアップグレードとは」では、プロキシを使用する利点と Object.defineProperty の欠点についても触れました。しかし今日は角度を変えて、chatGPT にこの質問に答えてもらいたいと思います。 [関連する推奨事項: vuejs ビデオ チュートリアル Web フロントエンド開発 ]

そうですね、私が要約したものよりも優れていると思います。

Vue のレスポンシブ データ処理方法の詳細な分析

# それでは、次の質問に進みます。

Vue のレスポンシブ データ処理方法の詳細な分析

この答えはより正式なものに感じられ、私が望む答えは得られません。

その理由は実際には非常に簡単で、プロキシ メソッドは値の型をプロキシできず、オブジェクトのみをプロキシできるからです。したがって、値型データを処理するには追加のメソッドが必要です。

もちろん、1 つの ref で世界を征服することもできます。vue のソースコードに互換性があれば、自動的に変換されます。

これを理解した上で、今日のを見てみましょう。 ハイライトは、vue3 のソース コードを模倣し、応答性の高いシステムを実装することです。

関連するコードをクリックして表示し、記事のタイトルに従ってさまざまなブランチを選択できます。 reactive の実装

前回の記事で、reactive が実際にはプロキシ オブジェクトであることも紹介しました。

プロキシを使用して、単純なプロキシ関数をリアクティブに実装できます。

      function reactive(target) {        const isObject = (val) =>  val !== null && typeof val === 'object'

        if (!isObject(target)) {          console.warn(`数据必须是对象: ${String(target)}`)          return target
        }        const proxy = new Proxy(target, {          get: (target, key, receiver) => {            console.log('get', key)            const res = Reflect.get(target, key, receiver)            // track(target, key)
            // 这句很关键,不然嵌套数据,里面的不会响应
            if (isObject(res)) {              return reactive(res)
            }            return res
          },          set: (target, key, value, receiver) => {            console.log('set', key, value)            const result = Reflect.set(target, key, value, receiver)            // trigger(target, key, value)
            return result
          },          deleteProperty: () => {            const result = Reflect.deleteProperty(target, key)            return result
          }
        })        return proxy
      }      const person = reactive({        name: '',        age: 18,        like: ['apple']
      })

      person.name  = 'vue test'复制代码

注: Reflect

Reflect.get(target, key) は、target[key] に直接アクセスすることとは少し異なります。

プロキシ オブジェクト内で this が指す get、set などがある場合、これをリダイレクトできます。

例:

        const person = new Proxy({            name: "vue test",            age: 18,            get info() {                return 'name is :' + this.name + ' age is:' + this.age
            }
        }, {            get: (target, key, receiver) => {                console.log('get', key)                // return target[key]
                return Reflect.get(target, key, receiver)
            }
        })        console.log(person.info)复制代码

Reflect を使用すると、名前と年齢にアクセスするときにトリガーできます。

Vue のレスポンシブ データ処理方法の詳細な分析ターゲットに変更した後は、情報内で 1 回だけトリガーされます。

return target[key]复制代码

Vue のレスポンシブ データ処理方法の詳細な分析ref の実装

vue3 では、ref は get と set によって実装されます。

上記と同様に、最初に関数を宣言し、次に get および set を通じてデータにアクセスします。

      function ref(value) {        return new RefImpl(value)
      }      class RefImpl {        constructor(value) {          // 如果值是对象,则用reactive处理
          this._value = isObject(value) ? reactive(value) : value          // 记录一下初始值
          this._rawValue = value
        }        get value() {          // trackRefValue(this)
          return this._value
        }        set value(newVal) {          if (!Object.is(newVal, this._rawValue)) {            // 更新原始数据
            this._rawValue = newVal            // 更新 .value 的值
            this._value = isObject(newVal) ? reactive(newVal) : value            // triggerRefValue(this)
          }
        }
      }复制代码

ソース コードでは、get/set が value を通じて設定されるため、.value で ref を使用する必要がある理由も非常に直感的に説明されています。

依存関係の収集とトリガーを追加する

データ プロキシは完成しましたが、データが変更された後、双方向バインディングを実装するようにコンポーネントに通知するにはどうすればよいでしょうか?

答えは、コレクションとトリガーに依存することです。つまり、get がトリガーされると、get をトリガーする条件 [関数] を保存します。set がトリガーされると、それを再実行して条件 [関数] をトリガーします。 ]. ]それだけでは十分ではありませんか?

もう一度コードを見て、トラック収集メソッドとターゲット トリガー メソッドを追加します。 (つまり、上記のコード スニペットでコメントアウトされた 2 行のコード)

さらに、トリガー関数を管理するためにエフェクト関数も必要です。

      let activeEffect = null
      const targetMap = new WeakMap()      // 依赖收集/触发
      function track(target, key) {        let depsMap = targetMap.get(target)        if (!depsMap) {
          targetMap.set(target, (depsMap = new Map()))
        }        let dep = depsMap.get(key)        if (!dep) {
          dep = new Set()
        }
        dep.add(activeEffect)
        depsMap.set(key, dep)
      }      function trigger(target, key, value) {        const depsMap = targetMap.get(target)        if (!depsMap) {          return
        }        const deps = depsMap.get(key)        if (!deps) {          return
        }

        deps.forEach(effectFn => {          if (effectFn.scheduler) {
            effectFn.scheduler()
          } else {            effectFn()
          }
        })
      }      function effect(fn,options = {}) {        const effectFn = () => {          try {
            activeEffect = effectFn            return fn()
          } catch (error) {
            activeEffect = null
          }
        }        if (!options.lazy) {          effectFn()
        }
        effectFn.scheduler = options.scheduler
        return effectFn
      }      const person = reactive({        name: "hello world"
      })      effect(() => {        console.log('effect person', person.name)
      })      setTimeout(() => {
        person.name = 'setTimeout world'
      }, 2000)复制代码

activeEffect は、トリガー条件関数を保存するために使用されます。

targetMap は依存関係辞書を格納するために使用されます。形式は次のとおりです

{
    target: {
        key: []
    }
}复制代码

出力結果は hello world です。2 秒後に依存関係関数が再実行され、setTimeout world が出力されます

Vue のレスポンシブ データ処理方法の詳細な分析概要

データ プロキシは複雑ではなく、プロキシに基づいており、いくつかの境界処理が追加されています。応答性を実現するには、依存関係の収集と依存関係のトリガーの実装を追加する必要があります。

effect は非常に重要な関数であり、useEffect や watch など多くの API がこの関数をベースにして開発されています。コンポーネントの更新も後述するエフェクト機能に基づいて行われます。

効果がわからない場合は、実行順序を整理してください。

  • 1. エフェクト関数を呼び出し、パラメーター fn
  • 2 を渡します。effectFn 関数を宣言して実行し、関数を activeEffect# として保存します。
  • ##3. fn を実行して person.name を読み取ります
  • 4. プロキシの get proxy を使用します
  • 5. 依存関係を収集し、activeEffect で保存した関数をグローバル マップに保存します
  • #6. このとき、エフェクト関数は実行され、データの更新を待機します
  • #7.2秒後、プロキシの設定プロキシに移動
  • 8. グローバルマップに保存した関数を実行し、エフェクト関数を再実行し、再び手順1に戻ります。
  • クリックして関連コード
を表示し、lesson3 ブランチを選択できます。

記事に関連するコードは vue/examples で参照でき、vue の模倣実装バージョンは package/reactivity で参照できます。

(学習ビデオ共有:

vuejs 入門チュートリアル

基本プログラミング ビデオ )

以上がVue のレスポンシブ データ処理方法の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。