書畫網(wǎng)站 建設(shè)方案室內(nèi)設(shè)計(jì)培訓(xùn)
文章目錄
- 一、reactive()
- 二、readonly()
- 三、shallowReactive()
- 四、shallowReadonly()
- 五、isReactive() 和 isReadonly()
- 六、toRef()
- 七、toRefs()
- 八、toRaw()
- 九、ref、toRef、toRefs 異同點(diǎn)
一、reactive()
reactive() 函數(shù)用于返回一個(gè)對(duì)象的響應(yīng)式代理。與 ref() 函數(shù)定義響應(yīng)式數(shù)據(jù)的異同點(diǎn)如下:
數(shù)字化管理平臺(tái)
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
權(quán)限系統(tǒng)-商城
個(gè)人博客地址
-
ref 函數(shù)和 reactive 函數(shù)都是用來定義響應(yīng)式數(shù)據(jù)的。
-
ref 函數(shù)更適合定義基本數(shù)據(jù)類型(可接收基本數(shù)據(jù)類型和對(duì)象)
-
函數(shù)參數(shù)可以是基本數(shù)據(jù)類型,也可以接受對(duì)象類型
-
如果參數(shù)是對(duì)象類型時(shí),其實(shí)底層的本質(zhì)還是 reactive,系統(tǒng)會(huì)自動(dòng)給 ref 傳入的值進(jìn)行轉(zhuǎn)換
ref(1) -> reactive({value:1}) // ref函數(shù)只能操作淺層次的數(shù)據(jù),把基本數(shù)據(jù)類型當(dāng)作自己的屬性值;深層次依賴于reactive
-
在 template 中訪問,系統(tǒng)會(huì)自動(dòng)添加
.value
。在 js 中需要手動(dòng).value
進(jìn)行訪問import { ref } from 'vue'// 為基本數(shù)據(jù)類型添加響應(yīng)式狀態(tài) const name = ref('Neo')// 為復(fù)雜數(shù)據(jù)類型添加響應(yīng)式狀態(tài) const state = ref({count: 0 })// 打印name的值 console.log(name.value) // 打印count的值 console.log(state.value.count)
-
ref 響應(yīng)式原理是依賴于
Object.defineProperty()
的get()
和set()
的
-
-
reactive 函數(shù)更適合定義復(fù)雜的數(shù)據(jù)類型(json/arr/obj/map/set)
-
它的響應(yīng)式是更加‘深層次’的(會(huì)影響對(duì)象內(nèi)部所有嵌套的屬性,所有的數(shù)據(jù)都是響應(yīng)式的),底層本質(zhì)是將傳入的數(shù)據(jù)包裝成一個(gè) JavaScript Proxy,其行為表現(xiàn)與一般對(duì)象相似。不同之處在于 Vue 能夠跟蹤對(duì)響應(yīng)式對(duì)象屬性的訪問與更改操作。因此不等于源對(duì)象,建議只使用響應(yīng)式代理,避免使用原始對(duì)象。
import { reactive } from 'vue'let list = reactive([]) const addData = () => {setTimeout(() => {let arr = ['banana','orange','peal']list.push(...arr)console.log(list)},1000) }
-
參數(shù)必須是對(duì)象或者數(shù)組,如果要讓對(duì)象的某個(gè)元素實(shí)現(xiàn)響應(yīng)式時(shí)比較麻煩。需要使用 toRefs 函數(shù)處理
import { reactive, toRefs } from 'vue'// 通過 reactive 定義響應(yīng)式數(shù)據(jù) const state = reactive({// 定義每一個(gè)表單控件的配置項(xiàng):type類型、label文本、prop綁定字段 等信息items: [{label: "用戶名",prop: "name",inputwidth: "100%",}, {password: true,label: "密碼",prop: "pwd",inputwidth: "100%",rules: [{ required: true, message: "請(qǐng)輸入密碼", trigger: 'blur' }]}, {label: "手機(jī)號(hào)",prop: "phone",inputwidth: "100%",required: true,validateType: "phone"}],// 定義每一個(gè)表單綁定字段對(duì)應(yīng)的信息(form表單數(shù)據(jù)信息)formData: {name: "",pwd: "",phone: ""},// form 元素配置信息options: {size: "small",formWidth: "35%",//表單占父元素的寬度labelWidth: "80px",//標(biāo)簽的長(zhǎng)度}, })// 通過 toRefs 獲取 reactive 中的每一項(xiàng)屬性的引用(js中調(diào)用使用 .value,template 中直接使用自動(dòng)解析) const { items, formData, options } = toRefs(state);console.log(items,options)
-
獲取數(shù)據(jù)值的時(shí)候直接獲取,不需要加.value
import { reactive } from 'vue'// 響應(yīng)式狀態(tài) const state = reactive({count: 0 })// 打印count的值 console.log(state.count)
-
二、readonly()
readonly() 函數(shù)接受一個(gè)對(duì)象 (不論是響應(yīng)式還是普通的) 或是一個(gè) ref,返回一個(gè)原值的只讀代理。本身不能去修改值,但受原始對(duì)象改變的影響。
import { readonly } from "vue"let obj = reactive({name:"Jack"})let readObj = readonly(obj)const change = () => {// 不能直接修改只讀屬性// readObj.name = "Lucy";// 受原始對(duì)象改變的影響obj.name = "David";console.log(obj,readObj);
}
只讀代理是深層的:對(duì)任何嵌套屬性的訪問都將是只讀的。它的 ref 解包行為與
reactive()
相同,但解包得到的值是只讀的。
三、shallowReactive()
reactive()
的淺層作用形式。和 reactive()
不同,這里沒有深層級(jí)的轉(zhuǎn)換:一個(gè)淺層響應(yīng)式對(duì)象里只有根級(jí)別的屬性是響應(yīng)式的。屬性的值會(huì)被原樣存儲(chǔ)和暴露,這也意味著值為 ref 的屬性不會(huì)被自動(dòng)解包了。
import { reactive,shallowReactive } from "vue";const stu = reactive({name:"Jack"})const obj = shallowReactive({foo:{bar:{num:1}}
})const change = () => {// reactive() 作用是深層次的,和shallowReactive() 一起使用時(shí),會(huì)影響其數(shù)據(jù)變化stu.name = "David"// shallowReactive() 作用是淺層的,只能修改第一層的數(shù)據(jù)。深層次數(shù)據(jù)無法修改。但是會(huì)受reactive數(shù)據(jù)修改的影響。obj.foo.bar.num = 1000;console.log(obj)
}
四、shallowReadonly()
readonly()
的淺層作用形式。和 readonly()
不同,這里沒有深層級(jí)的轉(zhuǎn)換:只有根層級(jí)的屬性變?yōu)榱酥蛔x。屬性的值都會(huì)被原樣存儲(chǔ)和暴露,這也意味著值為 ref 的屬性不會(huì)被自動(dòng)解包了。同樣會(huì)受原始對(duì)象數(shù)據(jù)改變的影響。
const state = shallowReadonly({foo: 1,nested: {bar: 2}
})// 更改狀態(tài)自身的屬性會(huì)失敗
state.foo++// ...但可以更改下層嵌套對(duì)象
isReadonly(state.nested) // false// 這是可以通過的
state.nested.bar++
五、isReactive() 和 isReadonly()
- isReactive() 函數(shù)檢查一個(gè)對(duì)象是否是由
reactive()
或shallowReactive()
創(chuàng)建的代理。 - isReadonly() 函數(shù)檢查傳入的值是否為只讀對(duì)象。只讀對(duì)象的屬性可以更改,但他們不能通過傳入的對(duì)象直接賦值。
數(shù)字化管理平臺(tái)
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
權(quán)限系統(tǒng)-商城
個(gè)人博客地址
六、toRef()
toRef() 函數(shù)基于響應(yīng)式對(duì)象上的一個(gè)屬性,創(chuàng)建一個(gè)對(duì)應(yīng)的 ref。這樣創(chuàng)建的 ref 與其源屬性保持同步:改變?cè)磳傩缘闹祵⒏?ref 的值,反之亦然。
toRef() 函數(shù)一次僅能設(shè)置一個(gè)數(shù)據(jù),接收兩個(gè)參數(shù),第一個(gè)參數(shù)是哪個(gè)對(duì)象,第二個(gè)參數(shù)是對(duì)象的哪個(gè)屬性。
<script setup>const state = reactive({title: '標(biāo)題',name: 'wff'})const name = toRef(state, 'name')console.log(state.name)console.log(name.value)
</script><template><div>name:{{name}}</div>
</template>
七、toRefs()
toRefs() 函數(shù)將一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)換為一個(gè)普通對(duì)象,這個(gè)普通對(duì)象的每個(gè)屬性都是指向源對(duì)象相應(yīng)屬性的 ref。
<script setup>const state = reactive({title: '標(biāo)題',name: 'wff'})const { title } = toRefs(state)console.log(state.title)console.log(title.value)
</script><template><div>title:{{title}}</div>
</template>
注:我們使用
reactive
創(chuàng)建的對(duì)象,如果想在模板中使用,就必須得使用xxx.xxx
的形式;如果大量用到的話還是很麻煩的,但是使用es6
解構(gòu)以后,會(huì)失去響應(yīng)式。那么toRefs
的作用就體現(xiàn)在這,利用toRefs
可以將一個(gè)響應(yīng)式reactive
對(duì)象的所有原始屬性轉(zhuǎn)換為響應(yīng)式的ref
屬性。
八、toRaw()
toRaw() 函數(shù)可以返回由 reactive()
、readonly()
、shallowReactive()
或者 shallowReadonly()
創(chuàng)建的代理對(duì)應(yīng)的原始對(duì)象(將響應(yīng)式對(duì)象轉(zhuǎn)化為普通對(duì)象)。
這是一個(gè)可以用于臨時(shí)讀取而不引起代理訪問/跟蹤開銷,或是寫入而不觸發(fā)更改的特殊方法。不建議保存對(duì)原始對(duì)象的持久引用,請(qǐng)謹(jǐn)慎使用。
const foo = {}
const reactiveFoo = reactive(foo)console.log(toRaw(reactiveFoo) === foo) // true
九、ref、toRef、toRefs 異同點(diǎn)
-
ref、toRef、toRefs 函數(shù)都可以將某個(gè)對(duì)象中的屬性變成響應(yīng)式數(shù)據(jù)
-
ref 函數(shù)的本質(zhì)是拷貝,修改響應(yīng)式數(shù)據(jù),不會(huì)影響到原始數(shù)據(jù)(引用數(shù)據(jù)類型會(huì)有影響),視圖會(huì)更新
-
toRef、toRefs 函數(shù)和傳入的數(shù)據(jù)形成引用關(guān)系,修改 toRef 會(huì)影響這些數(shù)據(jù),但是不會(huì)更新視圖
作用:把一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)換成普通對(duì)象,該普通對(duì)象的每個(gè)屬性都是一個(gè)
ref
- toRef 函數(shù)一次僅能設(shè)置一個(gè)數(shù)據(jù),接收兩個(gè)參數(shù),第一個(gè)參數(shù)是哪個(gè)對(duì)象,第二個(gè)參數(shù)是對(duì)象的哪個(gè)屬性
- toRefs 函數(shù)接收一個(gè)對(duì)象作為參數(shù),它會(huì)遍歷對(duì)象身上的所有屬性,然后挨個(gè)調(diào)用 toRef 執(zhí)行。用于批量設(shè)置多個(gè)數(shù)據(jù)為響應(yīng)式
-
ref 數(shù)據(jù)會(huì)引起監(jiān)聽行為,而 toRef 不會(huì)