vue3中v-model的用法詳解
綁定單個(gè)屬性
基礎(chǔ)綁定
以 自定義組件 CustomInput
舉例
<script setup> const txt = ref(''); </script> <template> <CustomInput v-model="txt" /> </template>
v-model
會(huì)被展開(kāi)為如下的形式
<CustomInput :modelValue="txt" @update:modelValue="newValue => txt = newValue" />
<CustomInput>
組件內(nèi)部需要做兩件事:
- 將內(nèi)部原生
<input>
元素的value
attribute 綁定到modelValue
prop - 當(dāng)原生的
input
事件觸發(fā)時(shí),觸發(fā)一個(gè)攜帶了新值的update:modelValue
自定義事件
這里是相應(yīng)的代碼:
<script setup> const props = defineProps({ 'modelValue': String, }) const emit = defineEmits(["update:modelValue"]) </script> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template>
有些人會(huì)覺(jué)得這種寫(xiě)法過(guò)于繁瑣,會(huì)導(dǎo)致標(biāo)簽代碼變得冗長(zhǎng)
另一種在組件內(nèi)實(shí)現(xiàn) v-model
的方式是使用一個(gè)可寫(xiě)的,同時(shí)具有 getter 和 setter 的 computed
屬性
computed 綁定
使用computed
屬性時(shí), get
方法需返回 modelValue
prop,而 set
方法需觸發(fā)相應(yīng)的事件
<script setup> const value = computed({ get() { return props.modelValue }, set(value) { emit("update:modelValue", value) } }) </script> <template> <input v-model="value" /> </template>
這種寫(xiě)法可以簡(jiǎn)化標(biāo)簽中的屬性,邏輯清晰
單個(gè)屬性可以使用 v-model
輕松搞定,如果多個(gè)屬性都需要雙向綁定呢?
?? v-model 綁定多個(gè)屬性
默認(rèn)情況下,v-model
在組件上都是使用 modelValue
作為 prop,并以 update:modelValue
作為對(duì)應(yīng)的事件
但我們可以通過(guò)給 v-model
指定一個(gè)參數(shù)來(lái)更改這些名字:
<template> <CustomInput v-model:first-name="first" v-model:last-name="last" /> </template>
同樣的,也可以用兩種方式綁定,只是 prop
從原來(lái)的 modelValue
變?yōu)榱藗魅氲膮?shù)名,對(duì)應(yīng)的事件也變成了 update:參數(shù)名
<script setup> const props = defineProps({ firstName: String, lastName: String, }) // 在computed中 使用 const emit = defineEmits(['update:firstName', 'update:lastName']) </script> <template> <input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)" /> <input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)" /> </template>
?? 綁定對(duì)象
在一個(gè)復(fù)雜的組件中,如果多個(gè)字段需要雙向綁定,如果使用上文所示方法的話,會(huì)有一些繁瑣
介紹兩種雙向綁定對(duì)象的做法
定義父組件 searchBar
為一個(gè)復(fù)雜表單組件
<script setup> import { ref } from "vue" const modelValue = ref({ keyword: "123", selectValue: "", options: [ { label: "全部", value: "" }, { label: "a1", value: "1" }, { label: "a2", value: "2" }, ] }) </script> <template> <searchBar v-model="modelValue" /> </template>
那么在 searchBar
組件內(nèi),我們接收 modelValue
并定義類(lèi)型為 Object
<template> <div> <!-- <input type="text" v-model="modelValue.keyword"> 可以實(shí)現(xiàn)雙向綁定 --> <input type="text" :value="modelValue.keyword" @input="handleKeywordChange" > <select v-model="modelValue.selectValue"> <option v-for="o in modelValue.options" :key="o.value" :value="o.value"> {{ o.label }} </option> </select> </div> </template> <script lang="ts" setup> const props = defineProps({ modelValue: { type: Object, default: () => ({}) } }) const emit = defineEmits(["update:modelValue"]); // 以 input 舉例 const handleKeywordChange=(val)=>{ emit("update:modelValue",{ ...props.modelValue, keyword:val.target.value }) } </script>
如果傳入對(duì)象的話,如注釋所介紹的那樣
<input type="text" v-model="modelValue.keyword">
雖然可以直接進(jìn)行雙向綁定,但是這樣會(huì)破壞單項(xiàng)數(shù)據(jù)流
和上文的 emit
觸發(fā)事件一樣,但是傳遞的數(shù)據(jù)則變成了對(duì)象
雖然使用 emit 可以觸發(fā)雙向綁定,但是過(guò)于繁瑣,下面介紹一種更優(yōu)雅的寫(xiě)法,可以說(shuō)是一種奇技淫巧 -- computed + prxoy
如果使用 computed
綁定,你可能會(huì)寫(xiě)出這種代碼
<template> <input type="text" v-model="model.keyword"> </template> <script lang="ts" setup> const model = computed({ get() { return props.modelValue }, set(value) { // console.log(value) // 發(fā)現(xiàn)沒(méi)有打印 emit("update:modelValue", { ...props.modelValue, keyword: value }) } }) <script>
但是當(dāng)你輸入的時(shí)候,你會(huì)發(fā)現(xiàn)并沒(méi)有觸發(fā) setter
, 因?yàn)?nbsp;computed
會(huì)做一層代理,代理對(duì)象沒(méi)有發(fā)生修改
如果想要觸發(fā) setter
,如下圖:
// 只有這樣才會(huì)變化 model.value = { keyword:"asdfad" }
這種方法無(wú)法觸發(fā) setter
,也就無(wú)法雙向綁定,該怎么辦呢?
在 getter
中返回 一個(gè) 代理對(duì)象!在 getter
中返回 一個(gè) 代理對(duì)象!在 getter
中返回 一個(gè) 代理對(duì)象!
因?yàn)?proxy
代理的對(duì)象是和被代理對(duì)象屬性是保持一致的,所以我們使用 proxy
包裹原對(duì)象
那么 v-model
綁定的是代理之后的對(duì)象,如果代理對(duì)象屬性發(fā)生了改變,則會(huì)觸發(fā)代理對(duì)象中的 set
方法,此時(shí)我們可以觸發(fā) emit
const model = computed({ get() { return new Proxy(props.modelValue, { set(obj, name, val) { emit("update:modelValue", { ...obj, [name]: val }) return true } }) }, set(value) { emit("update:modelValue", { ...props.modelValue, keyword: value }) } })
修飾符
我們知道 v-model
有一些內(nèi)置的修飾符,例如 .trim
,.number
和 .lazy
。
在某些場(chǎng)景下,我們可能想要一個(gè)自定義組件的 v-model
支持自定義的修飾符。
我們來(lái)創(chuàng)建一個(gè)自定義的修飾符 capitalize
,它會(huì)自動(dòng)將 v-model
綁定輸入的字符串值第一個(gè)字母轉(zhuǎn)為大寫(xiě):
<CustomInput v-model.capitalize="txt" />
我們添加了capitalize
修飾符,他會(huì)被自動(dòng)傳入到 prop
中的 modelModifiers
中
<script setup> const props = defineProps({ modelValue: String, modelModifiers: { default: () => ({}) } }) const emitValue = (e) => { let value = e.target.value; // 使用 修飾符 if (props.modelModifiers.capitalize) { value = value.charAt(0).toUpperCase() + value.slice(1) } emit('update:modelValue', value) } </script> <template> <input :value="modelValue" @input="emitValue" /> </template>
總結(jié)
在 vue
中, 我們可以使用 v-model
指令進(jìn)行很方便的雙向綁定,配合修飾符可以完成很多有趣的功能
以上就是vue3中v-model的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于vue3 v-model用法 的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決vue的router組件component在import時(shí)不能使用變量問(wèn)題
這篇文章主要介紹了解決vue的router組件component在import時(shí)不能使用變量問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07Vue數(shù)據(jù)監(jiān)聽(tīng)方法watch的使用
這篇文章主要介紹了Vue數(shù)據(jù)監(jiān)聽(tīng)方法watch的使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03在vue中使用echarts實(shí)現(xiàn)上浮與下鉆效果
這篇文章主要介紹了在vue中使用echarts實(shí)現(xiàn)上浮與下鉆效果,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11vue父組件中獲取子組件中的數(shù)據(jù)(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇vue父組件中獲取子組件中的數(shù)據(jù)(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09詳解如何創(chuàng)建基于vite的vue項(xiàng)目
vite 這個(gè)是尤大開(kāi)發(fā)的新工具,目的是以后替代webpack,下面這篇文章主要給大家介紹了關(guān)于如何創(chuàng)建基于vite的vue項(xiàng)目的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11vue組件數(shù)據(jù)傳遞、父子組件數(shù)據(jù)獲取,slot,router路由功能示例
這篇文章主要介紹了vue組件數(shù)據(jù)傳遞、父子組件數(shù)據(jù)獲取,slot,router路由功能,結(jié)合實(shí)例形式分析了vue.js組件數(shù)據(jù)傳遞、路由相關(guān)概念、原理及相關(guān)操作技巧,需要的朋友可以參考下2019-03-03vue路由切換之淡入淡出的簡(jiǎn)單實(shí)現(xiàn)
今天小編就為大家分享一篇vue路由切換之淡入淡出的簡(jiǎn)單實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10Vue中el-form標(biāo)簽中的自定義el-select下拉框標(biāo)簽功能
這篇文章主要介紹了Vue中el-form標(biāo)簽中的自定義el-select下拉框標(biāo)簽功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04openlayers6之地圖覆蓋物overlay三種常用用法(popup彈窗marker標(biāo)注text文本)
這篇文章主要介紹了openlayers6之地圖覆蓋物overlay三種常用用法(popup彈窗marker標(biāo)注text文本),主要講overlay三種最常用的案例,感興趣的朋友一起看看吧2021-09-09