Maison > interface Web > Voir.js > le corps du texte

Une analyse approfondie de la méthode de traitement des données réactives de Vue

青灯夜游
Libérer: 2023-03-28 19:14:40
avant
2202 Les gens l'ont consulté

Cet article vous aidera à apprendre Vue et à expliquer comment Vue gère les données réactives ? J'espère que cela aidera tout le monde !

Une analyse approfondie de la méthode de traitement des données réactives de Vue

Vous avez peut-être beaucoup de doutes sur les données réactives de vue.

Par exemple, pourquoi devrions-nous passer au proxy ?

Par exemple, pourquoi y a-t-il deux API, réactive et ref ?

Par exemple, comment Vue implémente-t-elle la réactivité ?

En fait, les réponses à ces questions se trouvent dans le code source.

Dans le premier article Quelles sont les mises à niveau de vue3, j'ai également mentionné les avantages de l'utilisation d'un proxy et les inconvénients d'Object.defineProperty. Mais aujourd’hui, j’ai envie de changer d’angle et de laisser chatGPT répondre à cette question. [Recommandations associées : tutoriel vidéo vuejs, développement web front-end]

Eh bien, je pense que c'est mieux que ce que j'ai résumé.

Une analyse approfondie de la méthode de traitement des données réactives de Vue

Passez ensuite à la question suivante.

Une analyse approfondie de la méthode de traitement des données réactives de Vue

Cette réponse semble plus officielle, mais elle ne me donne pas la réponse que je souhaite.

La raison est en fait très simple, car la méthode proxy ne peut pas proxy de types de valeurs, uniquement des objets. Une méthode supplémentaire est donc nécessaire pour gérer les données de type valeur.

Bien sûr, vous pouvez également conquérir le monde avec une seule référence. Si le code source de vue est compatible, il sera automatiquement converti

Avec cette compréhension, regardons le point culminant d'aujourd'hui, imitant le code source de vue3 en. mettre en place un système réactif.

Vous pouvez cliquer pour afficher le code correspondant, il suffit de sélectionner différentes branches en fonction du titre de l'article.

Implémenter reactive

Nous avons également introduit dans l'article précédent que reactive est en fait un objet proxy.

Nous pouvons utiliser un proxy pour implémenter une simple fonction proxy réactive.

      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'复制代码
Copier après la connexion

Remarque : Reflect

Reflect.get(target, key) est légèrement différent de l'accès direct à target[key].

Lorsqu'il y a get, set, etc. pointés dans l'objet proxy, cela peut être redirigé.

Par exemple :

        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)复制代码
Copier après la connexion

En utilisant Reflect, nous pouvons le déclencher lors de l'accès au nom et à l'âge. Une analyse approfondie de la méthode de traitement des données réactives de Vue

Après le passage en cible, il ne se déclenchera qu'une seule fois en info.

return target[key]复制代码
Copier après la connexion

Une analyse approfondie de la méthode de traitement des données réactives de Vue

Implémentation de ref

Dans vue3, ref est implémenté via get et set.

Semblable à ce qui précède, nous déclarons toujours une fonction d'abord, puis accédons aux données via get et 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)
          }
        }
      }复制代码
Copier après la connexion

Le code source explique également de manière très intuitive pourquoi ref doit être utilisé dans .value, car get/set est défini via value.

Ajouter la collecte et le déclenchement des dépendances

Nous avons terminé le proxy de données, mais après les modifications des données, comment notifier le composant pour implémenter la liaison bidirectionnelle ?

La réponse est de s'appuyer sur la collecte et le déclenchement. Autrement dit, lorsque get est déclenché, j'enregistre la condition [fonction] qui déclenche get. Lorsque set est déclenché, il suffit de le réexécuter pour déclencher la condition [fonction]. .

Regardons à nouveau le code. J'ajouterai une méthode de collecte de pistes et une méthode de déclenchement cible. (C'est-à-dire les deux lignes de code commentées dans l'extrait de code ci-dessus)

De plus, une fonction d'effet est nécessaire pour gérer la fonction de déclenchement.

      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)复制代码
Copier après la connexion

activeEffect est utilisé pour stocker les fonctions de condition de déclenchement.

targetMap est utilisé pour stocker le dictionnaire de dépendances. Le format est le suivant

{
    target: {
        key: []
    }
}复制代码
Copier après la connexion

Le résultat de sortie est hello world Après 2 secondes, la fonction de dépendance est réexécutée et setTimeout world est affiché

Une analyse approfondie de la méthode de traitement des données réactives de Vue

Résumé

. Le proxy des données n'est pas compliqué. Sur la base du proxy, un certain traitement des limites est ajouté. Pour atteindre la réactivité, vous devez ajouter la collecte de dépendances et l'implémentation du déclenchement des dépendances.

effect est une fonction très importante. De nombreuses API sont développées sur la base de cette fonction, comme useEffect et watch. La mise à jour des composants repose également sur la fonction d'effet, qui sera évoquée plus loin.

Si vous ne comprenez pas l'effet, vous pouvez trier la séquence d'exécution.

  • 1. Appelez la fonction effect et transmettez le paramètre fn
  • 2 Déclarez une fonction effectFn, exécutez-la et enregistrez la fonction sous activeEffect
  • 3.
  • 4. Utilisez le proxy get
  • 5. Collectez les dépendances et enregistrez la fonction enregistrée par activeEffect dans la carte globale
  • 6.
  • 7.2s Enfin, accédez au proxy défini par le proxy
  • 8. Exécutez la fonction enregistrée dans la carte globale, réexécutez la fonction d'effet et revenez à nouveau à l'étape 1
  • Vous pouvez cliquer pour afficher le code pertinent et sélectionnez la branche leçon3.
Le code lié à l'article peut être consulté dans vue/examples, et la version d'implémentation d'imitation vue peut être consultée dans packages/reactivity.

(Partage de vidéos d'apprentissage : Tutoriel d'introduction à vuejs

,

Vidéo de programmation de base

)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!