Home  >  Article  >  Web Front-end  >  Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples)

Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples)

WBOY
WBOYforward
2021-12-22 18:25:282254browse

This article brings you the relevant knowledge of vue2&vue3 data responsiveness principle analysis and manual implementation. The data responsive view and data are automatically updated. When the data is updated, the view is automatically updated to track the changes in the data. I hope everyone has to help.

Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples)

Data responsiveness

  • The view and data are automatically updated, and the view is automatically updated when the data is updated
  • Tracking data changes, you can perform some hijacking operations when reading or setting data
  • vue2 Use defineProperty
  • vue3 Use Proxy instead

Using defineProperty

How to track changes

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 ...

The object obj will call the get method of data hijacking when getting the age attribute
When assigning a value to the age attribute, the set method will be called

How to use Object.defineProperty to implement a data response?

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))

This function defineReactve is used to encapsulate Object.defineProperty. From the function name, you can It can be seen that the function is to define a responsive data. After encapsulation, you only need to pass the data, key and val
The track function is triggered whenever the key is read from the data, and when the data is set to the key of the data, set The trigger function in the function triggers

The responsiveness of the array

We change the content of the array through the method on the Array prototype and it will not trigger the getter and setter
After sorting it out, we found that it can be done in the Array prototypeThere are 7 methods to change the content of the array itself, respectively push pop shift unshift splice sort reverse
vue2 rewrites these 7 methods
Implementation method:
Create an arrayMethods object based on Array.propertype as the prototype, and then use Object.setPropertypeOf(o, arryMethods)Point o's __proto__ to arrayMethods

Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples)

How to collect dependencies

Use

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

Data used in this templatename, we need to observe the data, when the properties of the data change, we can notify the places where it is used,
This is why we need to collect dependencies first, that is, use Collect it at the data name, and then when the data changes, trigger the previously collected dependency loop. In summary, it is to collect dependencies in the getter and trigger the dependencies in the setter

Use proxy

Proxy object is used to create a proxy for an object, thereby realizing the interception and definition of basic operations (such as attribute search, assignment, enumeration, function deactivation, etc.)

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

  • The target object to be wrapped with Proxy (can be any type of object, including a native array, a function, or even another proxy) .

  • handler

  • An object that usually has functions as attributes. The functions in each attribute are respectively defined during execution. The behavior of p during various operations.
    reflect is a built-in object that provides methods to intercept JavaScript operations. These methods are the same as Proxy handlers

##Reflect.set function that assigns values ​​to properties. Returns a Boolean and returns true if the update is successful

Reflect.get gets the value of a certain attribute on the object, similar to target[name]

How to implement hijacking

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)
In the code The dinner object is proxied to the handler.

The difference between
defineProperty
defineProperty's properties need to be traversed to supervise all properties

Using proxy can all properties of the object be processed Proxy

Use proxy to implement a simulated response

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)
Automatically print after execution

Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples)

Thinking: Why only use recursion in get , what if set is not used?

Assignment also requires get first

Simple summary:

    vue2 (shallow responsiveness)
    Traverse the data and use defineProperty to intercept all properties
  • When the user operates the view, the set interceptor will be triggered
  • set first changes the current data, then notifies the wartch, and lets the watch notify the view update
  • Redraw the view and obtain the corresponding data from get again
    vue3 (deep responsiveness):
  • Use proxy for proxy; intercept any operation of any attribute of data (13 types), including reading and writing attributes, adding attributes, deleting attributes, etc.

  • Use Reflect for reflection; Dynamically perform specific operations on the corresponding properties of the proxy object

  • The reflection object (reflect) of the proxy object (proxy) must cooperate with each other to achieve responsiveness

The difference between the two

Proxy can hijack the entire object, while Object.defineProperty can only hijack the properties of the object; the former can achieve responsiveness by recursively returning the proxy of the value corresponding to the property, while the latter requires Deeply traverse each attribute, the latter is very unfriendly to array operations.

For more programming-related knowledge, please visit:

Introduction to Programming! !

The above is the detailed content of Vue2&vue3 data responsive principle analysis and manual implementation (detailed examples). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete