成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

更強大、更靈活! defineModel 重新定義雙向綁定

開發 前端
defineModel? 的引入不僅簡化了 Vue 中的雙向綁定,還為開發者提供了更強大的工具來處理復雜的數據流。隨著 Vue 生態的不斷發展,defineModel 必將在更多場景中發揮其重要作用,成為 Vue 開發者的得力助手。

前言

在 Vue 3.4 中,defineModel 宏的引入標志著 Vue 雙向綁定機制的一次重大革新。作為 Composition API 的重要補充,defineModel 不僅簡化了代碼結構,還顯著提升了開發效率和代碼可維護性。本文將深入探討 defineModel 的核心原理、最佳實踐以及在實際項目中的應用場景,展示其如何優雅地解決傳統 v-model 實現中的痛點。

傳統雙向綁定的痛點

在 defineModel 出現之前,Vue 的雙向綁定主要依賴于 v-model 和手動管理 props 和 emits。雖然這些方法有效,但在復雜場景下,代碼往往顯得冗長且難以維護。

方案一:手動管理 props 和 emits

1. 父組件傳遞數據的同時需要實現一個修改數據的方法傳遞給子組件

<!-- 父組件 -->
<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. 子組件接收數據的同時還需要接收父組件傳遞過來的事件,并通過emits調用,就可以修改父組件的數據了

<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,可以省去父組件定義修改數據的方法并傳遞給子組件這一步

1. 父組件通過v-model傳遞數據給子組件

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

2. 子組件在接受數據的同時也還要接受事件,只不過這個事件并不是父組件顯式傳遞過來的,并且格式有點區別

<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默認傳遞過來的參數名為:modelValue,默認傳遞過來的事件為:update:modelValue
  • 默認參數名在父組件中可以修改,格式為:v-model:name,同理子組件中接受的數據名與事件名改成一致即可

盡管 v-model 簡化了部分代碼,但仍需手動管理 props 和 emits,尤其是在處理多個雙向綁定時,代碼復雜度顯著增加。所以從 Vue 3.4 開始,官方更加推薦使用 defineModel() 宏來實現雙向數據綁定。

defineModel 的誕生:簡化雙向綁定

?

defineModel 是一個編譯器宏,用于在 Vue 組件中定義雙向綁定的 prop。它本質上是對 v-model 指令的語法糖,但提供了更簡潔、更直觀的語法。

基本用法

父組件還是不變,只需通過v-model傳遞數據給子組件即可

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

通過 defineModel,子組件無需再顯式接收 props 和 emits,直接通過 defineModel 返回的 ref 對象即可實現雙向綁定。

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

修飾符與轉換器

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

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

父組件添加修飾符

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

子組件獲取修飾符

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

// 通過defineModel聲明父組件傳遞過來的數據,返回一個ref對象
const [user, filters] = defineModel<IUser>({
    default: {},
    set: (val) => {
        console.log('set', val)
    }
})

修飾符格式

默認格式為:第一個參數為props值,第二個參數為對應的修飾符(修飾符可能有多個,格式如下)

轉換器處理數據轉換器處理數據

當存在修飾符時,我們可能需要在讀取或將其同步回父組件時對其值進行轉換。我們可以通過使用 get 和 set 轉換器選項來實現這一點:

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

多Model

我們可以在單個組件實例上創建多個v-model的雙向綁定

比如:

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

子組件同時接受多個v-model

// 通過defineModel聲明父組件傳遞過來的數據,返回一個ref對象
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
    }
})

實現原理:defineModel 的背后

了解了怎么用的,最后再來看看它是怎么實現的

我們知道defineModel其實就是v-model的語法糖,所以我們可以對比下兩種寫法最后的編譯結果有什么區別?

不使用defineModel

圖片圖片

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

使用defineModel

圖片圖片

使用defineModel后,我們在組件中雖然可以不用像之前那樣顯式的接收props與emits,但Vue同樣會幫我們生成這兩塊內容,并且可以看到兩者紅框內基本一樣,只不過使用defineModel會多一個修飾符的接收

defineModel 會被編譯成一個 _useModel 方法,這是實現雙向綁定的核心。從編譯后的代碼可以看出,defineModel 會接收父組件傳遞的 props 和 emits,并利用 props 中的值進行初始化。當數據需要更新時,它會調用 emits 中注冊的事件來通知父組件。然而,在實際開發中,我們通常不會直接操作 props 和 emits,而是通過 defineModel 返回的 ref 值來直接操作數據。因此,_useModel 的核心任務是確保這個 ref 值與父組件傳遞的 props 值保持同步,從而實現數據的雙向綁定。

結語:defineModel 的未來

defineModel 的引入不僅簡化了 Vue 中的雙向綁定,還為開發者提供了更強大的工具來處理復雜的數據流。隨著 Vue 生態的不斷發展,defineModel 必將在更多場景中發揮其重要作用,成為 Vue 開發者的得力助手。

通過本文的深入探討,相信你已經對 defineModel 有了更全面的理解。在實際項目中,不妨嘗試使用 defineModel,體驗其帶來的便利與高效。

責任編輯:武曉燕 來源: 前端南玖
相關推薦

2024-11-21 15:48:40

2017-02-09 08:47:44

2021-09-17 16:05:09

戴爾科技

2020-08-17 07:00:00

混合云云計算技術

2009-05-18 09:12:00

ASON自動交換光網絡

2017-10-13 22:18:53

物聯網

2023-06-06 19:24:06

KubernetesSpark

2009-11-05 11:42:45

Unix專家

2014-06-03 09:15:17

融合數據中心華三

2019-06-20 08:13:33

物聯網IOT技術

2015-08-04 09:03:27

數據中心hyperconver超級融合系統

2018-03-04 22:41:04

區塊鏈互聯網信息傳遞

2024-08-19 12:37:06

2018-11-29 09:30:04

區塊鏈教育

2014-12-12 15:36:49

ThinkPad

2022-06-13 19:12:15

云計算云原生

2023-02-09 11:12:41

語音識別人工智能

2019-07-03 09:32:11

APIGGVKong

2021-06-29 10:34:41

IT風險首席信息官CIO

2017-01-10 13:18:32

IBM存儲IBM存儲
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久一区二区三区四区 | 国产区精品 | 欧美一级黄色片免费观看 | 国产高清免费 | 激情三区 | 亚洲三区在线观看 | www日韩| 羞羞的视频免费在线观看 | 在线伊人| 性做久久久久久免费观看欧美 | 精品国产18久久久久久二百 | 国产特级毛片aaaaaa喷潮 | 97人人澡人人爽91综合色 | 久久99国产精品 | 国产精品一区在线 | 精品久久久久久久久久久 | 精品一区二区三区在线观看国产 | 亚洲一区中文字幕 | 亚洲国产成人精品女人久久久 | 日本a∨精品中文字幕在线 亚洲91视频 | 中文字幕一区二区三区四区 | 视频在线观看一区二区 | 亚洲成人网在线播放 | 久久久久一区 | 81精品国产乱码久久久久久 | 亚洲精品久久久久中文字幕欢迎你 | 午夜性色a√在线视频观看9 | 久久精品网 | 色999视频 | 国产精品海角社区在线观看 | 99在线观看| 亚洲国产精品va在线看黑人 | 亚洲综合在线视频 | 黄色一级片在线播放 | 亚洲视频免费在线看 | 亚洲视频免费播放 | 天天干天天爱天天爽 | 国产精品一区二区免费看 | 另类 综合 日韩 欧美 亚洲 | 久久里面有精品 | 中文字幕亚洲欧美日韩在线不卡 |