欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3中的setup()函數(shù)基本使用詳解

 更新時(shí)間:2024年02月21日 09:59:01   作者:前端青山  
在 Vue3 中,setup 函數(shù)是一個(gè)新引入的概念,它代替了之前版本中的 data、computed、methods 等選項(xiàng),用于設(shè)置組件的初始狀態(tài)和邏輯,本文將主要介紹Setup的基本用法和少量原理,感興趣的朋友一起看看吧

在 Vue3 中,setup 函數(shù)是一個(gè)新引入的概念,它代替了之前版本中的 data、computed、methods 等選項(xiàng),用于設(shè)置組件的初始狀態(tài)和邏輯。setup 函數(shù)的引入使得組件的邏輯更加清晰和靈活,本文將主要介紹Setup的基本用法和少量原理

  • 更靈活的組織邏輯:setup 函數(shù)可以將相關(guān)邏輯按照功能進(jìn)行組織,使得組件更加清晰和易于維護(hù)。不再受到 Options API 中選項(xiàng)的限制,可以更自由地組織代碼。
  • 邏輯復(fù)用:可以將邏輯抽取為可復(fù)用的函數(shù),并在 setup 函數(shù)中進(jìn)行調(diào)用,實(shí)現(xiàn)邏輯的復(fù)用,避免了在 Options API 中通過 mixins 或混入對(duì)象實(shí)現(xiàn)邏輯復(fù)用時(shí)可能出現(xiàn)的問題。
  • 更好的類型推斷:由于 setup 函數(shù)本身是一個(gè)普通的 JavaScript 函數(shù),可以更好地與 TypeScript 配合,提供更好的類型推斷和代碼提示。
  • 更好的響應(yīng)式處理:setup 函數(shù)中可以使用 ref、reactive 等函數(shù)創(chuàng)建響應(yīng)式數(shù)據(jù),可以更方便地處理組件的狀態(tài),實(shí)現(xiàn)數(shù)據(jù)的動(dòng)態(tài)更新。
  • 更細(xì)粒度的生命周期鉤子:setup 函數(shù)中可以使用 onMounted、onUpdated、onUnmounted 等函數(shù)注冊(cè)組件的生命周期鉤子,可以更細(xì)粒度地控制組件的生命周期行為。
  • 更好的代碼組織:setup 函數(shù)將組件的邏輯集中在一個(gè)地方,使得代碼更易讀、易維護(hù),并且可以更清晰地看到組件的整體邏輯。

setup()函數(shù)

setup() 鉤子是在組件中使用組合式 API 的入口,通常只在以下情況下使用:

  • 需要在非單文件組件中使用組合式 API 時(shí)。
  • 需要在基于選項(xiàng)式 API 的組件中集成基于組合式 API 的代碼時(shí)。

其他情況下,都應(yīng)優(yōu)先使用 <script setup> 語法。

1.1 基本使用

我們可以使用響應(yīng)式 API 來聲明響應(yīng)式的狀態(tài),在 setup() 函數(shù)中返回的對(duì)象會(huì)暴露給模板和組件實(shí)例。其它的選項(xiàng)也可以通過組件實(shí)例來獲取 setup() 暴露的屬性。

<script>
import { ref } from 'vue'
?
export default {
  setup() {
    const count = ref(0)
?
    // 返回值會(huì)暴露給模板和其他的選項(xiàng)式 API 鉤子
    return {
      count
    }
  },
?
  mounted() {
    console.log(this.count) // 0
  }
}
</script>
?
<template>
  <button @click="count++">{{ count }}</button>
</template>

請(qǐng)注意在模板中訪問從 setup 返回的 ref 時(shí),它會(huì)自動(dòng)淺層解包,因此你無須再在模板中為它寫 .value。當(dāng)通過 this 訪問時(shí)也會(huì)同樣如此解包。

setup() 自身并不含對(duì)組件實(shí)例的訪問權(quán),即在 setup() 中訪問 this 會(huì)是 undefined。你可以在選項(xiàng)式 API 中訪問組合式 API 暴露的值,但反過來則不行。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>組合式API</title>
</head>
<body>
  <div id="app">
    {{ count }}
    <button @click="add">加1</button>
  </div>
</body>
<script src="../lib/vue.global.js"></script>
<script>
  const { ref, onMounted } = Vue
  Vue.createApp({
    setup () {
      const count = ref(0)
      const add = () => {
        count.value += 1
      }
      onMounted(() => {
        console.log(1111)
      })
      return {
        count,
        add
      }
    },
    data () {
      return {
        count: 10
      }
    },
    methods: {
      add () {
        this.count += 10
      }
    },
    mounted () {
      console.log('2222')
    }
  }).mount('#app')
</script>
</html>

生命周期先執(zhí)行 組合式API 后執(zhí)行選項(xiàng)式API,其余以組合式API為優(yōu)先

1.2 訪問 Prop

setup 函數(shù)的第一個(gè)參數(shù)是組件的 props。和標(biāo)準(zhǔn)的組件一致,一個(gè) setup 函數(shù)的 props 是響應(yīng)式的,并且會(huì)在傳入新的 props 時(shí)同步更新。

{
  props: {
    title: String,
    count: Number
  },
  setup(props) {
    console.log(props.title)
    console.log(props.count)
  }
}

請(qǐng)注意如果你解構(gòu)了 props 對(duì)象,解構(gòu)出的變量將會(huì)丟失響應(yīng)性。因此我們推薦通過 props.xxx 的形式來使用其中的 props。

如果你確實(shí)需要解構(gòu) props 對(duì)象,或者需要將某個(gè) prop 傳到一個(gè)外部函數(shù)中并保持響應(yīng)性,那么你可以使用 toRefs() 和 toRef() 這兩個(gè)工具函數(shù):

{
  setup(props) {
    // 將 `props` 轉(zhuǎn)為一個(gè)其中全是 ref 的對(duì)象,然后解構(gòu)
    const { title } = toRefs(props)
    // `title` 是一個(gè)追蹤著 `props.title` 的 ref
    console.log(title.value)
?
    // 或者,將 `props` 的單個(gè)屬性轉(zhuǎn)為一個(gè) ref
    const title = toRef(props, 'title')
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>組合式API</title>
</head>
<body>
  <div id="app">
    <button @click="num++">加1</button> {{ num }}
    <my-root :num="num"></my-root>
  </div>
</body>
<script src="../lib/vue.global.js"></script>
<template id="root">
<div>{{ num }} -- {{ test }}</div>
</template>
<script>
  const { ref, onMounted, computed } = Vue
?
  const Root = {
    props: ['num'],
    template: '#root',
    // setup (props) { // 千萬不要對(duì) props 解構(gòu)
    //   console.log('111')
    //   return {
    //     test: computed(() => props.num) // 繼續(xù)保持響應(yīng)式
    //   }
    // }
    setup ({ num }) {
      console.log(num)
      return {
        test: computed(() => num) // 失去了響應(yīng)式 - test的值不會(huì)發(fā)生改變
      }
    }
  }
  Vue.createApp({
    setup () {
      const num = ref(10000)
      return { num }
    },
    components: {
      MyRoot: Root
    }
  }).mount('#app')
</script>
</html>

1.3 Setup的上下文

傳入 setup 函數(shù)的第二個(gè)參數(shù)是一個(gè) Setup 上下文對(duì)象。上下文對(duì)象暴露了其他一些在 setup 中可能會(huì)用到的值:

{
  setup(props, context) {
    // 透?jìng)?Attributes(非響應(yīng)式的對(duì)象,等價(jià)于 $attrs)
    console.log(context.attrs)
?
    // 插槽(非響應(yīng)式的對(duì)象,等價(jià)于 $slots)
    console.log(context.slots)
?
    // 觸發(fā)事件(函數(shù),等價(jià)于 $emit)
    console.log(context.emit)
?
    // 暴露公共屬性(函數(shù))
    console.log(context.expose)
  }
}

該上下文對(duì)象是非響應(yīng)式的,可以安全地解構(gòu):

{
  setup(props, { attrs, slots, emit, expose }) {
    ...
  }
}

attrsslots 都是有狀態(tài)的對(duì)象,它們總是會(huì)隨著組件自身的更新而更新。這意味著你應(yīng)當(dāng)避免解構(gòu)它們,并始終通過 attrs.xslots.x 的形式使用其中的屬性。此外還需注意,和 props 不同,attrsslots 的屬性都不是響應(yīng)式的。如果你想要基于 attrsslots 的改變來執(zhí)行副作用,那么你應(yīng)該在 onBeforeUpdate 生命周期鉤子中編寫相關(guān)邏輯。

expose 函數(shù)用于顯式地限制該組件暴露出的屬性,當(dāng)父組件通過模板引用訪問該組件的實(shí)例時(shí),將僅能訪問 expose 函數(shù)暴露出的內(nèi)容

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>setup上下文對(duì)象</title>
</head>
<body>
  <div id="app">
    <my-com ref="comref" class="myBox" style="color: red" id="box" msg="hello msg" @my-event="getData">
      <template #header>
        header
      </template>
      <div>content</div>
      <template #footer>
        footer
      </template>
    </my-com>
  </div>
</body>
<template id="com">
  <div>
    <h1>子組件</h1>
    <button @click="sendData">發(fā)送數(shù)據(jù)</button>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>
<script src="../lib/vue.global.js"></script>
<script>
  const { createApp, ref, onMounted } = Vue
  const Com = {
    template: '#com',
    setup (props, context) {
      // attrs 獲取透?jìng)鬟^來的值
      // slots 如果使用了插槽
      // emit  子組件給父組件傳值
      // expose 子組件暴露給父組件可以調(diào)用的屬性和方法  ---- options API  ref獲取子組件的實(shí)例
?
      console.log(props)
      console.log(context.attrs) // ref 不在透?jìng)髦?
      console.log(context.slots)
      const sendData = () => { // 子組件給父組件傳值
        context.emit('my-event', 1000)
      }
?
      // 自定義的屬性和方法,供給父組件使用
      const a = ref(1)
      const b = ref(2)
      const c = ref(3)
?
      const fn = () => {
        a.value = 100
      }
?
      // 暴露出去的是對(duì)象
      context.expose({
        a, b, fn
      })
?
      return {
        sendData
      }
    }
  }
?
  Vue.createApp({
    setup () {
      const getData = (val) => { // 接收子組件的值
        console.log('666', val)
      }
?
      const comref = ref() //  comref 就是模版中ref="comref"
?
      onMounted(() => {
        console.log('com', comref.value) // {}
        console.log('a', comref.value.a) // 1
        console.log('b', comref.value.b) // 2
        console.log('c', comref.value.c) // undefined 因?yàn)闆]有暴露
        comref.value.fn()
        console.log('a', comref.value.a) // 100
      })
?
      return {
        getData,
        comref
      }
    },
    components: {
      MyCom: Com
    }
  }).mount('#app')
</script>
</html>

在父組件通過ref獲取子組件的實(shí)例的屬性和方法的需求中,需要注意:

1.如果子組件是 選項(xiàng)式API組件,基本不需要做任何操作

2.如果子組件是 組合式API組件,需要通過 context.expose 暴露給父組件需要使用的屬性和方法

3.如果父組件使用 選項(xiàng)式API, 可以通過 this.$refs.refName 訪問到子組件想要你看到的屬性和方法

4.如果父組件使用 組合式API,需要在setup中先創(chuàng)建 refName,然后再訪問子組件想要你看到的屬性和方法(const refName = ref() refName.value.X)

1.4 與渲染函數(shù)一起使用

setup 也可以返回一個(gè)渲染函數(shù),此時(shí)在渲染函數(shù)中可以直接使用在同一作用域下聲明的響應(yīng)式狀態(tài):

{
  setup() {
    const count = ref(0)
    return () => h('div', count.value)
  }
}

返回一個(gè)渲染函數(shù)將會(huì)阻止我們返回其他東西。對(duì)于組件內(nèi)部來說,這樣沒有問題,但如果我們想通過模板引用將這個(gè)組件的方法暴露給父組件,那就有問題

我們可以通過調(diào)用 expose() 解決這個(gè)問題:

{
  setup(props, { expose }) {
    const count = ref(0)
    const increment = () => ++count.value
?
    expose({
      increment
    })
?
    return () => h('div', count.value)
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>渲染函數(shù)</title>
</head>
<body>
  <div id="app">
    <button @click="add">加1</button>
    <my-child ref="child"></my-child>
  </div>
</body>
<script src="../lib/vue.global.js"></script>
<script>
  const { h, ref } = Vue
  const Child = {
    // 寫法1:
    // template: `<div>child</div>`
    // 寫法2:
    // render () {
    //   return [
    //     h('div', 'child!')
    //   ]
    // }
    // 寫法3
    setup (props, { expose }) {
      const count = ref(10)
?
      const increment = () => {
        count.value += 1
      }
?
      expose({
        increment
      })
?
      // 返回一個(gè)函數(shù)  函數(shù)返回 渲染函數(shù)的結(jié)果
      return () => h('div', 'child!!' + count.value)
    }
  }
?
  Vue.createApp({
    components: {
      MyChild: Child
    },
    setup () {
      const child = ref()
?
      const add = () => {
        child.value.increment()
      }
?
      return {
        child,
        add
      }
    }
  }).mount('#app')
</script>
</html>

到此這篇關(guān)于vue3中的setup()函數(shù)詳解的文章就介紹到這了,更多相關(guān)vue3 setup()函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue+elementui實(shí)現(xiàn)表格多級(jí)表頭效果

    vue+elementui實(shí)現(xiàn)表格多級(jí)表頭效果

    這篇文章主要為大家詳細(xì)介紹了vue?+?elementui實(shí)現(xiàn)表格多級(jí)表頭,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • vuex 多模塊時(shí) 模塊內(nèi)部的mutation和action的調(diào)用方式

    vuex 多模塊時(shí) 模塊內(nèi)部的mutation和action的調(diào)用方式

    這篇文章主要介紹了vuex 多模塊時(shí) 模塊內(nèi)部的mutation和action的調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • vue實(shí)現(xiàn)導(dǎo)出word文檔的示例代碼

    vue實(shí)現(xiàn)導(dǎo)出word文檔的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何使用vue實(shí)現(xiàn)導(dǎo)出word文檔(包括圖片),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 一文詳細(xì)介紹vue的遞歸組件(推薦)

    一文詳細(xì)介紹vue的遞歸組件(推薦)

    這篇文章主要介紹了vue遞歸組件的相關(guān)資料,遞歸組件是Vue.js中用于渲染層級(jí)結(jié)構(gòu)的強(qiáng)大工具,通過組件調(diào)用自身來簡(jiǎn)化復(fù)雜數(shù)據(jù)的渲染,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12
  • Vue實(shí)現(xiàn)自定義下拉菜單功能

    Vue實(shí)現(xiàn)自定義下拉菜單功能

    這篇文章主要介紹了Vue實(shí)現(xiàn)自定義下拉菜單功能,文章先通過實(shí)例代碼給大家介紹,后面對(duì)用到的知識(shí)點(diǎn)總結(jié),需要的朋友可以參考下
    2018-07-07
  • vue引用json文件的方法小結(jié)

    vue引用json文件的方法小結(jié)

    這篇文章主要介紹了vue引用json文件,解決怎么從控制臺(tái)把數(shù)據(jù)移到j(luò)son文件中,只需要直接右擊復(fù)制值即可,需要的朋友可以參考下
    2022-09-09
  • Vuejs第十二篇之動(dòng)態(tài)組件全面解析

    Vuejs第十二篇之動(dòng)態(tài)組件全面解析

    組件(Component)是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。接下來通過本文給大家介紹Vuejs第十二篇之動(dòng)態(tài)組件,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-09-09
  • vue 解決IOS10低版本白屏的問題

    vue 解決IOS10低版本白屏的問題

    這篇文章主要介紹了vue 解決IOS10低版本白屏的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue項(xiàng)目中路徑使用@和~的區(qū)別及說明

    vue項(xiàng)目中路徑使用@和~的區(qū)別及說明

    這篇文章主要介紹了vue項(xiàng)目中路徑使用@和~的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • vue-cli初始化項(xiàng)目中使用less的方法

    vue-cli初始化項(xiàng)目中使用less的方法

    vue-cli 是 vue.js 的腳手架工具,可以幫助我們編寫基礎(chǔ)代碼、快速搭建開發(fā)環(huán)境。下面這篇文章主要給大家介紹了關(guān)于vue-cli初始化項(xiàng)目中使用less的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來一起看看吧
    2018-08-08

最新評(píng)論