您好,登錄后才能下訂單哦!
這篇文章主要介紹“vue3中的v-model怎么使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“vue3中的v-model怎么使用”文章能幫助大家解決問題。
以 自定義組件 CustomInput
舉例
<script setup> const txt = ref(''); </script> <template> <CustomInput v-model="txt" /> </template>
v-model
會被展開為如下的形式
<CustomInput :modelValue="txt" @update:modelValue="newValue => txt = newValue" />
<CustomInput>
組件內部需要做兩件事:
將內部原生 <input>
元素的 value
attribute 綁定到 modelValue
prop
當原生的 input
事件觸發時,觸發一個攜帶了新值的 update:modelValue
自定義事件
這里是相應的代碼:
<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>
有些人會覺得這種寫法過于繁瑣,會導致標簽代碼變得冗長
另一種在組件內實現 v-model
的方式是使用一個可寫的,同時具有 getter 和 setter 的 computed
屬性
使用computed
屬性時, get
方法需返回 modelValue
prop,而 set
方法需觸發相應的事件
<script setup> const value = computed({ get() { return props.modelValue }, set(value) { emit("update:modelValue", value) } }) </script> <template> <input v-model="value" /> </template>
這種寫法可以簡化標簽中的屬性,邏輯清晰
單個屬性可以使用 v-model
輕松搞定,如果多個屬性都需要雙向綁定呢?
默認情況下,v-model
在組件上都是使用 modelValue
作為 prop,并以 update:modelValue
作為對應的事件
但我們可以通過給 v-model
指定一個參數來更改這些名字:
<template> <CustomInput v-model:first-name="first" v-model:last-name="last" /> </template>
同樣的,也可以用兩種方式綁定,只是 prop
從原來的 modelValue
變為了傳入的參數名,對應的事件也變成了 update:參數名
<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>
在一個復雜的組件中,如果多個字段需要雙向綁定,如果使用上文所示方法的話,會有一些繁瑣
介紹兩種雙向綁定對象的做法
定義父組件 searchBar
為一個復雜表單組件
<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
組件內,我們接收 modelValue
并定義類型為 Object
<template> <div> <!-- <input type="text" v-model="modelValue.keyword"> 可以實現雙向綁定 --> <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">
雖然可以直接進行雙向綁定,但是這樣會破壞單項數據流
和上文的 emit
觸發事件一樣,但是傳遞的數據則變成了對象
雖然使用 emit 可以觸發雙向綁定,但是過于繁瑣,下面介紹一種更優雅的寫法,可以說是一種奇技淫巧 -- computed + prxoy
如果使用 computed
綁定,你可能會寫出這種代碼
<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) // 發現沒有打印 emit("update:modelValue", { ...props.modelValue, keyword: value }) } }) <script>
但是當你輸入的時候,你會發現并沒有觸發 setter
, 因為 computed
會做一層代理,代理對象沒有發生修改
如果想要觸發 setter
,如下圖:
// 只有這樣才會變化 model.value = { keyword:"asdfad" }
這種方法無法觸發 setter
,也就無法雙向綁定,該怎么辦呢?
在 getter
中返回 一個 代理對象!在 getter
中返回 一個 代理對象!在 getter
中返回 一個 代理對象!
因為 proxy
代理的對象是和被代理對象屬性是保持一致的,所以我們使用 proxy
包裹原對象
那么 v-model
綁定的是代理之后的對象,如果代理對象屬性發生了改變,則會觸發代理對象中的 set
方法,此時我們可以觸發 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
有一些內置的修飾符,例如 .trim
,.number
和 .lazy
。
在某些場景下,我們可能想要一個自定義組件的 v-model
支持自定義的修飾符。
我們來創建一個自定義的修飾符 capitalize
,它會自動將 v-model
綁定輸入的字符串值第一個字母轉為大寫:
<CustomInput v-model.capitalize="txt" />
我們添加了capitalize
修飾符,他會被自動傳入到 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>
關于“vue3中的v-model怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。