ホームページ > 記事 > ウェブフロントエンド > 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" />
af7e595dcdbda7820db674c9e899f5bc
コンポーネント内で 2 つのことを行う必要があります:
内部ネイティブを変換します。 d5fd7aea971a85678ba271703566ebfd
ネイティブ ## の場合、要素の value
属性は 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 はコンポーネントの prop として
modelValue を使用し、コンポーネントの prop として
update:modelValue を使用します。対応するイベント
v -model を渡すこともできます。 これらの名前を変更するパラメーターを指定します。
<template> <CustomInput v-model:first-name="first" v-model:last-name="last" /> </template>同様に、2 つの方法でバインドすることもできますが、
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>に変更されます。バインディングオブジェクト複雑なコンポーネントでAフィールドが複数ある場合、双方向のバインディングが必要になります。上記の方法だと少し面倒になります。2つの方法を紹介します。双方向バインディング オブジェクト親コンポーネントを定義します
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
<pre class="brush:php;toolbar:false"><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></pre># として定義します。
##コメントに記載されているように、オブジェクトが渡された場合は、
c5e44a1b4f0a675a16a4473925921278これは両方向のバインディングで直接実行できますが、これにより
トリガー イベントと同じですが、渡されたデータはオブジェクトになります
単一のデータ フローが破壊されます# # 上記の 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
がトリガーされないことがわかります。
はプロキシのレイヤーであり、プロキシ オブジェクトはプロキシ オブジェクトではないためです。修正済み setter
をトリガーする場合は、以下のようにします。
// 只有这样才会变化 model.value = { keyword:"asdfad" }
このメソッドは setter
をトリガーできないため、双方向バインディングは実行できません。完了しました。どうすればよいでしょうか?
getter
で
getter
で proxy オブジェクトを返します! getter
で proxy オブジェクトを返します! プロキシ オブジェクトはプロキシされたオブジェクトのプロパティと一致しているため、proxy を使用して元のオブジェクトをラップします
その後、v-model
がプロキシの背後にあるオブジェクトにバインドされます。プロキシ オブジェクトのプロパティが変更されると、プロキシ オブジェクトの set
メソッドがトリガーされます。この時点で、
<pre class="brush:js;">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
})
}
})</pre>
Modifiersv-model
には、
.lazy。
一部のシナリオでは、カスタム コンポーネントの
v-model でカスタム修飾子をサポートすることが必要になる場合があります。
カスタム修飾子
capitalize
v-model バインディング入力の文字列値の最初の文字を自動的に大文字に変換します:
<CustomInput v-model.capitalize="txt" />
capitalize 修飾子を追加しました。これは、
prop中
<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>の
modelModifiers に自動的に渡されます。
以上がvue3でのv-modelの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。