最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3 Composition API使用及說明

 更新時間:2025年10月22日 11:07:20   作者:tianzhiyi1989sq  
文章詳細介紹了Vue3的Composition API,包括setup配置、響應(yīng)式進階、生命周期、自定義Hook、toRef與toRefs的使用,以及Vue3新組件如Fragment、Teleport和Suspense,對比了Vue2和Vue3的生命周期

一、setup 配置詳解

1.1 Vue2 中的 $attrs 和 $slots 回顧

在 Vue2 中,父組件通過標(biāo)簽屬性向子組件傳遞數(shù)據(jù)時,通常需要在子組件中使用 props 接收。但即使不聲明接收,這些屬性也會存在于子組件實例的 $attrs 中。

示例對比:

// Vue2 子組件
export default {
  props: ['receivedProp'], // 聲明接收的屬性
  created() {
    console.log(this.$attrs) // 未聲明接收的屬性會出現(xiàn)在這里
    console.log(this.$slots) // 父組件傳遞的插槽內(nèi)容
  }
}

1.2 Vue3 setup 的兩個關(guān)鍵點

執(zhí)行時機

  • setup 在 beforeCreate 之前執(zhí)行
  • 此時組件實例尚未創(chuàng)建,this 為 undefined

參數(shù)解析

setup 接收兩個參數(shù):

props:包含組件外部傳遞且內(nèi)部聲明接收的屬性

context:上下文對象,包含:

  • attrs:未在 props 中聲明的屬性(相當(dāng)于 Vue2 的 $attrs
  • slots:接收的插槽內(nèi)容(相當(dāng)于 Vue2 的 $slots
  • emit:觸發(fā)自定義事件的函數(shù)(相當(dāng)于 Vue2 的 $emit

完整示例:

import { defineComponent } from 'vue'

export default defineComponent({
  props: ['title'],
  emits: ['change'], // 必須聲明自定義事件
  setup(props, { attrs, slots, emit }) {
    console.log(props.title) // 訪問聲明的 prop
    console.log(attrs.customAttr) // 訪問未聲明的屬性
    
    const handleClick = () => {
      emit('change', 'new value') // 觸發(fā)事件
    }
    
    return {
      handleClick
    }
  }
})

二、響應(yīng)式進階:計算屬性與監(jiān)視

2.1 computed 函數(shù)

Vue3 的 computed 用法與 Vue2 類似,但更靈活:

import { ref, computed } from 'vue'

setup() {
  const firstName = ref('張')
  const lastName = ref('三')
  
  // 只讀計算屬性
  const fullName = computed(() => `${firstName.value} ${lastName.value}`)
  
  // 可寫計算屬性
  const editableName = computed({
    get: () => `${firstName.value} ${lastName.value}`,
    set: (newValue) => {
      const [first, last] = newValue.split(' ')
      firstName.value = first
      lastName.value = last
    }
  })
  
  return { fullName, editableName }
}

2.2 watch 函數(shù)詳解

Vue3 的 watch 功能強大但有一些注意事項:

import { ref, reactive, watch } from 'vue'

setup() {
  const count = ref(0)
  const state = reactive({
    user: {
      name: 'Alice',
      age: 25
    }
  })
  
  // 情況1:監(jiān)視 ref
  watch(count, (newVal, oldVal) => {
    console.log(`count變化: ${oldVal} -> ${newVal}`)
  })
  
  // 情況2:監(jiān)視多個 ref
  watch([count, anotherRef], ([newCount, newAnother], [oldCount, oldAnother]) => {
    // 處理變化
  })
  
  // 情況3:監(jiān)視 reactive 對象(注意 oldValue 問題)
  watch(
    () => state.user,
    (newUser, oldUser) => {
      // oldUser 可能與 newUser 相同!
    },
    { deep: true } // 雖然默認開啟,但顯式聲明更清晰
  )
  
  // 情況4:監(jiān)視 reactive 對象的特定屬性
  watch(
    () => state.user.age,
    (newAge, oldAge) => {
      // 這里能正確獲取 oldAge
    }
  )
}

2.3 watchEffect 智能監(jiān)聽

watchEffect 自動追蹤回調(diào)中的響應(yīng)式依賴:

import { ref, watchEffect } from 'vue'

setup() {
  const count = ref(0)
  const message = ref('')
  
  watchEffect(() => {
    console.log(`count: ${count.value}, message: ${message.value}`)
    // 會自動追蹤 count 和 message 的變化
  })
  
  // 實際應(yīng)用:自動取消之前的請求
  const searchQuery = ref('')
  watchEffect(async (onCleanup) => {
    const query = searchQuery.value
    const controller = new AbortController()
    
    onCleanup(() => controller.abort()) // 清除副作用
    
    if (query) {
      const results = await fetchResults(query, {
        signal: controller.signal
      })
      // 處理結(jié)果
    }
  })
}

三、生命周期全解析

3.1 Vue2 與 Vue3 生命周期對比

Vue2 生命周期Vue3 生命周期 (Options API)Vue3 Composition API
beforeCreatebeforeCreatesetup()
createdcreatedsetup()
beforeMountbeforeMountonBeforeMount
mountedmountedonMounted
beforeUpdatebeforeUpdateonBeforeUpdate
updatedupdatedonUpdated
beforeDestroybeforeUnmountonBeforeUnmount
destroyedunmountedonUnmounted

3.2 組合式 API 生命周期使用

import { onMounted, onUnmounted } from 'vue'

setup() {
  // 鼠標(biāo)位置跟蹤示例
  const x = ref(0)
  const y = ref(0)
  
  const updatePosition = (e) => {
    x.value = e.pageX
    y.value = e.pageY
  }
  
  onMounted(() => {
    window.addEventListener('mousemove', updatePosition)
  })
  
  onUnmounted(() => {
    window.removeEventListener('mousemove', updatePosition)
  })
  
  return { x, y }
}

四、自定義 Hook 實踐

自定義 Hook 是 Vue3 代碼復(fù)用的利器:

4.1 鼠標(biāo)位置跟蹤 Hook

// hooks/useMousePosition.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useMousePosition() {
  const x = ref(0)
  const y = ref(0)
  
  const updatePosition = (e) => {
    x.value = e.pageX
    y.value = e.pageY
  }
  
  onMounted(() => {
    window.addEventListener('mousemove', updatePosition)
  })
  
  onUnmounted(() => {
    window.removeEventListener('mousemove', updatePosition)
  })
  
  return { x, y }
}

// 在組件中使用
import { useMousePosition } from './hooks/useMousePosition'

setup() {
  const { x, y } = useMousePosition()
  return { x, y }
}

4.2 數(shù)據(jù)請求 Hook

// hooks/useFetch.js
import { ref, isRef, unref, watchEffect } from 'vue'

export function useFetch(url) {
  const data = ref(null)
  const error = ref(null)
  const loading = ref(false)
  
  const fetchData = async () => {
    loading.value = true
    try {
      const response = await fetch(unref(url))
      data.value = await response.json()
      error.value = null
    } catch (err) {
      error.value = err.message
    } finally {
      loading.value = false
    }
  }
  
  if (isRef(url)) {
    watchEffect(fetchData)
  } else {
    fetchData()
  }
  
  return { data, error, loading, retry: fetchData }
}

五、toRef 與 toRefs 深度解析

5.1 toRef 使用場景

import { reactive, toRef } from 'vue'

setup() {
  const state = reactive({
    name: 'Alice',
    age: 25
  })
  
  // 保持響應(yīng)式連接
  const nameRef = toRef(state, 'name')
  
  setTimeout(() => {
    state.name = 'Bob' // nameRef 也會更新
  }, 1000)
  
  return {
    nameRef // 可以在模板中直接使用
  }
}

5.2 toRefs 解構(gòu)響應(yīng)式對象

import { reactive, toRefs } from 'vue'

setup() {
  const state = reactive({
    name: 'Alice',
    age: 25,
    address: {
      city: 'Beijing'
    }
  })
  
  // 解構(gòu)后仍保持響應(yīng)式
  const { name, age } = toRefs(state)
  
  // 嵌套對象需要單獨處理
  const { city } = toRefs(state.address)
  
  return {
    name,
    age,
    city
  }
}

六、Vue3 新組件實戰(zhàn)

6.1 Fragment 片段組件

Vue3 不再需要根標(biāo)簽:

<template>
  <header>...</header>
  <main>...</main>
  <footer>...</footer>
</template>

6.2 Teleport 傳送門

將組件渲染到 DOM 中的其他位置:

<template>
  <button @click="showModal = true">打開彈窗</button>
  
  <Teleport to="body">
    <div v-if="showModal" class="modal">
      <div class="modal-content">
        <h2>標(biāo)題</h2>
        <p>內(nèi)容...</p>
        <button @click="showModal = false">關(guān)閉</button>
      </div>
    </div>
  </Teleport>
</template>

<script>
import { ref } from 'vue'
export default {
  setup() {
    const showModal = ref(false)
    return { showModal }
  }
}
</script>

6.3 Suspense 異步組件

優(yōu)雅處理異步組件加載狀態(tài):

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div class="loading-spinner">
        加載中...
      </div>
    </template>
  </Suspense>
</template>

<script>
import { defineAsyncComponent } from 'vue'

const AsyncComponent = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

export default {
  components: {
    AsyncComponent
  }
}
</script>

七、Composition API 優(yōu)勢總結(jié)

  • 更好的代碼組織:相關(guān)功能代碼集中在一起
  • 更好的邏輯復(fù)用:通過自定義 Hook 實現(xiàn)
  • 更好的類型推斷:對 TypeScript 支持更友好
  • 更小的生產(chǎn)包:Tree-shaking 友好

對比示例:

// Options API 方式
export default {
  data() {
    return {
      count: 0,
      searchQuery: ''
    }
  },
  computed: {
    filteredList() {
      // 基于 searchQuery 過濾列表
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    // 初始化代碼
  }
}

// Composition API 方式
import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const searchQuery = ref('')
    
    const increment = () => {
      count.value++
    }
    
    const filteredList = computed(() => {
      // 過濾邏輯
    })
    
    onMounted(() => {
      // 初始化代碼
    })
    
    return {
      count,
      searchQuery,
      increment,
      filteredList
    }
  }
}

總結(jié)

Vue3 的 Composition API 為開發(fā)者提供了更靈活、更強大的代碼組織方式。通過本文的詳細解析和豐富示例,相信你已經(jīng)掌握了其核心概念和使用技巧。

在實際開發(fā)中,建議從簡單功能開始逐步嘗試組合式 API,體驗其帶來的開發(fā)效率提升和代碼可維護性優(yōu)勢。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue實現(xiàn)多頁簽組件

    Vue實現(xiàn)多頁簽組件

    這篇文章主要介紹了Vue實現(xiàn)多頁簽組件的方法,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下
    2021-01-01
  • Nuxt3:拉取項目模板失敗問題以及解決

    Nuxt3:拉取項目模板失敗問題以及解決

    文章描述了在使用官網(wǎng)命令創(chuàng)建Nuxt3項目時遇到的問題,通過分析命令,推測問題出在拉取項目模板失敗,解決方法是手動訪問并下載項目模板,解壓后按照官網(wǎng)教程安裝依賴并啟動,最終成功解決問題
    2024-12-12
  • vuejs如何配置less

    vuejs如何配置less

    本篇文章主要介紹了vuejs如何配置less,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • vue3.0使用mapState,mapGetters和mapActions的方式

    vue3.0使用mapState,mapGetters和mapActions的方式

    這篇文章主要介紹了vue3.0使用mapState,mapGetters和mapActions的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 使用vscode快速建立vue模板過程詳解

    使用vscode快速建立vue模板過程詳解

    這篇文章主要介紹了使用vscode快速建立vue模板過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Vue3組合式API之getCurrentInstance詳解

    Vue3組合式API之getCurrentInstance詳解

    我們可以通過?getCurrentInstance這個函數(shù)來返回當(dāng)前組件的實例對象,也就是當(dāng)前vue這個實例對象,下面這篇文章主要給大家介紹了關(guān)于Vue3組合式API之getCurrentInstance的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • Vue3?KeepAlive實現(xiàn)原理解析

    Vue3?KeepAlive實現(xiàn)原理解析

    KeepAlive?是一個內(nèi)置組件,那封裝一個組件對于大家來說應(yīng)該不會有太大的困難,它的核心邏輯在于它的?render?函數(shù),它用?map?去記錄要緩存的組件,就是?[key,vnode]?的形式,這篇文章主要介紹了Vue3?KeepAlive實現(xiàn)原理,需要的朋友可以參考下
    2022-09-09
  • vue3中如何使用mqtt數(shù)據(jù)傳輸

    vue3中如何使用mqtt數(shù)據(jù)傳輸

    這篇文章主要為大家詳細介紹了vue3中如何使用mqtt數(shù)據(jù)傳輸,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • 使用WebStorm運行vue項目的詳細圖文教程

    使用WebStorm運行vue項目的詳細圖文教程

    在WebStorm中怎么打開一個已有的項目,這個不用多說,那么如何運行一個vue項目呢?下面這篇文章主要給大家介紹了關(guān)于使用WebStorm運行vue項目的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Vue2 element 表頭查詢功能實現(xiàn)代碼

    Vue2 element 表頭查詢功能實現(xiàn)代碼

    本文介紹Vue2中Element UI表格自定義表頭及查詢功能實現(xiàn),需通過slot-scope綁定數(shù)據(jù),注意Vue2.6+版本改用#header語法,并提供示例代碼說明,感興趣的朋友一起看看吧
    2025-07-07

最新評論

壤塘县| 胶南市| 海南省| 三江| 屯昌县| 宜兴市| 寿宁县| 砚山县| 安达市| 贵阳市| 武乡县| 芦山县| 太康县| 汉中市| 全椒县| 辽源市| 大石桥市| 阳高县| 巴东县| 玉门市| 全椒县| 无棣县| 津市市| 比如县| 本溪| 咸丰县| 磐安县| 湘西| 南平市| 昆山市| 潼关县| 兴安县| 冷水江市| 永修县| 关岭| 金川县| 高唐县| 石棉县| 横山县| 河西区| 景谷|