? 在這里我會用通俗易懂的語言和淺層次的原理來幫助學習Vue的小伙伴去理解ref函式和reactive函式和二者的區別以及其回應式原理,幫助大家少走彎路,這里對于不會描述底層核心代碼,想了解底層原理的小伙伴可以去看上篇,
ref函式:
語法:const xxx = ref (initValue)
接受的資料型別:基本型別,物件型別
作用:把引數加工成一個回應式物件,全稱為reference物件(我們下面一律簡稱為ref物件)
核心原理:回應式依賴Object.defineProperty( )的get( )和set( )
Ref函式對于基本資料型別的引數
-
基本使用
<template>
<h2>{{Str}}</h2>
</template>
<script>
import {ref} from 'vue'
export default {
setup(){
const Str =ref('hello')
return{
Str
}
}
}
這里我們定義了一個Str變數來接收ref加工生成的ref物件,我們都知道物件的資料都是以鍵值對的形式存盤的,但是在這里為什么直接把Str給return出去,
并且模板里可以直接寫Str這個物件呢,我們的源資料呢?帶著這個疑問我們來輸出一下Str
setup(){
const Str =ref('hello')
console.log(Str)
return{
Str
}
}
列印結果如下:
RefImpl
__v_isRef: true
_rawValue: "hello"
_shallow: false
_value: "hello"
value: "hello"
[[Prototype]]: Object
在這里我們看到了ref物件身上的一個屬性 value,沒錯,我們存入的值就對應在value屬性上,至于為什么直接return出是Str而不是Str.value ,是因為Vue幫了我們
一個忙,我們在這里可以簡寫,return出去的Str 就相當于Str.value ,當然 非要寫.value的形式也不是不可以,不過這里需要注意的是,在
setup函式中操作Str中的資料不可以簡寫,
-
回應式原理
對于基本資料型別說完了它的基本用法,下面我們來說說他的回應式原理,也就是我們為什么非要用一個ref物件來接受資料,而不是直接就定義好一個字符
串‘hello’然后去直接操作這個字串?
對于ref函式,資料引數和它加工生成的ref物件二者存在著某種“契約”,我們把加工好的引數也就是ref物件交出去之后,我們直接操作修改的就是ref
物件上的value屬性,因為這個契約的存在,以至于在修改屬性值的時候對應的源資料引數也會連同被修改,但在原資料被修改之前vue就會監聽到我
們修改了資料,立馬進行決議模板更新頁面,這就是ref物件的回應式原理,這里的契約其實就是Object.defineProperty的get( )和set( )篇幅有
限我們不對底層核心代碼做示范.
我們知道了ref函式定義基本型別,下面會講解reactive函式,該函式引數是物件型別和ref的物件型別引數有著千絲萬縷的聯系,所以學會reacti
ve函式學會了ref函式存盤的物件資料型別也就自然理解了,
reactive函式:
語法:const xxx = ref (源物件)
接受的資料型別:物件型別
作用:把引數加工成一個代理物件,全稱為proxy物件
核心原理:基于Es6的Proxy實作,通過代理操作源物件,相比于reactive定義的淺層次回應式資料物件,reactive定義的是更深層次的回應式資料物件
reactive對于物件型別的引數
-
基本使用
<template> <h2>姓名:{{Person.name}}</h2> <h2>薪水:{{Person.job.salary}}</h2> </template> <script> import {reactive} from 'vue' export default { setup(){ const p ={ name:'Ben', job:{ salary:'30k' } } const Person =reactive(p) return{ Person } } } 這里不同于上面的ref函式,引數是一個物件型別的資料,那么對于接受回傳值的Person物件也會和上面的ref物件一樣都是把資料對應到value屬性上嗎? 帶著這個疑問列印一下Person物件 Proxy [[Handler]]: Object [[Target]]: Object job: {salary: "30k"} name: "Ben" [[Prototype]]: Object [[IsRevoked]]: false 我們發現Person物件身上并沒有value屬性并且Person物件是一個proxy型別的物件,這里我們可以理解為Person是一個加強版的p物件,對于p來說Person是一個代理物件,所以我們可以 直接訪問到自身的屬性,而不是和ref函式一樣把資料對應到value屬性上,所以我們return出去的Person物件可以直接放在模板里讀取屬性 -
回應式原理
reactive的回應式是更加“深層次”的,底層依賴于ES6中的Proxy實作,用reactive函式加工出來的物件都是Proxy物件,無論原資料物件里面有多少層物件他們都會被加工成Proxy 型別物件(深層次),它的回應式核心思想和ref是大同小異的,這里我們定義的Person物件來代理p物件,二者也會建立“契約”,我們在把Person物件return出去 后在我們操作修改Person物件的資料時,在原物件資料改變之前Vue都會監聽到這一舉動并且同時決議模板、更新頁面,
Ref函式對于物件型別的引數
說到這里大家會有個疑問,ref定義物件型別的資料和這個reactive函式有什么關系呢?
ref物件只能去操作淺層次的資料,把基本資料型別當做自己的屬性值,如果ref函式的引數是物件這種深層次的資料型別時它會求助一個人,這個人不是別人正是reactive函式,在底層Vue會把物件引數通過reactive函式加工成一個Proxy代理物件放到ref的value屬性上
<template>
<h2>姓名:{{Person.name}}</h2>
<h2>薪水:{{Person.job.salary}}</h2>
</template>
<script>
import {reactive,ref} from 'vue'
export default {
setup(){
const p ={
name:'Ben',
job:{
salary:'30k'
}
}
const Person =ref(p)
console.log(Person)
return{
Person
}
}
}
列印Person物件的結果:
RefImpl {_shallow: false, __v_isRef: true, _rawValue: {…}, _value: Proxy}
__v_isRef: true
_rawValue: {name: "Ben", job: {…}}
_shallow: false
_value: Proxy {name: "Ben", job: {…}}
value: Proxy
[[Handler]]: Object
[[Target]]: Object
job: {salary: "30k"}
name: "Ben"
[[Prototype]]: Object
[[IsRevoked]]: false
[[Prototype]]: Object
我們可以很清楚的看到,value屬性下對應的正是給p原資料物件加工生成Proxy物件
區別:
1.存盤型別:ref物件可以接受基本資料型別得資料也可以接受物件型別的資料,而reactive只可以接受物件型別的資料
2.回應式:相比于ref物件reactive函式是更深層次的,ref函式引數為物件型別時依賴的也是reactive函式
3.用法:Proxy代理物件的資料鍵值對是和原資料物件的鍵值對一一對應的,在使用時可以直接使用 物件(接受回傳值的物件).鍵名 的形式,ref物件會把資料引數對應到自己
value屬性上,在模板里我們可以直接省略.value的形式,這看起來好像是“把源資料賦值給了ref型別的變數,可以直接在模板上使用這個ref型別的變數”
4.回應式原理:ref的回應式原理是依賴于Object.defineProperty( )的get( )和set( )而reactive的回應式原理是依賴于ES6中的Proxy,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/296906.html
標籤:其他
