自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

更強(qiáng)大、更靈活! defineModel 重新定義雙向綁定

開(kāi)發(fā) 前端
defineModel? 的引入不僅簡(jiǎn)化了 Vue 中的雙向綁定,還為開(kāi)發(fā)者提供了更強(qiáng)大的工具來(lái)處理復(fù)雜的數(shù)據(jù)流。隨著 Vue 生態(tài)的不斷發(fā)展,defineModel 必將在更多場(chǎng)景中發(fā)揮其重要作用,成為 Vue 開(kāi)發(fā)者的得力助手。

前言

在 Vue 3.4 中,defineModel 宏的引入標(biāo)志著 Vue 雙向綁定機(jī)制的一次重大革新。作為 Composition API 的重要補(bǔ)充,defineModel 不僅簡(jiǎn)化了代碼結(jié)構(gòu),還顯著提升了開(kāi)發(fā)效率和代碼可維護(hù)性。本文將深入探討 defineModel 的核心原理、最佳實(shí)踐以及在實(shí)際項(xiàng)目中的應(yīng)用場(chǎng)景,展示其如何優(yōu)雅地解決傳統(tǒng) v-model 實(shí)現(xiàn)中的痛點(diǎn)。

傳統(tǒng)雙向綁定的痛點(diǎn)

在 defineModel 出現(xiàn)之前,Vue 的雙向綁定主要依賴于 v-model 和手動(dòng)管理 props 和 emits。雖然這些方法有效,但在復(fù)雜場(chǎng)景下,代碼往往顯得冗長(zhǎng)且難以維護(hù)。

方案一:手動(dòng)管理 props 和 emits

1. 父組件傳遞數(shù)據(jù)的同時(shí)需要實(shí)現(xiàn)一個(gè)修改數(shù)據(jù)的方法傳遞給子組件

<!-- 父組件 -->
<child :carObj="carObj" @carPriceAdd="carPriceAdd" />

<script setup lang="ts">
const carObj = ref<ICarObj>({
    brand: 'BMW',
    price: 100000
})

const carPriceAdd = () => {
    carObj.value.price += 1000
}
</script>

2. 子組件接收數(shù)據(jù)的同時(shí)還需要接收父組件傳遞過(guò)來(lái)的事件,并通過(guò)emits調(diào)用,就可以修改父組件的數(shù)據(jù)了

<script setup lang="ts">
const props = defineProps<{
  modelValue: IUser,  // v-model
  carObj: ICarObj // v-bind
}>()
const emits = defineEmits(['carPriceAdd'])
const priceAdd = () => {
    emits('carPriceAdd')
    console.log(props.carObj.price)
}
</script>

方案二:使用 v-model

還可以借助v-model,可以省去父組件定義修改數(shù)據(jù)的方法并傳遞給子組件這一步

1. 父組件通過(guò)v-model傳遞數(shù)據(jù)給子組件

<child v-model="user" />
<script setup lang="ts">
const user = ref<IUser>({
    name: 'song',
    age: 18
})
</script>

2. 子組件在接受數(shù)據(jù)的同時(shí)也還要接受事件,只不過(guò)這個(gè)事件并不是父組件顯式傳遞過(guò)來(lái)的,并且格式有點(diǎn)區(qū)別

<script setup lang="ts">
const props = defineProps<{
  modelValue: IUser,  // v-model
  carObj: ICarObj // v-bind
}>()
const emits = defineEmits(['update:modelValue'])
const ageAdd = () => {
    emits('update:modelValue', {
        ...props.modelValue,
        age: props.modelValue.age + 1
    })
    // console.log(props.modelValue.age)
}
</script>
  • v-model默認(rèn)傳遞過(guò)來(lái)的參數(shù)名為:modelValue,默認(rèn)傳遞過(guò)來(lái)的事件為:update:modelValue
  • 默認(rèn)參數(shù)名在父組件中可以修改,格式為:v-model:name,同理子組件中接受的數(shù)據(jù)名與事件名改成一致即可

盡管 v-model 簡(jiǎn)化了部分代碼,但仍需手動(dòng)管理 props 和 emits,尤其是在處理多個(gè)雙向綁定時(shí),代碼復(fù)雜度顯著增加。所以從 Vue 3.4 開(kāi)始,官方更加推薦使用 defineModel() 宏來(lái)實(shí)現(xiàn)雙向數(shù)據(jù)綁定。

defineModel 的誕生:簡(jiǎn)化雙向綁定

?

defineModel 是一個(gè)編譯器宏,用于在 Vue 組件中定義雙向綁定的 prop。它本質(zhì)上是對(duì) v-model 指令的語(yǔ)法糖,但提供了更簡(jiǎn)潔、更直觀的語(yǔ)法。

基本用法

父組件還是不變,只需通過(guò)v-model傳遞數(shù)據(jù)給子組件即可

<child v-model="user" />
<script setup lang="ts">
const user = ref<IUser>({
    name: 'song',
    age: 18
})
</script>

通過(guò) defineModel,子組件無(wú)需再顯式接收 props 和 emits,直接通過(guò) defineModel 返回的 ref 對(duì)象即可實(shí)現(xiàn)雙向綁定。

<script setup lang="ts">
// 通過(guò)defineModel聲明父組件傳遞過(guò)來(lái)的數(shù)據(jù),返回一個(gè)ref對(duì)象
const user = defineModel<IUser>('user', {
    default: {}
})
// 子組件可以直接修改剛剛通過(guò)defineModel聲明的數(shù)據(jù),不需要通過(guò)emits,父組件會(huì)自動(dòng)更新
const ageAdd = () => {
    user.value.age += 1
}
</script>

修飾符與轉(zhuǎn)換器

在一些特殊場(chǎng)景下,我們可能還需要使用v-model的修飾符功能

比如:清除字符串末尾的空格

父組件添加修飾符

<!-- 父組件 -->
<child v-model:userName.trim="userName" />

子組件獲取修飾符

在子組件中,我們可以通過(guò)解構(gòu) defineModel() 的返回值,來(lái)獲取父組件添加到子組件 v-model 的修飾符:

// 通過(guò)defineModel聲明父組件傳遞過(guò)來(lái)的數(shù)據(jù),返回一個(gè)ref對(duì)象
const [user, filters] = defineModel<IUser>({
    default: {},
    set: (val) => {
        console.log('set', val)
    }
})

修飾符格式

默認(rèn)格式為:第一個(gè)參數(shù)為props值,第二個(gè)參數(shù)為對(duì)應(yīng)的修飾符(修飾符可能有多個(gè),格式如下)

轉(zhuǎn)換器處理數(shù)據(jù)轉(zhuǎn)換器處理數(shù)據(jù)

當(dāng)存在修飾符時(shí),我們可能需要在讀取或?qū)⑵渫交馗附M件時(shí)對(duì)其值進(jìn)行轉(zhuǎn)換。我們可以通過(guò)使用 get 和 set 轉(zhuǎn)換器選項(xiàng)來(lái)實(shí)現(xiàn)這一點(diǎn):

const [userName, userNameFilters] = defineModel('userName',{
    default: '',
    set: (val) => {
        if(userNameFilters.trim) {
            return val.trim()
        }
        return val
    }
})

多Model

我們可以在單個(gè)組件實(shí)例上創(chuàng)建多個(gè)v-model的雙向綁定

比如:

<!-- 父組件 -->
<child v-model.trim="user" v-model:userName.trim.number="userName" />

子組件同時(shí)接受多個(gè)v-model

// 通過(guò)defineModel聲明父組件傳遞過(guò)來(lái)的數(shù)據(jù),返回一個(gè)ref對(duì)象
const [user, filters] = defineModel<IUser>({
    default: {},
    set: (val) => {
        console.log('set', val)
    }
})

const [userName, userNameFilters] = defineModel<string>('userName',{
    default: '',
    set: (val) => {
        if(userNameFilters.trim) {
            return val.trim()
        }
        return val
    }
})

實(shí)現(xiàn)原理:defineModel 的背后

了解了怎么用的,最后再來(lái)看看它是怎么實(shí)現(xiàn)的

我們知道defineModel其實(shí)就是v-model的語(yǔ)法糖,所以我們可以對(duì)比下兩種寫(xiě)法最后的編譯結(jié)果有什么區(qū)別?

不使用defineModel

圖片圖片

最終就是props與emits分別接收變量與事件

使用defineModel

圖片圖片

使用defineModel后,我們?cè)诮M件中雖然可以不用像之前那樣顯式的接收props與emits,但Vue同樣會(huì)幫我們生成這兩塊內(nèi)容,并且可以看到兩者紅框內(nèi)基本一樣,只不過(guò)使用defineModel會(huì)多一個(gè)修飾符的接收

defineModel 會(huì)被編譯成一個(gè) _useModel 方法,這是實(shí)現(xiàn)雙向綁定的核心。從編譯后的代碼可以看出,defineModel 會(huì)接收父組件傳遞的 props 和 emits,并利用 props 中的值進(jìn)行初始化。當(dāng)數(shù)據(jù)需要更新時(shí),它會(huì)調(diào)用 emits 中注冊(cè)的事件來(lái)通知父組件。然而,在實(shí)際開(kāi)發(fā)中,我們通常不會(huì)直接操作 props 和 emits,而是通過(guò) defineModel 返回的 ref 值來(lái)直接操作數(shù)據(jù)。因此,_useModel 的核心任務(wù)是確保這個(gè) ref 值與父組件傳遞的 props 值保持同步,從而實(shí)現(xiàn)數(shù)據(jù)的雙向綁定。

結(jié)語(yǔ):defineModel 的未來(lái)

defineModel 的引入不僅簡(jiǎn)化了 Vue 中的雙向綁定,還為開(kāi)發(fā)者提供了更強(qiáng)大的工具來(lái)處理復(fù)雜的數(shù)據(jù)流。隨著 Vue 生態(tài)的不斷發(fā)展,defineModel 必將在更多場(chǎng)景中發(fā)揮其重要作用,成為 Vue 開(kāi)發(fā)者的得力助手。

通過(guò)本文的深入探討,相信你已經(jīng)對(duì) defineModel 有了更全面的理解。在實(shí)際項(xiàng)目中,不妨嘗試使用 defineModel,體驗(yàn)其帶來(lái)的便利與高效。

責(zé)任編輯:武曉燕 來(lái)源: 前端南玖
相關(guān)推薦

2024-11-21 15:48:40

2017-02-09 08:47:44

2021-09-17 16:05:09

戴爾科技

2020-08-17 07:00:00

混合云云計(jì)算技術(shù)

2017-10-13 22:18:53

物聯(lián)網(wǎng)

2009-05-18 09:12:00

ASON自動(dòng)交換光網(wǎng)絡(luò)

2009-11-05 11:42:45

Unix專(zhuān)家

2014-06-03 09:15:17

融合數(shù)據(jù)中心華三

2019-06-20 08:13:33

物聯(lián)網(wǎng)IOT技術(shù)

2018-03-04 22:41:04

區(qū)塊鏈互聯(lián)網(wǎng)信息傳遞

2018-11-29 09:30:04

區(qū)塊鏈教育

2024-08-19 12:37:06

2015-08-04 09:03:27

數(shù)據(jù)中心hyperconver超級(jí)融合系統(tǒng)

2023-06-06 19:24:06

KubernetesSpark

2022-06-13 19:12:15

云計(jì)算云原生

2019-07-03 09:32:11

APIGGVKong

2014-12-12 15:36:49

ThinkPad

2021-06-29 10:34:41

IT風(fēng)險(xiǎn)首席信息官CIO

2017-01-10 13:18:32

IBM存儲(chǔ)IBM存儲(chǔ)

2023-02-09 11:12:41

語(yǔ)音識(shí)別人工智能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)