Vue3 學(xué)習(xí)筆記 —Vue3 的Setup 如何實(shí)現(xiàn)響應(yīng)式功能?
setup 是用來寫組合式 api ,內(nèi)部的數(shù)據(jù)和方法需要通過 return 之后,模板才能使用。在之前 vue2 中,data 返回的數(shù)據(jù),可以直接進(jìn)行雙向綁定使用,如果我們把 setup 中數(shù)據(jù)類型直接雙向綁定,發(fā)現(xiàn)變量并不能實(shí)時響應(yīng)。接下來就看看setup如何實(shí)現(xiàn)data的響應(yīng)式功能?
一、ref
setup 內(nèi)的自定義屬性不具備響應(yīng)式能力,所以引入了 ref ,ref 底層通過代理,把屬性包裝值包裝成一個 proxy ,proxy 內(nèi)部是一個對象,使得基礎(chǔ)類型的數(shù)據(jù)具備響應(yīng)式能力,使用之前必須引入。
示例1:ref 使用
- <template>
- <div>
- <input type="text" v-model="mood">
- {{mood}}
- </div>
- </template>
- <script>
- import { ref } from "vue"
- export default{
- setup(){
- let mood = ref("此時心情好差呀!")
- setTimeout(()=>{
- mood.value = "心情要變的像人一樣美"
- },3000)
- return{
- mood
- }
- }
- }
- </script>
此時可以在 setup 模板內(nèi)任意編輯 mood,可以保證實(shí)時響應(yīng)。實(shí)例在修改 mood 的值加了 value ,是因?yàn)?ref 的工作原來:
let mood = ref("此時心情好差呀!")
修改成 :let mood = proxy({value:"此時心情好差呀!"})
二、reactive
上述的 ref 讓基礎(chǔ)數(shù)據(jù)類型具備了響應(yīng)式,但是如果我們換成引用類型的數(shù)據(jù),就會失效。所以引入了 reactive。
reactive 通過底層包裝,將引用類型數(shù)據(jù)包裝到 proxy 內(nèi),使用原理如:
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- // 運(yùn)行結(jié)果為
- let me = proxy : { single: true, want:"暖的像火爐的暖男" }
引用的時候,直接使用 me.want 就可以了。
示例2:reactive 使用
- <template>
- <div>
- {{me.want}}
- </div>
- </template>
- <script>
- import { ref , reactive } from "vue"
- export default{
- setup(){
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- setTimeout(()=>{
- me.want = "夏天容易化了"
- },3000)
- return{
- me
- }
- }
- }
- </script>
通過 setup + ref + reactive 就可以完全實(shí)現(xiàn) vue2 中 data 的響應(yīng)式功能,所以 setup 完全可以替換掉 data。
三、toRefs 、toRef 應(yīng)用
setup + ref + reactive 實(shí)現(xiàn)了數(shù)據(jù)響應(yīng)式,不能使用 ES6 解構(gòu),會消除響應(yīng)特性。所以需要 toRefs 解構(gòu),使用時,需要先引入。
它的工作原理為:
- import { ref , reactive, toRefs } from "vue"
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- //運(yùn)行為
- let me = proxy : { single: true, want:"暖的像火爐的暖男" }
- const { single, want } = toRefs( me )
- // 運(yùn)行為
- single : proxy({ value:true })
- want : proxy({ value:"暖的像火爐的暖男" })
toRefs 把 single 和 want 解構(gòu)成兩個 proxy ,所以是響應(yīng)式的。
示例3:toRefs 解構(gòu)數(shù)據(jù)
- <template>
- <div>
- {{want}}
- <input type="text" v-model="want">
- </div>
- </template>
- <script>
- import { ref , reactive, toRefs } from "vue"
- export default{
- setup(){
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- setTimeout(()=>{
- me.want = "夏天容易化了"
- },3000)
- // 解構(gòu)
- const {single,want} = toRefs(me)
- return{
- single,
- want
- }
- }
- }
- </script>
toRef作用:將對象某一個屬性,作為引用返回。比較難理解,可以打印查看下結(jié)果更容易理解。
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- let lv = toRef( me, 'love' )
- console.log('love',love);
- //打印結(jié)果
- ObjectRefImpl {
- __v_isRef: true
- _key: "love"
- _object: Proxy {single: true, want: "暖的像火爐的暖男"}
- value: undefined
- [[Prototype]]: Object
- }
toRef 是組件之間進(jìn)行傳值值,對可選參數(shù)進(jìn)行處理,運(yùn)行時,先查看 me中是否存在 love ,如果存在時就繼承 me 中的 love ,如果不存在時就創(chuàng)建一個 love ,然后解構(gòu)賦值給變量 lv。
示例4:toRef 使用
- <template>
- <div>
- {{want}}
- <input type="text" v-model="want">
- </div>
- </template>
- <script>
- import { ref , reactive, toRefs, toRef } from "vue"
- export default{
- setup(){
- let me = reactive({
- single:true,
- want:"暖的像火爐的暖男"
- })
- setTimeout(()=>{
- me.want = "夏天容易化了"
- },3000)
- const {single,want } = toRefs(me)
- const love = toRef(me,'love')
- console.log('love',love);
- return{
- single,
- want
- }
- }
- }
- </script>
四、總結(jié)
ref 讓基礎(chǔ)數(shù)據(jù)類型具備響應(yīng)式,而 reactive 讓引用類型的數(shù)據(jù)具備響應(yīng)式。setup + ref + reactive 完全實(shí)現(xiàn) vue2 中 data 響應(yīng)式功能。
toRefs 解構(gòu) reactive 包裝的數(shù)據(jù),toRef 用于對可選參數(shù)。