Vue3中新的API

常用的 Composition API(組合API)

setup

  1. Vue3.0新增的配置項划提,值為一個函數(shù)
  2. setup是所有Composition API的
  3. 組件中所用到的:數(shù)據(jù)王浴,方法等等丑蛤,均需要配置在setup函數(shù)中
  4. setup函數(shù)的兩種返回值:
    • 若返回是一個對象,對象中的屬性重绷,方法唬渗,在模板中均可以直接使用
    • 若返回一個渲染函數(shù),則可以自定義渲染內(nèi)容
  5. setup的兩個注意點:
    • setup的執(zhí)行時機:在beforeCreate之前執(zhí)行一次圃泡,this是undefined
    • setup的參數(shù):
      • props:值為對象,包含外部傳遞過來愿险,且組件內(nèi)部申明接收了的屬性
      • context:上下文對象
        • attrs:值為對象颇蜡,包含組件外部傳遞過來,但是沒有在props中配置中申明的屬性辆亏,相當于this.$attrs
        • slots:收到的插槽的內(nèi)容风秤,相當于this.$slots
        • emit:分發(fā)自定義時間的函數(shù),相當于this.$emit扮叨。(值得注意的是缤弦,Vue3中使用emit,需要使用emits去接收父組件傳過來的數(shù)據(jù)彻磁,和props
          差不多)
PS:
  1. 盡量不要與Vue2的配置項混用:
    • Vue2配置項(data,methods,computed...)中可以訪問到setup中的屬性碍沐,方法。
    • 但在setup中不能訪問到Vue2中的配置
    • 如果有重名兵迅,setup優(yōu)先
  2. setup函數(shù)不能是一個async函數(shù)(后面學習異步組件抢韭,也行薪贫,需要的是Suspense和異步組件引入的配合)恍箭,因為返回值不在是一個return的對象,而是promise瞧省,模板看不到return對象中的屬性
<template>
    <h1>{{name}}</h1>
    <button @click="sayHi"></button>
</template>
<script>
exprot default {
    name: 'App',
    setup(props,context) {
        const name = "景天" // 不是響應式的數(shù)據(jù)
        function sayHi() {
            console.log(`Hi,我是${name}`)
        }
        
        // 返回值是一個對象
        return {
            name,
            sayHi
        }
        
        // 返回值是一個渲染函數(shù)
        return () => h('h1','這是渲染函數(shù)渲染的內(nèi)容')
    }
}
</script>

ref函數(shù)

  1. 作用:定義一個響應式的數(shù)據(jù)扯夭,或者說是生成一個引用實現(xiàn)對象
  2. 語法:const xxx = ref(initValue)
    • 創(chuàng)建一個包含響應式數(shù)據(jù)的引用對象(reference對象)
    • JS中操作數(shù)據(jù)需要:xxx.value
    • 模板中讀取數(shù)據(jù):直接使用即可
PS:
  1. ref接收的數(shù)據(jù)可以是基本類型數(shù)據(jù),也可以是對象類型
  2. 基本類型的數(shù)據(jù):響應式是靠Object鞍匾。defineProperty()的get和set完成的
  3. 對象類型的數(shù)據(jù):內(nèi)部使用了reactive函數(shù)
<template>
    <h1>{{name}}</h1>
    <h1>{{age}}</h1>
    <button @click="sayHi"></button>
</template>
<script>
import {ref} from 'vue'
exprot default {
    name: 'App',
    setup() {
        const name = ref("景天") 
        const age = ref(18) 
        const job = ref({
            type: '前端'交洗,
            money:'30K'
        }) // 其實Vue3幫你調(diào)用了reactive函數(shù)
        // 在setup中訪問ref定義的基本數(shù)據(jù)類型的數(shù)據(jù),需要 .value才能拿到值
        function sayHi() {
            name.value = '飛蓬'
            age.value = '1000'
            job.value.money = '60K'
        }
        
        return {
            name,
            age,
            job,
            sayHi
        }
    }
}
</script>

reactive函數(shù)

  1. 作用:定義一個對象類型的響應式數(shù)據(jù)
  2. 語法:const 代理對象 = reactive(源對象) 參數(shù)是一個對象或者數(shù)組橡淑,返回一個代理對象(Proxy的實例對象构拳,簡稱proxy對象)
  3. reactive定義的響應式數(shù)據(jù)是深層次的
  4. 內(nèi)部基于ES6的Proxy實現(xiàn),通過代理對象操作源對象內(nèi)部數(shù)據(jù)
<template>
    <h1>{{name}}</h1>
    <h1>{{age}}</h1>
    <button @click="sayHi"></button>
</template>
<script>
import {ref, reactive} from 'vue'
exprot default {
    name: 'App',
    setup() {
        const name = ref("景天") 
        const age = ref(18) 
        const job = reactive({
            type: '前端'梁棠,
            money:'30K'
        }) 
        const hobby = ['抽煙', '喝酒', '燙頭']
        
        function sayHi() {
            name.value = '飛蓬'
            age.value = '1000'
            job.money = '60K'   // 不需要.value了
            hobby[0] = '吃飯'
        }
        
        return {
            name,
            age,
            job,
            hobby,
            sayHi
        }
        
        // ref定義的基本類型的數(shù)據(jù)都要.value取值置森,有點煩,我們可以換一種思路符糊,而且語義化
        const person = reactive({
            name: '景天',
            age: 18,
            jon: {
                type: '前端'凫海,
                money:'30K'
            },
            hobby: ['抽煙', '喝酒', '燙頭']
        })
        
        return {
            person
        }
    }
}
</script>

computed

簡寫和完整版寫法和Vue2都一樣,只是使用不一樣男娄,需要單獨引入使用行贪,變成了一個函數(shù)

<template>
    <h1><input v-model="firstName" /></h1>
    <h1><input v-model="lastName" /></h1>
    <div>{{fullName}}</div>
</template>
<script>
import {reactive,computed} from 'vue'
exprot default {
    name: 'App',
    setup() {
        const person = reactive({
            firstName + : '景天',
            lastName: 18,
        })
        // 或者可以綁定在person對象上
        // person.fullName = computed(()=>{
        let fullName = computed(()=>{
            // 簡寫形式漾稀,完整版的get和set和Vue2都一樣
            return person.firstName + person.lastName
        })
        
        return {
            person,
            fullName
        }
    }
}
</script>

watch

  • 和Vue2基本相似,配置是一樣的
  • 兩個坑:
    • 監(jiān)視reactive定義的響應式數(shù)據(jù)時:oldVal無法正確的獲取建瘫,強制開啟了深度監(jiān)視(deep配置無效)
    • 監(jiān)視reactive定義的響應式數(shù)據(jù)中的某個屬性(對象)時:deep配置有效
<template>
    <h1>{{num}}</h>
    <h1>{{msg}}</h>
</template>
<script>
import {ref,reactive,watch} from 'vue'
exprot default {
    name: 'App',
    setup() {
        let num = ref(0)
        let msg= ref('消息')
        let p = reactive({
            name: '景天',
            age: 18,
            a: {
                b: {
                    c: 100
                }
            }
        })
        
        // 1. 監(jiān)視ref所定義的一個響應式數(shù)據(jù)
        watch(num,(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        },{immediate:true})
        
         // 2. 監(jiān)視ref所定義的多個響應式數(shù)據(jù)
        watch([num,msg],(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        },{immediate:true})
        
        // 3. 監(jiān)視reactive所定義的一個響應式數(shù)據(jù)崭捍。
        // 注意:此處無法正確的獲得oldVal
        // 注意:強制開啟了深度監(jiān)視器(deep配置無效)
        watch(p,(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        },{deep:false}) // 此處的deep無效
        
        // 4. 監(jiān)視reactive所定義的一個響應式數(shù)據(jù)中的某個屬性。需要使用函數(shù)
        watch(()=>p.name,(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        })
        
        // 5. 監(jiān)視reactive所定義的一個響應式數(shù)據(jù)中的某些屬性啰脚。
        watch([()=>p.name,()=>p.age],(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        },{deep:false})
        
        // 特殊情況
        watch(()=>p.a,(newVal,oldVal)=> {
            console.log(newVal,oldVal)
        },{deep:true})      // 此處由于監(jiān)視的是reactive所定義的對象中的某個屬性(對象)缕贡,所以deep配置有效
        
        
        return {
            num,
            msg,
            p
        }
    }
}
</script>

watchEffect函數(shù)

  • watch:需要指明監(jiān)視的屬性,也要指明監(jiān)視的回調(diào)
  • watchEffect:不需要指明監(jiān)視哪個豎向拣播,監(jiān)視的回調(diào)中用到哪個屬性晾咪,就監(jiān)視那個屬性
  • watchEffect有點類似于computed:
    • computed注重的是計算出來的值,所以必須寫返回值
    • watchEffect更注重的是過程贮配,所以不需要寫返回值
<template>
    <h1>{{num}}</h>
    <h1>{{msg}}</h>
</template>
<script>
import {ref,reactive,watchEffect} from 'vue'
exprot default {
    name: 'App',
    setup() {
        let num = ref(0)
        let msg= ref('消息')
        let p = reactive({
            name: '景天',
            age: 18,
            a: {
                b: {
                    c: 100
                }
            }
        })
        
        watchEffect(()=> {
            const x1 = sum.value
            const x2 = age.value
            console.log('watchEffect調(diào)用了')
        })
        
        return {
            num,
            msg,
            p
        }
    }
}
</script>

toRef

  • 作用:創(chuàng)建一個ref對象谍倦,其value值指向另一個對象中的某個屬性,這樣才是響應式的
  • 語法:const name = toRef(person,'name')
  • 應用:要將響應式對象中的某個屬性單獨提供給外部使用
  • 擴展:toRefs和toRef功能一直泪勒,但是可以批量創(chuàng)建多個ref對象昼蛀,語法toRefs(person)
// 上面說過數(shù)據(jù)可以定義reactive,避免.value圆存。但是這樣的話叼旋,我們使用數(shù)據(jù)就要person.name這樣使用,那么可以試試這樣
return {
    ...toRefs(person)
}

其他Composition API

shallowReactive和shallowRef

  • shallowReactive:值處理對象最外層屬性的響應式(淺響應式)
  • shallowRef:只處理基本數(shù)據(jù)類型的響應式沦辙,處理基本類型數(shù)據(jù)夫植,和ref沒有區(qū)別,不進行對象的響應式處理
  • 什么時候使用油讯?
    • 如果有一個對象數(shù)據(jù)详民,結(jié)構比較淺,但變化時只是外層屬性變化陌兑,使用shallowReactive
    • 如果有一個對象數(shù)據(jù)沈跨,后續(xù)功能不會修改該對象中的屬性,而是生成新的對象來替換兔综,使用shallowRef

readonly和shallowReadonly

  • readonly:讓一個響應式數(shù)據(jù)變?yōu)橹蛔x(深只讀)
  • shallowReadonly:讓一個響應式數(shù)據(jù)變?yōu)橹蛔x(淺只讀)饿凛,只是最外層屬性值不讓改
  • 使用場景:不希望數(shù)據(jù)被改變時,比如別人定義的數(shù)據(jù)软驰,你使用涧窒,但是改了對別人有影響,你在使用的時候可以先使用readonly(person),這樣就不怕被改了碌宴。

toRaw和markRaw

  • toRaw:
    • 作用:將一個由reactive生成的響應式對象轉(zhuǎn)換為普通對象杀狡。toRaw(person)
    • 場景:用于讀取響應式對象對應的普通對象,對于這個普通對象的所有操作贰镣,不會引起頁面的更新
  • markRaw
    • 作用:標記一個對象呜象,使其永遠不會再成為響應式對象
    • 場景:
      1. 有些值不應該被設置為響應式的膳凝,如第三方庫
      2. 當渲染具有不可變數(shù)據(jù)的大列表時,跳過響應式轉(zhuǎn)換可以提高性能

customRef

  • 作用:創(chuàng)建一個自定義的ref恭陡,并對其依賴項跟蹤和更新觸發(fā)進行顯式控制蹬音。
demo:實現(xiàn)輸入數(shù)據(jù),防抖效果
<template>
    <input v-model="keyword">
    <div>{{keyword}}</div>
</template>
    
<script>
    import { customRef } from 'vue'
    export default {
        name: 'demo',
        setup() {
            // 自定義一個ref休玩,名稱為myRef
            function myRef(value,delay) {
                let timer
                // 使用vue的customRef去配置我們的myRef,參數(shù)為一個函數(shù)著淆,這個函數(shù)有兩個參數(shù)可以直接使用
                // track:
                // trigger:
                return customRef((track,trigger)=> {
                    // 要求必須返回一個對象,里面包含get和set
                    return {
                        get() {
                            // 通知vue追蹤value的變化
                            track()
                            return value
                        },
                        set(neValue) {
                            clearTimeout(timer)
                            timer = setTimeout(()=> {
                                value = newValue
                                // 通知vue去重新解析模板
                                trigger()
                            },delay)
                        }
                    }
                })
            }
        }
        
        let keyword = myRef('Hello',100)
        
        return {
            keyword
        }
    }
</script>

provide和inject在Vue3中的使用

  • 作用:實現(xiàn)祖孫組件間通信,即父組件定義拴疤,后面所有子代組件都能用
  • 套路:父組件有一個provide選項來提供數(shù)據(jù)永部,后代組件有一個inject選項來開始使用這些數(shù)據(jù)
// 祖組件
import {reactive} from 'vue'
setup() {
    let car = reactive({
        name: '奧迪',
        price: '100W'
    })
    provide('car',car)
}
// 后代組件
import {inject} from 'vue'
setup(props,context) {
    const car = inject('car')
    return {
        car
    }
}

響應式數(shù)據(jù)的判斷

  • isRef: 檢查一個值是不是一個ref對象
  • isReactive: 檢查一個對象是不是由reactive創(chuàng)建愛你的響應式代理
  • isReadonly: 檢查一個對象是不是由readonly創(chuàng)建的只讀代理
  • isProxy: 檢查一個對象是否是由ractive或者readonly方法創(chuàng)建的代理

Vue3中的新組件

Fragment

相當于一個虛擬的容器,在Vue中呐矾,每個組件苔埋,都需要有個根組件,但是在Vue3不需要蜒犯,其實是Vue3幫助我們調(diào)用了這個組件组橄,在我們的頁面上,不會渲染出來

Teleport

當我們的組件總有些內(nèi)容罚随,不想顯示在我們自己的組件中玉工,可以使用這個組件,比如我們有個彈窗淘菩,想顯示在body標簽中

// to這里支持標簽
// to支持css標簽
// <teleport to="body">
<teleport to="#main">
    <div class="dialog">
        這是一個對話框
    </div>
</teleport>

Suspense

試驗性

Suspense 是一個試驗性的新特性遵班,其API可能隨時會發(fā)生變動。特此聲明瞄勾,以便社區(qū)能夠為當前的實現(xiàn)提供反饋费奸。

生產(chǎn)環(huán)境請勿使用。

以上是官方的警告进陡!

  • 等待異步組件渲染一些額外的內(nèi)容,讓應用有更好的用戶體驗
  • <suspense> 組件有兩個插槽微服。它們都只接收一個直接子節(jié)點趾疚。default 插槽里的節(jié)點會盡可能展示出來。如果不能以蕴,則展示 fallback 插槽里的節(jié)點糙麦。
  • 這里就是之前說到setup的時候提到的,setup的返回值不能使用異步丛肮,但是如果像下面這樣使用異步函數(shù)引入子組件赡磅,那么子組件就可以使用異步了,像Promise宝与。
<template>
    <div>
        <Suspense>
            // 這兩個插槽名稱是固定的
            // defalut:這里面寫的就是我們正常要顯示的組件和代碼
            // fallback:這里寫的就是應急代碼焚廊,就是正常代碼沒有顯示的時候的代碼
            <template v-slot:defalut:>
                <Child/>
            </template>
            <template v-slot:fallback>
                <div>加載中...</div>
            </template>
        </Suspense>
    </div>
</template>
    
<script>
    // import Child from './component/Child.vue' // 平時使用的靜態(tài)引入
    
    // 下面這是異步引入
    import { defineAsyncComponent } from 'vue'
    const Child = defineAsyncComponent(()=> import('./component/Child.vue'))
    export default {
        name: 'app',
        components: {
            Child
        }
        setup() {
            
        }
    }
</script>
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冶匹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咆瘟,更是在濱河造成了極大的恐慌嚼隘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袒餐,死亡現(xiàn)場離奇詭異飞蛹,居然都是意外死亡,警方通過查閱死者的電腦和手機灸眼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門卧檐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人焰宣,你說我怎么就攤上這事泄隔。” “怎么了宛徊?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵佛嬉,是天一觀的道長。 經(jīng)常有香客問我闸天,道長暖呕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任苞氮,我火速辦了婚禮湾揽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笼吟。我一直安慰自己库物,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布贷帮。 她就那樣靜靜地躺著戚揭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撵枢。 梳的紋絲不亂的頭發(fā)上民晒,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音锄禽,去河邊找鬼潜必。 笑死,一個胖子當著我的面吹牛沃但,可吹牛的內(nèi)容都是我干的磁滚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼宵晚,長吁一口氣:“原來是場噩夢啊……” “哼垂攘!你這毒婦竟也來了维雇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搜贤,失蹤者是張志新(化名)和其女友劉穎谆沃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仪芒,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡唁影,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了掂名。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片据沈。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饺蔑,靈堂內(nèi)的尸體忽然破棺而出锌介,到底是詐尸還是另有隱情,我是刑警寧澤猾警,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布孔祸,位于F島的核電站,受9級特大地震影響发皿,放射性物質(zhì)發(fā)生泄漏崔慧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一穴墅、第九天 我趴在偏房一處隱蔽的房頂上張望惶室。 院中可真熱鬧,春花似錦玄货、人聲如沸皇钞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夹界。三九已至,卻和暖如春惩坑,著一層夾襖步出監(jiān)牢的瞬間掉盅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工以舒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人慢哈。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓蔓钟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親卵贱。 傳聞我的和親對象是個殘疾皇子滥沫,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容