Ambil komponen tersuai CustomInput
sebagai contoh
<script setup> const txt = ref(''); </script> <template> <CustomInput v-model="txt" /> </template>
v-model
akan dikembangkan ke dalam bentuk berikut
<CustomInput :modelValue="txt" @update:modelValue="newValue => txt = newValue" />
<CustomInput>
Dua perkara perlu dilakukan di dalam komponen:
Ikat atribut <input>
unsur asli dalaman value
pada prop modelValue
Apabila acara input
asli dicetuskan, acara tersuai update:modelValue
yang membawa nilai baharu dicetuskan
Berikut ialah yang sepadan kod:
<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>
Sesetengah orang mungkin berpendapat bahawa cara penulisan ini terlalu rumit dan akan menyebabkan kod tag menjadi panjang
Cara lain untuk melaksanakan v-model
dalam komponen ialah menggunakan boleh ditulis, dengan Apabila menggunakan atribut computed
getter dan setter
, kaedah computed
perlu mengembalikan get
prop, dan kaedah modelValue
perlu mencetuskan Peristiwa yang sepadan set
<script setup> const value = computed({ get() { return props.modelValue }, set(value) { emit("update:modelValue", value) } }) </script> <template> <input v-model="value" /> </template>
Bagaimana jika berbilang atribut memerlukan pengikatan dua hala?v-model
menggunakan v-model
sebagai prop pada komponen dan menggunakan modelValue
sebagai acara yang sepadan update:modelValue
: v-model
<template> <CustomInput v-model:first-name="first" v-model:last-name="last" /> </template>
berubah daripada prop
asal kepada diluluskan dalam Nama parameter, peristiwa yang sepadan juga telah menjadi 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>
sebagai komponen bentuk komplekssearchBar
<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>
komponen, kami menerima searchBar
dan mentakrifkan jenis sebagai 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>
Jika objek dimasukkan, seperti yang diterangkan dalam ulasanadalah sama dengan peristiwa pencetus
walaupun ia boleh dilakukan secara langsung pengikatan dua hala, tetapi ini akan memusnahkan<input type="text" v-model="modelValue.keyword">
aliran data tunggal
di atas, tetapi data yang diluluskan menjadi objekemit
computed + prxoy
mengikat, anda boleh menulis kod ini 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>
tidak dicetuskan, kerana setter
akan melakukan lapisan proksi, Objek proksi belum diubah suai computed
, seperti yang ditunjukkan di bawah: setter
// 只有这样才会变化 model.value = { keyword:"asdfad" }
, dan oleh itu pengikatan dua hala tidak boleh dilakukan Apa yang perlu saya lakukan? setter
objek proksi dalam getter
! mengembalikan objek proksi dalam getter
! mengembalikan objek proksi dalam getter
!
konsisten dengan objek proksi, kami menggunakan proxy
untuk membalut objek asal proxy
ialah terikat kepada Untuk objek selepas proksi, jika sifat objek proksi berubah, kaedah v-model
dalam objek proksi akan dicetuskan Pada masa ini, kita boleh mencetuskan pengubah suai 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 }) } })
mempunyai beberapa pengubah suai terbina dalam, seperti v-model
, .trim
dan .number
. .lazy
menyokong pengubah suai tersuai. v-model
, yang secara automatik akan menukar huruf pertama nilai rentetan yang terikat kepada capitalize
kepada huruf besar: v-model
<CustomInput v-model.capitalize="txt" />
, ia akan dihantar secara automatik ke dalam capitalize
<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>
prop
modelModifiers
dalam Atas ialah kandungan terperinci Cara menggunakan v-model dalam vue3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!