Vue3 組合式API.md

組合式API

介紹

什么是組合式 API(composition API)

  • 組合式 API 是 Vue3 提供的新功能永淌,為我們提供了另一種編寫(xiě)組件的方式
  • 代碼共享。在 setup 鉤子里面佩耳,可以按邏輯上的關(guān)注點(diǎn)來(lái)對(duì)代碼進(jìn)行分組遂蛀,并與其他組件共享代碼。

組合式 API 的出現(xiàn)解決了什么樣的問(wèn)題

  • 隨著Vue項(xiàng)目規(guī)模和復(fù)雜性的增加干厚,現(xiàn)有 Option API 變得難以應(yīng)付
  • 邏輯并沒(méi)有真正地按功能分組李滴,這可能會(huì)讓人很難讀懂一個(gè)龐大而復(fù)雜的組件文件。
  • 通過(guò) Option API 實(shí)現(xiàn)組件間共享重復(fù)的邏輯(共享代碼)比較麻煩
  • 通過(guò)組合時(shí) API 我們可以將重用邏輯封裝為功能蛮瞄,這個(gè)功能可以組件間共享所坯,這樣你就可以在整個(gè)應(yīng)用程序的不同組件中使用這些邏輯。

接口

setup

執(zhí)行時(shí)間

優(yōu)先于beforeCreate 和 created挂捅。setup 選項(xiàng)在組件創(chuàng)建之前執(zhí)行芹助,一旦 props 被解析,就將作為組合式 API 的入口籍凝。

參數(shù)
  1. props:組件傳入的屬性
  2. context

setup中接受的props是響應(yīng)式的周瞎,當(dāng)傳入新的props會(huì)被及時(shí)更新苗缩。在setup中不能直接訪問(wèn)到this對(duì)象饵蒂。

所以在setup中定義props,用這樣的方式

defineProps({
  msg: String
})

context是一個(gè)普通的JavaScript對(duì)象酱讶,它暴露組件的三個(gè)property
context.attrs, context.slots, context.emit

組合式API生命周期函數(shù)
組合式api生命周期

onBeforeMount
onMounted
onBeforeUpdate
onUpdated
onUnmounted ( -> destroyed)
onActivated ( -> activited)
onDeacitivated ( ->deacitivated)
onRenderTriggered
onRenderTricked

reactive 和 ref

reactive 和 ref的作用都是定義和跟蹤需要雙向綁定的變量退盯。也就是數(shù)據(jù)定義,將一個(gè)普通對(duì)象變?yōu)轫憫?yīng)式對(duì)象泻肯。

ref 接收參數(shù)并將其包裹在一個(gè)帶有 value property 的對(duì)象中返回渊迁,然后可以使用該 property 訪問(wèn)或更改響應(yīng)式變量的值

toRefs的作用就是,將一個(gè)reactive對(duì)象轉(zhuǎn)化為屬性全部為ref對(duì)象的普通對(duì)象

<template>
<div> {{ month }}</div>
</template>
<script>
import {ref,reactive,toRefs } from "vue"

export default defineComponent({
 setup() {
    const year = ref(0)
    const date = reactive({
        month: 1
        minutes:200
    })
    
    return {
        year,
        ...toRefs(date)
    }
 }
)
</script>


isRef

isRef用于判斷變量是否為ref對(duì)象

const unwrapped = isRef(foo) ? foo.value : foo

computed

computed函數(shù)與vue2中computed功能一致灶挟,它接收一個(gè)函數(shù)并返回一個(gè)value為getter返回值的不可改變的響應(yīng)式ref對(duì)象琉朽。

const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 錯(cuò)誤,computed不可改變

// 同樣支持set和get屬性
onst count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: val => { count.value = val - 1 }
})
plusOne.value = 1
console.log(count.value) // 0

watch

用法

  • 指定依賴(lài)源:
    在基礎(chǔ)用法中稚铣,
    當(dāng)依賴(lài)了多個(gè)reactive或ref是無(wú)法直接看到的箱叁,需要在回調(diào)中尋找.
<template>
  <div>
    <input type="text" v-model="state.count">{{state.count}}
    <input type="text" v-model="inputRef">{{inputRef}}
  </div>
</template>
<script>
  import {watch, reactive, ref} from 'vue'

  export default {
    setup() {
      const state = reactive({count: 0})
      const inputRef = ref('')
      // state.count與inputRef中任意一個(gè)源改變都會(huì)觸發(fā)watch
      watch(() => {
        console.log('state', state.count)
        console.log('ref', inputRef.value)
      })
      return {state, inputRef}
    }
  }
</script>

  • 指定依賴(lài)源
<template>
  <div>
    state2.count: <input type="text" v-model="state2.count">
    {{state2.count}}<br/><br/>
    ref2: <input type="text" v-model="ref2">{{ref2}}<br/><br/>
  </div>
</template>
<script>
  import {watch, reactive, ref} from 'vue'

  export default {
    setup() {
      const state2 = reactive({count: ''})
      const ref2 = ref('')
      // 通過(guò)函數(shù)參數(shù)指定reative依賴(lài)源
      // 只有在state2.count改變時(shí)才會(huì)觸發(fā)watch
      watch(
        () => state2.count,
        () => {
          console.log('state2.count',state2.count)
          console.log('ref2.value',ref2.value)
      })
      // 直接指定ref依賴(lài)源
      watch(ref2,() => {
        console.log('state2.count',state2.count)
        console.log('ref2.value',ref2.value)
      })

      return {state, inputRef, state2, ref2}
    }
  }
</script>

  • 指定多個(gè)數(shù)據(jù)源
<template>
  <div>
    <p>
      <input type="text" v-model="state.a"><br/><br/>
      <input type="text" v-model="state.b"><br/><br/>
    </p>
    <p>
      <input type="text" v-model="ref1"><br/><br/>
      <input type="text" v-model="ref2"><br/><br/>
    </p>
  </div>
</template>

<script>
  import {reactive, ref, watch} from 'vue'

  export default {
    setup() {
      const state = reactive({a: 'a', b: 'b'})
      // state.a和state.b任意一個(gè)改變都會(huì)觸發(fā)watch的回調(diào)
      watch(() => [state.a, state.b],
       // 回調(diào)的第二個(gè)參數(shù)是對(duì)應(yīng)上一個(gè)狀態(tài)的值
       ([a, b], [preA, preB]) => {
        console.log('callback params:', a, b, preA, preB)
        console.log('state.a', state.a)
        console.log('state.b', state.b)
        console.log('****************')
      })

      const ref1 = ref(1)
      const ref2 = ref(2)
      watch([ref1, ref2],([val1, val2], [preVal1, preVal2]) => {
        console.log('callback params:', val1, val2, preVal1, preVal2)
        console.log('ref1.value:',ref1.value)
        console.log('ref2.value:',ref2.value)
         console.log('##############')
      })
      return {state, ref1, ref2}
    }
  }
</script>

  • 取消watch
<template>
  <div>
    <input type="text" v-model="inputRef">
    <button @click="onClick">stop</button>
  </div>
</template>

<script>
  import {watch, ref} from 'vue'

  export default {
    setup() {
      const inputRef = ref('')
      const stop = watch(() => {
        console.log('watch', inputRef.value)
      })
      const onClick = () => {
        // 取消watch墅垮,取消之后對(duì)應(yīng)的watch不會(huì)再執(zhí)行
        stop()
      }
      return {inputRef, onClick}
    }
  }
</script>

  • onCleanyp函數(shù):watch提供了一個(gè)onCleanup的副作用清除函數(shù),該函數(shù)接收一個(gè)函數(shù)耕漱,在該函數(shù)中進(jìn)行副作用清除算色。那么onCleanup什么時(shí)候執(zhí)行?

    • watch的callback即將被第二次執(zhí)行時(shí)先執(zhí)行onCleanup螟够。
    • watch被停止時(shí)灾梦,即組件被卸載之后。
      -watch選項(xiàng)
  • deep
    深層對(duì)象的任意一個(gè)屬性的改變都會(huì)出發(fā)回調(diào)的執(zhí)行

<template>
  <div>
    <button @click="onClick">CHANGE</button>
  </div>
</template>
<script>
  import {watch, ref} from 'vue'

  export default {
    setup() {
      const objRef = ref({a: {b: 123}, c: 123})
      watch(objRef,() => {
        console.log('objRef.value.a.b',objRef.value.a.b)
      }, {deep: true})
      const onClick = () => {
        // 設(shè)置了deep之后妓笙,深層對(duì)象任意屬性的改變都會(huì)觸發(fā)watch回調(diào)的執(zhí)行
        objRef.value.a.b = 780
      }
      return {onClick}
    }
  }
</script>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末若河,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子寞宫,更是在濱河造成了極大的恐慌牡肉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淆九,死亡現(xiàn)場(chǎng)離奇詭異统锤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)炭庙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)饲窿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人焕蹄,你說(shuō)我怎么就攤上這事逾雄。” “怎么了腻脏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵鸦泳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我永品,道長(zhǎng)做鹰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任鼎姐,我火速辦了婚禮钾麸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘炕桨。我一直安慰自己饭尝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布献宫。 她就那樣靜靜地躺著钥平,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姊途。 梳的紋絲不亂的頭發(fā)上涉瘾,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天奈惑,我揣著相機(jī)與錄音,去河邊找鬼睡汹。 笑死肴甸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的囚巴。 我是一名探鬼主播原在,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼彤叉!你這毒婦竟也來(lái)了庶柿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秽浇,失蹤者是張志新(化名)和其女友劉穎浮庐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體柬焕,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡审残,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斑举。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搅轿。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖富玷,靈堂內(nèi)的尸體忽然破棺而出璧坟,到底是詐尸還是另有隱情,我是刑警寧澤赎懦,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布雀鹃,位于F島的核電站,受9級(jí)特大地震影響励两,放射性物質(zhì)發(fā)生泄漏黎茎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一伐蒋、第九天 我趴在偏房一處隱蔽的房頂上張望工三。 院中可真熱鬧,春花似錦先鱼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至串远,卻和暖如春宏多,著一層夾襖步出監(jiān)牢的瞬間儿惫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工伸但, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肾请,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓更胖,卻偏偏與公主長(zhǎng)得像铛铁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子却妨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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