vue3中v-model的用法詳解
綁定單個(gè)屬性
基礎(chǔ)綁定
以 自定義組件 CustomInput 舉例
<script setup>
const txt = ref('');
</script>
<template>
<CustomInput v-model="txt" />
</template>v-model 會(huì)被展開為如下的形式
<CustomInput :modelValue="txt" @update:modelValue="newValue => txt = newValue" />
<CustomInput> 組件內(nèi)部需要做兩件事:
- 將內(nèi)部原生
<input>元素的valueattribute 綁定到modelValueprop - 當(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ì)覺得這種寫法過于繁瑣,會(huì)導(dǎo)致標(biāo)簽代碼變得冗長
另一種在組件內(nèi)實(shí)現(xiàn) v-model 的方式是使用一個(gè)可寫的,同時(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>這種寫法可以簡化標(biāo)簽中的屬性,邏輯清晰
單個(gè)屬性可以使用 v-model 輕松搞定,如果多個(gè)屬性都需要雙向綁定呢?
?? v-model 綁定多個(gè)屬性
默認(rèn)情況下,v-model 在組件上都是使用 modelValue 作為 prop,并以 update:modelValue 作為對應(yīng)的事件
但我們可以通過給 v-model 指定一個(gè)參數(shù)來更改這些名字:
<template>
<CustomInput v-model:first-name="first" v-model:last-name="last" />
</template>同樣的,也可以用兩種方式綁定,只是 prop 從原來的 modelValue 變?yōu)榱藗魅氲膮?shù)名,對應(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>?? 綁定對象
在一個(gè)復(fù)雜的組件中,如果多個(gè)字段需要雙向綁定,如果使用上文所示方法的話,會(huì)有一些繁瑣
介紹兩種雙向綁定對象的做法
定義父組件 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 并定義類型為 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>如果傳入對象的話,如注釋所介紹的那樣
<input type="text" v-model="modelValue.keyword">雖然可以直接進(jìn)行雙向綁定,但是這樣會(huì)破壞單項(xiàng)數(shù)據(jù)流
和上文的 emit 觸發(fā)事件一樣,但是傳遞的數(shù)據(jù)則變成了對象
雖然使用 emit 可以觸發(fā)雙向綁定,但是過于繁瑣,下面介紹一種更優(yōu)雅的寫法,可以說是一種奇技淫巧 -- computed + prxoy
如果使用 computed 綁定,你可能會(huì)寫出這種代碼
<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)沒有打印
emit("update:modelValue", {
...props.modelValue,
keyword: value
})
}
})
<script>但是當(dāng)你輸入的時(shí)候,你會(huì)發(fā)現(xiàn)并沒有觸發(fā) setter, 因?yàn)?nbsp;computed 會(huì)做一層代理,代理對象沒有發(fā)生修改
如果想要觸發(fā) setter ,如下圖:
// 只有這樣才會(huì)變化
model.value = {
keyword:"asdfad"
}這種方法無法觸發(fā) setter,也就無法雙向綁定,該怎么辦呢?
在 getter 中返回 一個(gè) 代理對象!在 getter 中返回 一個(gè) 代理對象!在 getter 中返回 一個(gè) 代理對象!
因?yàn)?proxy代理的對象是和被代理對象屬性是保持一致的,所以我們使用 proxy 包裹原對象
那么 v-model 綁定的是代理之后的對象,如果代理對象屬性發(fā)生了改變,則會(huì)觸發(fā)代理對象中的 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。
在某些場景下,我們可能想要一個(gè)自定義組件的 v-model 支持自定義的修飾符。
我們來創(chuàng)建一個(gè)自定義的修飾符 capitalize,它會(huì)自動(dòng)將 v-model 綁定輸入的字符串值第一個(gè)字母轉(zhuǎn)為大寫:
<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用法 的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在vue react中如何使用Web Components組件
這篇文章主要介紹了在vue react中如何使用Web Components組件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
Vue中使用jsencrypt進(jìn)行RSA非對稱加密的操作方法
這篇文章主要介紹了Vue中使用jsencrypt進(jìn)行RSA非對稱加密,在這里需要注意要加密的數(shù)據(jù)必須是字符串,對Vue?RSA非對稱加密相關(guān)知識感興趣的朋友一起看看吧2022-04-04
vue實(shí)現(xiàn)登錄時(shí)的圖片驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)登錄時(shí)的圖片驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
vue后臺(tái)管理如何配置動(dòng)態(tài)路由菜單
這篇文章主要介紹了vue后臺(tái)管理如何配置動(dòng)態(tài)路由菜單,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue?項(xiàng)目的成功發(fā)布和部署的實(shí)現(xiàn)
本文主要介紹了Vue?項(xiàng)目的成功發(fā)布和部署的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
結(jié)合el-upload組件實(shí)現(xiàn)大文件分片上傳功能
Element UI的el-upload上傳組件相信各位小伙伴都已經(jīng)非常熟悉,最近接了一個(gè)新需求,要求在el-upload組件基礎(chǔ)上實(shí)現(xiàn)分片上傳功能,即小于等于5M文件正常上傳,大于5M文件切成5M每片上傳,那么這個(gè)功能怎么實(shí)現(xiàn)呢?一起看看吧2022-09-09
vue請求接口并且攜帶token的實(shí)現(xiàn)
本文主要介紹了vue請求接口并且攜帶token的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
vue.js實(shí)現(xiàn)的綁定class操作示例
這篇文章主要介紹了vue.js實(shí)現(xiàn)的綁定class操作,結(jié)合實(shí)例形式分析了vue.js綁定class常見的3種操作技巧,需要的朋友可以參考下2018-07-07
Vue3.0路由跳轉(zhuǎn)攜帶參數(shù)的示例詳解
這篇文章主要介紹了Vue3.0路由跳轉(zhuǎn)攜帶參數(shù)的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04

