Vue3組合式API

組合API

前言

  • 組合式api(Composition API)算是vue3對我們開發(fā)者來說非常有價值的一個api更新。
  • 注意,vue3中仍可以使用選項API冲呢。

一鸥咖、選項API和組合API

選項API

  • 各個選項都有固定的書寫位置燕鸽,data選項寫響應式數據,methods選項寫方法函數...啼辣,一個功能邏輯的代碼分散啊研。

  • 優(yōu)點:寫代碼的位置已經約定好,結構清晰

  • 缺點:代碼組織性差鸥拧,相似的邏輯代碼不便于復用党远,邏輯復雜代碼多了不好閱讀,同一功能的上下文代碼難找富弦。

組合API

  • 特定功能相關的所有東西都寫在一起沟娱,同一功能代碼塊集中
  • 優(yōu)點:
    • 可以快讀定位到某個功能的所有相關代碼舆声。
    • 功能復雜花沉,代碼量大,我們還可以進行邏輯拆分處理媳握,功能封裝碱屁。

組合API功能抽離,封裝:


二蛾找、生命周期函數

選項式API 組合式API
beforeCreate 不需要(直接寫到setup(創(chuàng)建實例前)函數中)
created 不需要(直接寫到setup(創(chuàng)建實例前)函數中)
beforeMount onBeforeMount掛載DOM前
mounted onMounted掛載DOM后
beforeUpdate onBeforeUpdate更新組件前
updated onUpdated更新組件后
beforeDestroyed onBeforeUnmount卸載銷毀前
destroyed onUnmounted卸載銷毀后

總結: 組合API的生命周期鉤子有7個娩脾,可以多次使用同一個鉤子,執(zhí)行順序和書寫順序相同打毛。


三柿赊、組合API基礎

3.1 setup入口函數
  1. setup 函數是一個新的組件選項,作為組件中組合式API 的起點(入口)
  2. setup 中不能使用 this幻枉, this 指向 undefined
  3. setup函數只會在組件初始化的時候執(zhí)行一次
  4. setup函數在beforeCreate生命周期鉤子執(zhí)行之前執(zhí)行
export default {
  setup () {
    console.log('setup執(zhí)行了')
    console.log(this)
  },
  beforeCreate() {
    console.log('beforeCreate執(zhí)行了')
    console.log(this)
  }
}

3.2 reactive函數
  • 作用:reactive是一個函數碰声,接收一個普通的對象傳入,把對象數據轉化為響應式對象并返回

使用步驟

  1. 從vue框架中導入reactive函數
  2. setup函數中調用reactive函數并將對象數據傳入
  3. setup函數中把reactive函數調用完畢之后的返回值以對象的形式返回出去

3.3 toRef函數
  • toRef是函數熬甫,轉換響應式對象中某個屬性為單獨響應式數據胰挑,并且值是關聯的。

3.4 toRefs函數
  • 場景: 經過reactive函數處理之后返回的對象,如果給這個對象解構或者展開瞻颂,會讓數據丟失響應式的能力豺谈,為了解決這個問題需要引入toRefs函數,使用 toRefs函數 可以保證該對象展開的每個屬性都是響應式的贡这。

3.5 ref函數
  • 作用:ref是一個函數茬末,接受一個簡單類型或者復雜類型的傳入并返回一個響應式且可變的 ref 對象

使用步驟

  1. 從vue框架中導出ref函數
  2. setup函數中調用ref函數并傳入數據(簡單類型或者復雜類型)
  3. setup函數中把ref函數調用完畢的返回值以對象的形式返回出去
  4. 注意:在setup函數中使用ref結果,需要通過.value訪問盖矫,模板中使用不需要加.value

四丽惭、組合API

4.1 computed函數
  • computed函數,是用來定義計算屬性的辈双,計算屬性不能修改吐根。

計算屬性兩種用法:

  • computed傳入函數,返回值就是計算屬性的值
  • computed傳入對象辐马,get獲取計算屬性的值,set監(jiān)聽計算屬性改變局义。

4.2 watch函數
  • watch函數喜爷,是用來定義偵聽器的
  1. 監(jiān)聽ref定義的響應式數據

  2. 監(jiān)聽多個響應式數據數據

  3. 監(jiān)聽reactive定義的響應式數據

  4. 監(jiān)聽reactive定義的響應式數據,某一個屬性

  5. 深度監(jiān)聽

  6. 默認執(zhí)行

<template>
  <div class="container">
    <div>
      <p>count的值:{{count}}</p>
      <button @click="add">改數據</button>
    </div>
    <hr>
    <div>
      <p>{{obj.name}}</p>
      <p>{{obj.age}}</p>
      <p>{{obj.brand.name}}</p>
      <button @click="updateName">改名字</button>
      <button @click="updateBrandName">改品牌名字</button>
    </div>
  </div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
  name: 'App',
  setup () {
    const count = ref(0)
    const add = () => {
      count.value++
    }
    // 當你需要監(jiān)聽數據的變化就可以使用watch
    // 1. 監(jiān)聽一個ref數據
    // 1.1 第一個參數  需要監(jiān)聽的目標
    // 1.2 第二個參數  改變后觸發(fā)的函數
    // watch(count, (newVal,oldVal)=>{
    //   console.log(newVal,oldVal)
    // })

    const obj = reactive({
      name: 'ls',
      age: 10,
      brand: {
        id: 1,
        name: '寶馬'
      }
    })
    const updateName = () => {
      obj.name = 'zs'
    }
    const updateBrandName = () => {
      obj.brand.name = '奔馳'
    }
    // 2. 監(jiān)聽一個reactive數據
    watch(obj, ()=>{
      console.log('數據改變了')
    })

    watch(()=>obj.brand, ()=>{
      console.log('brand數據改變了')
    },{
      // 5. 需要深度監(jiān)聽
      deep: true,
      // 6. 想默認觸發(fā)
      immediate: true
    })

    // 3. 監(jiān)聽多個數據的變化
    // watch([count, obj], ()=>{
    //   console.log('監(jiān)聽多個數據改變了')
    // }) 


    // 4. 此時監(jiān)聽對象中某一個屬性的變化 例如:obj.name 
    // 需要寫成函數返回該屬性的方式才能監(jiān)聽到
    // watch(()=>obj.name,()=>{
    //   console.log('監(jiān)聽obj.name改變了')
    // })

    return {count, add, obj, updateName, updateBrandName}
  }
}
</script>

4.3 ref屬性
  • 使用ref屬性綁定DOM或組件

獲取單個DOM或者組件:

<template>
  <div class="container">
    <!-- vue2.0 獲取單個元素 -->
    <!-- 1. 通過ref屬性綁定該元素 -->
    <!-- 2. 通過this.$refs.box獲取元素 -->
    <!-- <div ref="box">我是box</div> -->
    <!-- vue2.0 獲取v-for遍歷的多個元素 -->
    <!-- 1. 通過ref屬性綁定被遍歷元素 -->
    <!-- 2. 通過this.$refs.li 獲取所有遍歷元素  -->
    <!-- <ul>
      <li v-for="i in 4" :key="i" ref="li">{{i}}</li>
    </ul> -->

    <!-- 單個元素 -->
    <div ref="dom">我是box</div>
    <!-- 被遍歷的元素 -->
    <ul>
      <li v-for="i in 4" :key="i" :ref="setDom">第{{i}}LI</li>
    </ul>
  </div>
</template>
<script>
import { onMounted, ref } from 'vue'
export default {
  name: 'App',
  setup () {
    // 1. 獲取單個元素
    // 1.1 先定義一個空的響應式數據ref定義的
    // 1.2 setup中返回該數據萄唇,你想獲取那個dom元素檩帐,在該元素上使用ref屬性綁定該數據即可。
    const dom = ref(null)
    onMounted(()=>{
       console.log(dom.value)
    })
  }
}
</script>
<style scoped lang="less"></style>

獲取v-for遍歷的DOM或者組件:

// 2. 獲取v-for遍歷的元素
   // 2.1 定義一個空數組另萤,接收所有的LI
   // 2.2 定義一個函數湃密,往空數組push DOM
   const domList = []
   const setDom = (el) => {
     domList.push(el)
   }
   onMounted(()=>{
     console.log(domList)
   })
   return {dom, setDom}

總結:

  • 單個元素:先申明ref響應式數據,返回給模版使用四敞,通過ref綁定數據

  • 遍歷的元素:先定義一個空數組泛源,定一個函數獲取元素,返回給模版使用忿危,通過ref綁定這個函數

    • 有一個邊界問題:組件更新的時候會重復的設置dom元素給數組:
    // ref獲取v-for遍歷的DOM元素达箍,需要在組件更新的時候重置接受dom元素的數組。
    onBeforeUpdate(()=>{
      list = []
    })
    

4.4 父子通訊

父傳子:

子傳父:

總結:

  • 父傳子:在setup種使用props數據 setup(props){ // props就是父組件數據 }
  • 子傳父:觸發(fā)自定義事件的時候emit來自 setup(props,{emit}){ // emit 就是觸發(fā)事件函數 }
  • 在vue3.0中 v-model.sync 已經合并成 v-model 指令

4.5 依賴注入(祖孫通訊)
  • 使用provide函數和inject函數完成后代組件數據通訊

總結:

  • provide函數提供數據和函數給后代組件使用
  • inject函數給當前組件注入provide提供的數據和函數

五铺厨、補充

5.1 v-model語法糖
  • 在vue2.0中v-mode語法糖簡寫的代碼 <Son :value="msg" @input="msg=$event" />
  • 在vue3.0中v-model語法糖有所調整:<Son :modelValue="msg" @update:modelValue="msg=$event" />

演示代碼:

//父組件App
<template>
  <div class="container">
    <!-- 如果你想獲取原生事件事件對象 -->
    <!-- 如果綁定事函數 fn fn(e){ // e 就是事件對象 } -->
    <!-- 如果綁定的是js表達式  此時提供一個默認的變量 $event -->
    <h1 @click="$event.target.style.color='red'">父組件 {{count}}</h1>
    <hr>
    <!-- 如果你想獲取自定義事件  -->
    <!-- 如果綁定事函數 fn fn(data){ // data 觸發(fā)自定義事件的傳參 } -->
    <!-- 如果綁定的是js表達式  此時 $event代表觸發(fā)自定義事件的傳參 -->
    <!-- <Son :modelValue="count" @update:modelValue="count=$event" /> -->
    <Son v-model="count" />
  </div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
  name: 'App',
  components: {
    Son
  },
  setup () {
    const count = ref(10)
    return { count }
  }
}
</script>


//子組件Son
<template>
  <div class="container">
    <h2>子組件 {{modelValue}} <button @click="fn">改變數據</button></h2>
  </div>
</template>
<script>
export default {
  name: 'Son',
  props: {
    modelValue: {
      type: Number,
      default: 0
    }
  },
  setup (props, {emit}) {
    const fn = () => {
      // 改變數據
      emit('update:modelValue', 100)
    }
    return { fn }
  }
}
</script>

總結: vue3.0封裝組件支持v-model的時候缎玫,父傳子:modelValue 子傳父 @update:modelValue

補充: vue2.0的 xxx.sync 語法糖解析 父傳子 :xxx 子傳父 @update:xxx 在vue3.0 使用 v-model:xxx 代替。


5.2 mixins語法
  • 混入 (mixin) 提供了一種非常靈活的方式解滓,來分發(fā) Vue 組件中的可復用功能赃磨。一個混入對象可以包含任意組件選項。當組件使用混入對象時洼裤,所有混入對象的選項將被“混合”進入該組件本身的選項邻辉。

理解全局混入:所有組件混入了這些邏輯代碼

總結: 在vue2.0中一些可復用的邏輯可以使用mixins來封裝,當是需要考慮邏輯代碼沖突問題。vue3.0的組合API很好的解決了這個問題恩沛,就不在推薦使用mixins了在扰。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市雷客,隨后出現的幾起案子芒珠,更是在濱河造成了極大的恐慌,老刑警劉巖搅裙,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皱卓,死亡現場離奇詭異,居然都是意外死亡部逮,警方通過查閱死者的電腦和手機娜汁,發(fā)現死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兄朋,“玉大人掐禁,你說我怎么就攤上這事÷停” “怎么了傅事?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長峡扩。 經常有香客問我蹭越,道長,這世上最難降的妖魔是什么教届? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任响鹃,我火速辦了婚禮,結果婚禮上案训,老公的妹妹穿的比我還像新娘买置。我一直安慰自己,他們只是感情好萤衰,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布堕义。 她就那樣靜靜地躺著,像睡著了一般脆栋。 火紅的嫁衣襯著肌膚如雪倦卖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天椿争,我揣著相機與錄音怕膛,去河邊找鬼。 笑死秦踪,一個胖子當著我的面吹牛褐捻,可吹牛的內容都是我干的掸茅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼柠逞,長吁一口氣:“原來是場噩夢啊……” “哼昧狮!你這毒婦竟也來了?” 一聲冷哼從身側響起板壮,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤逗鸣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绰精,有當地人在樹林里發(fā)現了一具尸體撒璧,經...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年笨使,在試婚紗的時候發(fā)現自己被綠了卿樱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡硫椰,死狀恐怖繁调,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情靶草,我是刑警寧澤涉馁,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站爱致,受9級特大地震影響,放射性物質發(fā)生泄漏寒随。R本人自食惡果不足惜糠悯,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妻往。 院中可真熱鬧互艾,春花似錦、人聲如沸讯泣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽好渠。三九已至昨稼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拳锚,已是汗流浹背假栓。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留霍掺,地道東北人匾荆。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓拌蜘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牙丽。 傳聞我的和親對象是個殘疾皇子简卧,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容