v-model مع المكون
يمكن استخدام v-model
على مكون لتنفيذ ارتباط ثنائي الاتجاه.
أولا دعونا نعيد النظر في كيفية استخدام v-model
على عنصر أصلي:
template
<input v-model="searchText" />
خلف الكواليس، يقوم مصرّف القوالب بتجزئة v-model
إلى الحدث input@
و السمة value
. لذلك، تقوم الشيفرة أعلاه بنفس الأمر الذي تقوم به الشيفرة الموالية:
template
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
عند استخدامه على مكون، يُجزّء v-model
إلى ما يلي:
template
<CustomInput
:model-value="searchText"
@update:model-value="newValue => searchText = newValue"
/>
لكن ليشتغل هذا فعلا، يجب على <CustomInput>
القيام بأمرين:
- اربط السمة
value
لعنصر<input>
الأصلي مع الخاصيةmodelValue
- عندما تُشغل حدث
input
الأصلي ، ارسل حدث مخصصupdate:modelValue
مع القيمة الجديدة
عمليا:
vue
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
الآن يجب أن يعمل v-model
بشكل مثالي مع هذا المكون:
template
<CustomInput v-model="searchText" />
طريقة أخرى لتنفيذ v-model
داخل هذا المكون هي استخدام خاصية computed
قابلة للكتابة مع الدالتين المحصلة و المعينة. يجب أن تعيد الدالة get
الخاصية modelValue
ويجب أن ترسل الدالة set
الحدث الموافق:
vue
<!-- CustomInput.vue -->
<script setup>
import { computed } from 'vue'
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
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
كخاصية و update:modelValue
كحدث. يمكننا تعديل هذه الأسماء من خلال إرسال وسيط إلى v-model
:
template
<MyComponent v-model:title="bookTitle" />
في هذه الحالة، يجب أن يتوقع المكون الابن خاصية title
ويرسل الحدث update:title
لتحديث القيمة في المكون الأب:
vue
<!-- MyComponent.vue -->
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>
<template>
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)"
/>
</template>
الربط المتعدد بـ v-model
باستخدام قدرة تحديد خاصية معينة وحدث معين كما تعلمنا من قبل مع وسائط v-model
، يمكننا الآن إنشاء عدة ارتباطات v-model على نسخة واحدة من المكون.
كل v-model سيتزامن مع خاصية مختلفة ، دون الحاجة إلى خيارات إضافية في المكون:
template
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>
vue
<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>
معالجة معدلات v-model
عندما كنا نتعلم عن ارتباطات إدخال النموذج، رأينا أن v-model
لديه المعدلات المدمجة - .trim
, .number
و lazy.
. في بعض الحالات، قد ترغب أيضًا في أن يدعم v-model
على مكون إدخال مخصص بعض المعدلات المخصصة.
لنقم بإنشاء مثال لمعدل مخصص، capitalize
، يقوم بتكبير الحرف الأول من السلسلةالنصية المقدمة من خلال ربط v-model
:
template
<MyComponent v-model.capitalize="myText" />
المُعدِّلات المضافة إلى v-model
للمكون ستُمرر إلى المكون عبر خاصية modelModifiers
. في المثال أدناه، قمنا بإنشاء مكون يحتوي على خاصية modelModifiers
تعيد قيمة فارغة افتراضيًا:
vue
<script setup>
const props = defineProps({
modelValue: String,
modelModifiers: { default: () => ({}) }
})
defineEmits(['update:modelValue'])
console.log(props.modelModifiers) // { capitalize: true }
</script>
<template>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
تجدر الإشارة إلى أن خاصية modelModifiers
للمكون تحتوي على المُعدِّل capitalize
وقيمته true
- بسبب تعيينها على v-model
بالربط "v-model.capitalize="myText
.
الآن، بعد أن قمنا بإعداد الخاصية، يمكننا التحقق من مفاتيح الكائن modelModifiers
وكتابة مُعالِج لتغيير القيمة المرسلة. في الشيفرة أدناه، سنقوم بتكبير الحرف الأول من السلسلة النصية عندما يُطلق حدث input
على عنصر </ input>
.
vue
<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="modelValue" @input="emitValue" />
</template>
Modifiers for v-model
with arguments
بالنسبة لربط v-model
مع كل من الوسيط والمعدلات، سيكون اسم الخاصية المولدة "arg + "Modifiers
على سبيل المثال.
template
<MyComponent v-model:title.capitalize="myText">
التصريحات المقابلة يجب أن تكون:
js
const props = defineProps(['title', 'titleModifiers'])
defineEmits(['update:title'])
console.log(props.titleModifiers) // { capitalize: true }
Here's another example of using modifiers with multiple v-model
with different arguments:
template
<UserName
v-model:first-name.capitalize="first"
v-model:last-name.uppercase="last"
/>
vue
<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>