Bileşen v-model
Bileşen v-model
Temel Kullanım
v-model
, bir bileşende iki yönlü veri bağlama uygulamak için kullanılabilir.
Vue 3.4 ile birlikte, bunu gerçekleştirmek için önerilen yaklaşım, defineModel()
makrosunu kullanmaktır:
<!-- Child.vue -->
<script setup>
const model = defineModel()
function update() {
model.value++
}
</script>
<template>
<div>Üst bileşende bağlı v-model: {{ model }}</div>
<button @click="update">Arttır</button>
</template>
Üst bileşen, v-model
ile bir değeri bağlayabilir:
<!-- Parent.vue -->
<Child v-model="countModel" />
defineModel()
tarafından döndürülen değer bir ref'dir. Diğer ref'ler gibi erişilebilir ve değiştirilebilir, tek farkla ki bu, bir üst değer ile bir yerel değer arasında iki yönlü bir bağlama olarak işlev görür:
.value
'sı, üstv-model
ile bağlı olan değerle senkronizedir;- Çocuk tarafından değiştirildiğinde, üstte bağlı değer de güncellenir.
Bu, bu ref'i v-model
ile bir yerel giriş elemanına da bağlayabileceğiniz anlamına gelir, bu da yerel giriş elemanlarını sarmayı ve aynı v-model
kullanımını sağlamayı kolaylaştırır:
<script setup>
const model = defineModel()
</script>
<template>
<input v-model="model" />
</template>
Altta Ne Oluyor
defineModel
, bir kolaylık makrosudur. Derleyici bunu aşağıdakilere genişletir:
- Yerel ref'in değeriyle senkronize edilen
modelValue
adlı bir prop; - Yerel ref'in değeri değiştirildiğinde yayılacak olan
update:modelValue
adlı bir olay.
Aşağıdakileri önceden 3.4 öncesinde aynı çocuk bileşeni uygulamak için kullanabilirsiniz:
<!-- Child.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
Sonrasında, üst bileşende v-model="foo"
derlendiğinde:
<!-- Parent.vue -->
<Child
:modelValue="foo"
@update:modelValue="$event => (foo = $event)"
/>
Gördüğünüz gibi, oldukça daha ayrıntılı. Ancak, altında neler olup bittiğini anlamak için yararlıdır.
Çünkü defineModel
bir prop ilan ettiği için, defineModel
'a geçirerek temel prop'un seçeneklerini de belirleyebilirsiniz:
// v-model'i zorunlu kılma
const model = defineModel({ required: true })
// varsayılan bir değer sağlama
const model = defineModel({ default: 0 })
Eğer defineModel
prop'u için bir default
değeri varsa ve üst bileşenden bu prop için herhangi bir değer sağlanmazsa, üst ve alt bileşenler arasında senkronizasyonun bozulmasına neden olabilir. Aşağıdaki örnekte, üstteki myRef
tanımsız, ancak alt bileşenin model
değeri 1'dir:
Alt bileşen:
const model = defineModel({ default: 1 })
Üst bileşen:
const myRef = ref()
<Child v-model="myRef"></Child>
Öncelikle, bir yerel elemanda v-model
kullanımına yeniden göz atalım:
<input v-model="searchText" />
Altta, şablon derleyicisi v-model
'i daha ayrıntılı bir eşdeğeri genişletir. Yani yukarıdaki kod, aşağıdaki gibi işler:
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
Bir bileşende kullanıldığında, v-model
bunun yerine buna genişler:
<CustomInput
:model-value="searchText"
@update:model-value="newValue => searchText = newValue"
/>
Bunun çalışması için, `` bileşeninin iki şeyi yapması gerekir:
- Yerel `
elemanının
valueözelliğini
modelValue` prop'una bağlamak - Yerel bir
input
olayı tetiklendiğinde, yeni değerleupdate:modelValue
özel olayını yaymak
İşte bu şekilde:
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
Artık v-model
bu bileşenle mükemmel bir şekilde çalışmalıdır:
<CustomInput v-model="searchText" />
Bu bileşende v-model
'i uygulamanın bir başka yolu, hem bir getter hem de bir setter ile yazılabilir bir computed
özelliği kullanmaktır. get
yöntemi modelValue
özelliğini döndürmelidir ve set
yöntemi ilgili olayı yaymalıdır:
<!-- CustomInput.vue -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue'],
computed: {
value: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
}
}
}
}
</script>
<template>
<input v-model="value" />
</template>
v-model
Argümanları
Bir bileşende v-model
, bir argümanı da kabul edebilir:
<MyComponent v-model:title="bookTitle" />
Alt bileşende, ilgili argümanı karşılamak için defineModel()
'a bir string geçerek destekleyebiliriz:
<!-- MyComponent.vue -->
<script setup>
const title = defineModel('title')
</script>
<template>
<input type="text" v-model="title" />
</template>
Eğer prop seçeneklerine de ihtiyaç varsa, bunları model isminin ardından geçirmelisiniz:
const title = defineModel('title', { required: true })
3.4 Öncesi Kullanım
<!-- MyComponent.vue -->
<script setup>
defineProps({
title: {
required: true
}
})
defineEmits(['update:title'])
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
Bu durumda, varsayılan modelValue
prop'u ve update:modelValue
olayı yerine, alt bileşen bir title
prop'u beklemeli ve üst değeri güncellemek için update:title
olayını yaymalıdır:
<!-- MyComponent.vue -->
<script>
export default {
props: ['title'],
emits: ['update:title']
}
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
Birden Fazla v-model
Bağlantısı
v-model
argümanlarıile öğrendiğimiz gibi, belirli bir prop ve olayı hedefleme yeteneğini kullanarak, tek bir bileşen örneğinde birden fazla
v-model` bağlamamız mümkün.
Her v-model
, bileşende fazladan seçenekler gerektirmeden farklı bir prop'a senkronize edilir:
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
</script>
<template>
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
</template>
3.4 Öncesi Kullanım
<script setup>
defineProps({
firstName: String,
lastName: String
})
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>
<script>
export default {
props: {
firstName: String,
lastName: String
},
emits: ['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>
v-model
Modifikasyonları ile İlgilenmek
Form giriş bağlamaları hakkında bilgi aldığımızda, v-model
'in dahili modifikasyonları - .trim
, .number
ve .lazy
- olduğunu gördük. Bazı durumlarda, özel bir girdi bileşeninizde v-model
'in özel modifikasyonları desteklemesini de isteyebilirsiniz.
v-model
bağlaması ile sağlanan string'in ilk harfini büyük hale getiren bir özel modifikasyon olan capitalize
örneğini oluşturalım:
<MyComponent v-model.capitalize="myText" />
Bileşen v-model
'ine eklenen modifikasyonlar, alt bileşende defineModel()
dönüş değerini şu şekilde parçalayarak erişilebilir:
<script setup>
const [model, modifiers] = defineModel()
console.log(modifiers) // { capitalize: true }
</script>
<template>
<input type="text" v-model="model" />
</template>
Değerin, modifikasyonlara bağlı olarak nasıl okunacağını veya yazılacağını şartlı olarak ayarlamak için, defineModel()
'a get
ve set
seçenekleri geçebiliriz. Bu iki seçenek, model ref'in elde edilmesi veya ayarlanması sırasında değeri alır ve dönüştürülmüş bir değer döndürmelidir. capitalize
modifikasyonunu gerçekleştirmek içinset
seçeneğini nasıl kullanabileceğimiz:
<script setup>
const [model, modifiers] = defineModel({
set(value) {
if (modifiers.capitalize) {
return value.charAt(0).toUpperCase() + value.slice(1)
}
return value
}
})
</script>
<template>
<input type="text" v-model="model" />
</template>
3.4 Öncesi Kullanım
<script setup>
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => ({}) }
})
const emit = defineEmits(['update:modelValue'])
function 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 type="text" :value="props.modelValue" @input="emitValue" />
</template>
Bileşene eklenen modifikasyonlar, bileşene modelModifiers
prop'u ile sağlanır. Aşağıdaki örnekte, varsayılan olarak boş bir nesne dönen modelModifiers
prop'una sahip bir bileşen oluşturduk:
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
created() {
console.log(this.modelModifiers) // { capitalize: true }
}
}
</script>
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
Bileşenin modelModifiers
prop'unun capitalize
içerdiğini ve değerinin true
olduğunu unutmayın - bu, v-model
bağlaması üzerinde v-model.capitalize="myText"
olarak ayarlandığı içindir.
Artık prop'umuzu ayarladıktan sonra, modelModifiers
nesnesi anahtarlarını kontrol edebilir ve yayılan değeri değiştirmek için bir işlemci yazabiliriz. Aşağıdaki kodda, `elementi bir
input` olayı tetiklediğinde string'in büyük harfli olmasını sağlayacağız.
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
methods: {
emitValue(e) {
let value = e.target.value
if (this.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:modelValue', value)
}
}
}
</script>
<template>
<input type="text" :value="modelValue" @input="emitValue" />
</template>
Argüman ile v-model
için Modifikasyonlar
Argüman ve modifikasyonları olan v-model
bağlamaları için, oluşturulan prop adı arg + "Modifiers"
biçiminde olacaktır. Örneğin:
<MyComponent v-model:title.capitalize="myText">
İlgili bildirimler şöyle olmalıdır:
export default {
props: ['title', 'titleModifiers'],
emits: ['update:title'],
created() {
console.log(this.titleModifiers) // { capitalize: true }
}
}
İşte argümanlarla farklı v-model
kullanarak modifikasyonları örnek almak için başka bir örnek:
<UserName
v-model:first-name.capitalize="first"
v-model:last-name.uppercase="last"
/>
<script setup>
const [firstName, firstNameModifiers] = defineModel('firstName')
const [lastName, lastNameModifiers] = defineModel('lastName')
console.log(firstNameModifiers) // { capitalize: true }
console.log(lastNameModifiers) // { uppercase: true }
</script>
3.4 Öncesi Kullanım
<script setup>
const props = defineProps({
firstName: String,
lastName: String,
firstNameModifiers: { default: () => ({}) },
lastNameModifiers: { default: () => ({}) }
})
defineEmits(['update:firstName', 'update:lastName'])
console.log(props.firstNameModifiers) // { capitalize: true }
console.log(props.lastNameModifiers) // { uppercase: true }
</script>
<script>
export default {
props: {
firstName: String,
lastName: String,
firstNameModifiers: {
default: () => ({})
},
lastNameModifiers: {
default: () => ({})
}
},
emits: ['update:firstName', 'update:lastName'],
created() {
console.log(this.firstNameModifiers) // { capitalize: true }
console.log(this.lastNameModifiers) // { uppercase: true }
}
}
</script>