The implementation of responsive data in vue and the difference between reactive, ref, toRef, and toRefs

Table of contents

1. Vue2 passes Object.defineProperty

Two, vue3 through Proxy

3. The difference between reactive, ref, toRef, and toRefs


1. Vue2 passes Object.defineProperty 

1.1, monitor a single attribute

var obj={
    a:1,
    b:'字符串b'
}
var obj2

Object.defineProperty(obj,'a',{
    get:()=>{
        console.log('触发get')
        return 'aaa'
    },
    set:(v)=>{
        console.log("触发set")
        obj2=v
    }
})
console.log('obj2初始:',obj2)   // obj2初始: undefined
obj.a                          // 触发get
obj.a = 3                      // 触发set,
console.log('obj2现:',obj2)     // obj2现: 3
console.log('obj.a:',obj.a)     //触发get   obj.a: aaa     //set中无返回值,所以obj.a = 3 本质是对obj2 进行赋值

1.2, monitor the object

  When you want to assign a value to the obj object, be careful of an infinite loop.


var obj={
    a:1,
    b:'字符串b'
}
var obj2

Object.keys(obj).forEach(k=>{
    Object.defineProperty(obj,k,{
    get:()=>{
        console.log('触发get')
        return 'aaa'
    },
    set:(v)=>{
        console.log("触发set")
        return obj[k]=v   
    }
})
})

obj.b = 'ss'   //结果会重复打印“触发set” --由于set中也调用了 obj的set方法,相当于递归,会形成死循环

  Improvement to avoid recursion in the set or get method, which can be defined externally

var obj={
    a:1,
    b:'字符串b',
    c:[],
    d:{
        name:'eee'
    }
}

function definePropertyFun(data,key,val){
    if(Object.prototype.toString.call(val)==='[object Object]'){
        observer(val)
        return 
    }
    Object.defineProperty(data,key,{
    get:()=>{
        console.log('触发get')
        return val
    },
    set:(v)=>{
        console.log("触发set")
        return val=v
    }
})
}

function observer(data){
    if(Object.prototype.toString.call(data) !=='[object Object]'){
        console.log('传参要是对象类型')
        return 
    }

    Object.keys(data).forEach( k => {
        definePropertyFun(data,k,data[k])
    })
}

observer(obj)   //对对象进行监听
obj.a=5         // 触发set
console.log(obj.a);  // 触发get   5

obj.c = [0,1]   // 触发set
obj.c[1]=2      // 触发get      无法触发 set ,vue2中也无法触发set
obj.c.push(3)   // 触发get      vue2可以触发set,它对push进行了重写

obj.d.name = 's' // 触发set

Two, vue3 through Proxy

The implementation of vue3 is more elegant

var obj={
    a:1,
    b:'字符串b',
    c:[],
    d:{
        name:'eee'
    }
}
var obj2='d'

const newobj = new Proxy(obj,{
    get:(data,val)=>{
        console.log('触发get')
        return data[val]
    },
    set:(data,key,val)=>{
        console.log("触发set")
        return data[key]=val  
    }

})

newobj.a           //触发get 
newobj.c.push(3)   //触发get   
newobj.d.name      //触发get    
newobj.p="ds"      //触发set   原本不存在的属性也可以

3. The difference between reactive, ref, toRef, and toRefs

Official Documentation: Refs | Vue.js

accept return
reactive object type Responsive object (proxy object)
ref

basic data type

(If it is an object type, the reactive function will be called)

Returns a responsive and mutable ref object with a .value property

toRef and toRefs

same:

  • toRef and toRefs convert the properties in the responsive object to responsive.
  • The responsive link to the source object is not lost, that is, if the property value of the source object is modified, the corresponding property value (ref) of the generated new object will also be modified, and vice versa.

the difference:

  • toRef: accepts two parameters, the source object and the attribute name, and returns a ref data
  • toRefs: Convert all properties to responsive at one time. Often used for destructuring of responsive objects

Note :

If only the ref operation is performed on the data, what is obtained is a copy of the data. Changing the value of the result data will not change the value of the source object, but what is obtained through toRef or toRefs is the data reference

Guess you like

Origin blog.csdn.net/qq_41045128/article/details/125944134