Maison >interface Web >Voir.js >Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)

Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)

WBOY
WBOYavant
2021-12-22 18:25:282279parcourir

Cet article vous apporte les connaissances pertinentes sur l'analyse du principe de réponse aux données vue2 et vue3 et la mise en œuvre manuelle. La vue et les données réactives aux données sont automatiquement mises à jour lorsque les données sont mises à jour, la vue est automatiquement mise à jour pour suivre les modifications des données. vous sera utile. Tout le monde est utile.

Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)

Réactivité des données

  • La vue et les données sont automatiquement mises à jour lorsque les données sont mises à jour, la vue est automatiquement mise à jour
  • Suivi des modifications des données, vous pouvez effectuer des détournements lors de la lecture des données ou de la définition des données. Certaines opérations
  • vue2 utilise DéfinirProperty
  • vue3 et utilise Proxy

Utiliser DéfinirProperty

Comment suivre les modifications

var obj = {}var age 
Object.defineProperty(obj, 'age', {
    get: function() {
        consoel.log('get age ...')
        return age    },
    set: function(val) {
        console.log('set age ...')
        age = val    }})obj.age =100 //set age ...console.log(obj.age)//get age ...

L'objet obj appellera la méthode get de piratage de données lors de l'obtention de l'attribut age
Lors de l'attribution d'une valeur à l'attribut age, appelez le set method

Ensuite, comment utiliser Object.defineProperty pour implémenter une réponse de données

function defineReactive(data) {
  if (!data || Object.prototype.toString.call(data) !== '[object Object]')
    return;
  for (let key in data) {
    let val = data[key];
    Object.defineProperty(data, key, {
      enumerable: true, //可枚举
      configurable: true, //可配置
      get: function() {
        track(data, key);
        return val;
      },
      set: function() {
        trigger(val, key);
      },
    });
    if (typeof val === "object") {
      defineReactive(val);
    }
  }}function trigger(val, key) {
  console.log("sue set", val, key);}function track(val, key) {
  console.log("sue set", val, key);}const data = {
  name:'better',
  firends:['1','2']}defineReactive(data)console.log(data.name)console.log(data.firends[1])console.log(data.firends[0])console.log(Object.prototype.toString.call(data))

Cette fonction defineReactve est utilisée pour encapsuler Object.defineProperty À partir du nom de la fonction, vous. On peut voir que la fonction consiste à définir des données réactives. Après l'encapsulation, il vous suffit de transmettre les données, la clé et la valeurdefineReactve用来对Object.defineProperty进行封装,从函数名可以看出,起作用就是定义一个响应式数据,封装后只需要传递data,key和val就行
每当从data中读取key的时候触发track函数,往data的key中设置数据时,set函数中的trigger函数触发

数组的响应式

我们通过Array原型上的方法来改变数组的内容不会触发getter和setter
整理发现Array原型中可以改变数组自身内容的方法有7个,分别push pop shift unshift splice sort reverse
vue2 改写了这这7种方法
实现方式:
以Array.propertype为原型创建一个arrayMethods对象,再使用Object.setPropertypeOf(o, arryMethods)将o的__proto__指向arrayMethods

Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)

如何收集依赖

使用

<template><p>{{name}}</p></template>

该模板中使用数据 name, 我们要观察数据, 当数据的属性发生变化的时候, 可以通知哪些使用的地方,
这就是我们要先收集依赖,即把用到数据name的地方收集起来,然后等数据变化的时候,把之前收集好的依赖循环触发一遍,总结来说就是getter中收集依赖,在setter中触发依赖

使用proxy

Proxy对象用于创建一个对象的代理, 从而实现基本操作的拦截和定义(如属性查找、赋值、枚举、函数掉用等)

const p = new Proxy(target, handler)
  • target

  • 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

  • handler

  • 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
    reflect是一个内置对象, 他提供拦截javascript操作的方法, 这些方法和Proxy handlers相同

Reflect.set将值分配给属性的函数。返回一个Boolean 如果更新成功则返回true

Reflect.get获取对象身上某个属性的值,类似target[name]

如何实现劫持

const dinner = {
  meal:'111'}const handler = {
  get(target, prop) {
    console.log('get...', prop)
    return Reflect.get(...arguments)
  },
  set(target, key, value) {
    console.log('get...', prop)
    console.log('set',key,value)
    return Reflect.set(...arguments)
  }}const proxy = new Proxy(dinner, handler)console.log(proxy.meal)console.log(proxy.meal)

代码中dinner 对象代理到handler上
defineProperty区别
defineProperty Chaque fois que la clé est lue à partir des données, la fonction de suivi est déclenchée et lorsque les données sont définies. à la clé des données, dans la fonction set La fonction trigger déclenche la

réactivité du tableau

Nous modifions le contenu du tableau via les méthodes sur le prototype Array, qui ne déclencheront pas le getter et le setter

Après. organiser et découvrir les méthodes dans le prototype Array qui peuvent changer le contenu du tableau lui-même Il y en a respectivement 7 push pop shift unshift splice sort <code>reverse

vue2 réécrit ces 7 méthodes

Méthode d'implémentation :

Créer un tableauMethods objet avec Array.propertype comme prototype, puis utilisez Object.setPropertypeOf(o, arryMethods)Pointez le __proto__ de o vers arrayMethods<img src="https://img.php.cn/upload/article/000/000/067/acd642f4f02e97980836bd636302ac44-1.png" alt="Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)">

Analyse du principe de réactivité aux données Vue2 et Vue3 et mise en œuvre manuelle (exemples détaillés)

Comment collecter les dépendances

Utilisez

function reactive(obj) {
  const handler = {
    get(target, prop, receiver) {
      track(target, prop);
      const value =  Reflect.get(...arguments);
      if(typeof value === 'Object') {
        reactive(value)
      }else {
        return value      }
    },
    set(target,key, value, receiver) {
      trigger(target,key, value);
      return Reflect.set(...arguments);
    },
  };
  return new Proxy(obj,handler)}function track(data, key) {
  console.log("sue set", data, key);}function trigger(data, key,value) {
  console.log("sue set", key,':',value);}const dinner = {
  name:'haochi1'}const proxy  =reactive(dinner)proxy.name
proxy.list = []proxy.list.push(1)

Les données nom sont utilisées dans ce modèle. Nous devons observer les données. Lorsque les attributs des données changent, nous pouvons notifier les endroits où elles sont utilisées,
    Cela signifie que nous devons d'abord collecter les dépendances, c'est-à-dire collecter les endroits où le nom des données est utilisé. , puis lorsque les données changent, déclenchez la boucle de dépendance précédemment collectée. En résumé, les dépendances sont collectées dans les getters et les dépendances sont déclenchées dans les setters
  1. Utiliser un proxy
    L'objet proxy est utilisé pour créer un proxy pour un objet, réalisant ainsi. l'interception et la définition des opérations de base (telles que la recherche d'attributs, l'affectation, l'énumération, la suppression de fonctions, etc.)
  • rrreee
  • target code><li> <li>L'objet cible à envelopper avec <code> Proxy (peut être n'importe quel type d'objet, y compris un tableau natif, une fonction ou même un autre proxy).
  1. handler
  • Un objet généralement avec des fonctions comme attributs. Les fonctions de chaque attribut définissent respectivement le comportement de l'agent p lors de l'exécution de diverses opérations.

    Reflect est un objet intégré qui fournit des méthodes pour intercepter les opérations Javascript. Ces méthodes sont les mêmes que les gestionnaires de proxy
  • Fonction Reflect.set qui attribue des valeurs aux propriétés. Renvoie un booléen et renvoie vrai si la mise à jour réussit
  • Reflect.get obtient la valeur d'une propriété sur l'objet, similaire à target[name]

    Comment implémenter le détournement
  • rrreee
L'objet dîner dans le code est proxy vers le gestionnaire

Suivez la différence defineProperty

Les propriétés de defineProperty doivent être parcourues pour superviser toutes les propriétés

Utilisez un proxy pour proxy toutes les propriétés de l'objet

Utilisez un proxy pour implémenter une réponse simuléerrreee

Imprimer automatiquement après l'exécution🎜 🎜🎜🎜🎜Réflexion : Pourquoi utiliser uniquement la récursivité dans get et non set 🎜🎜L'affectation doit également être obtenue en premier🎜🎜Résumé simple : 🎜🎜🎜vue2 (shallow responsive)🎜🎜 🎜🎜Traverser les données et utiliser DefineProperty Intercepter tous les attributs🎜🎜Lorsque l'utilisateur exploite la vue, l'intercepteur défini sera déclenché🎜🎜set modifie d'abord les données actuelles, puis notifie la montre, laissant la montre notifier la mise à jour de la vue🎜🎜View redessinez et obtenez à nouveau les données correspondantes auprès de get🎜🎜🎜 🎜vue3 (réactivité profonde) : 🎜🎜🎜🎜🎜Utilisez un proxy pour un proxy ; interceptez toute opération sur n'importe quel attribut de données (13 types), y compris la lecture et l'écriture d'attributs, ajouter des attributs, supprimer des attributs, etc. 🎜🎜🎜🎜 utiliser Reflect effectue une réflexion ; effectue dynamiquement des opérations spécifiques sur les propriétés correspondantes de l'objet proxy🎜🎜🎜🎜L'objet de réflexion (reflect) de l'objet proxy (proxy) doit coopérer avec chacun autre pour atteindre la réactivité🎜🎜🎜🎜La différence entre les deux🎜🎜Proxy Il peut détourner l'objet entier, tandis que Object.defineProperty ne peut détourner que les propriétés de l'objet, le premier peut atteindre la réactivité en renvoyant récursivement le proxy de la valeur correspondante ; à la propriété, alors que cette dernière nécessite une traversée approfondie de chaque propriété, et cette dernière est très peu conviviale pour les opérations sur les tableaux. 🎜🎜Pour plus de connaissances sur la programmation, veuillez visiter : 🎜Introduction à la programmation🎜 ! ! 🎜

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer