vue でのレスポンシブ データの実装と、reactive、ref、toRef、および toRefs の違い

目次

1. Vue2 は Object.defineProperty を渡します

2、プロキシ経由の vue3

3. リアクティブ、ref、toRef、toRefs の違い


1. Vue2 は Object.defineProperty を渡します 

1.1、単一の属性を監視する

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、オブジェクトを監視する

  obj オブジェクトに値を代入する場合は、無限ループに注意してください。


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方法,相当于递归,会形成死循环

  外部で定義できる set メソッドや get メソッドでの再帰を回避するための改善

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

2、プロキシ経由の vue3

vue3 の実装はよりエレガントです

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. リアクティブ、ref、toRef、toRefs の違い

公式ドキュメント: Refs | Vue.js

受け入れる 戻る
反応性 オブジェクトタイプ レスポンシブ オブジェクト(プロキシ オブジェクト)
参照

基本データ型

(オブジェクト型の場合はリアクティブ関数が呼び出されます)

.valueプロパティを持つレスポンシブで変更可能な ref オブジェクトを返します

toRef と toRefs

同じ:

  • toRef と toRefs は、レスポンシブ オブジェクトのプロパティをレスポンシブに変換します。
  • ソース オブジェクトへのレスポンシブ リンクは失われません。つまり、ソース オブジェクトのプロパティ値が変更された場合、生成された新しいオブジェクトの対応するプロパティ値 (ref) も変更され、その逆も同様です。

違い:

  • toRef: ソース オブジェクトと属性名の 2 つのパラメーターを受け取り、ref データを返します。
  • toRefs: すべてのプロパティを一度にレスポンシブに変換します。レスポンシブ オブジェクトの分解によく使用されます。

:

データに対して ref 操作のみを実行した場合、得られるのはデータのコピーです。結果データの値を変更してもソース オブジェクトの値は変更されませんが、toRef または toRefs を介して取得されるのはデータ参照です。

おすすめ

転載: blog.csdn.net/qq_41045128/article/details/125944134