ホームページ  >  記事  >  ウェブフロントエンド  >  vue3でのv-modelの使い方

vue3でのv-modelの使い方

王林
王林転載
2023-05-10 11:07:321854ブラウズ

単一の属性をバインドする

基本的なバインディング

コンポーネントをカスタマイズするには CustomInput

<script setup>
    const txt = ref(&#39;&#39;);
 </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({
  &#39;modelValue&#39;: String,
})
const emit = defineEmits(["update:modelValue"])
</script>

<template>
    <input :value="modelValue" @input="$emit(&#39;update:modelValue&#39;, $event.target.value)" />
</template>

一部の人は、この書き方は面倒でタグコードが長くなる原因になると感じるでしょう。

コンポーネント内で

v-model を実装する別の方法は次のとおりです。 getter と setter の computed 属性

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 複数の属性のバインド

デフォルトでは、

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([&#39;update:firstName&#39;, &#39;update:lastName&#39;])
</script>

<template>
  <input
    type="text"
    :value="firstName"
    @input="$emit(&#39;update:firstName&#39;, $event.target.value)"
  />
  <input
    type="text"
    :value="lastName"
    @input="$emit(&#39;update:lastName&#39;, $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">&lt;template&gt; &lt;div&gt; &lt;!-- &lt;input type=&quot;text&quot; v-model=&quot;modelValue.keyword&quot;&gt; 可以实现双向绑定 --&gt; &lt;input type=&quot;text&quot; :value=&quot;modelValue.keyword&quot; @input=&quot;handleKeywordChange&quot; &gt; &lt;select v-model=&quot;modelValue.selectValue&quot;&gt; &lt;option v-for=&quot;o in modelValue.options&quot; :key=&quot;o.value&quot; :value=&quot;o.value&quot;&gt; {{ o.label }} &lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;/template&gt; &lt;script lang=&quot;ts&quot; setup&gt; const props = defineProps({ modelValue: { type: Object, default: () =&gt; ({}) } }) const emit = defineEmits([&quot;update:modelValue&quot;]); // 以 input 举例 const handleKeywordChange=(val)=&gt;{ emit(&quot;update:modelValue&quot;,{ ...props.modelValue, keyword:val.target.value }) } &lt;/script&gt;</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 がトリガーされないことがわかります。

computed

はプロキシのレイヤーであり、プロキシ オブジェクトはプロキシ オブジェクトではないためです。修正済み setter をトリガーする場合は、以下のようにします。

// 只有这样才会变化
 model.value = {
   keyword:"asdfad"
 }

このメソッドは setter をトリガーできないため、双方向バインディングは実行できません。完了しました。どうすればよいでしょうか?

getter

proxy オブジェクトを返します!

getterproxy オブジェクトを返します! getterproxy オブジェクトを返します! プロキシ オブジェクトはプロキシされたオブジェクトのプロパティと一致しているため、proxy を使用して元のオブジェクトをラップします

その後、v-model がプロキシの背後にあるオブジェクトにバインドされます。プロキシ オブジェクトのプロパティが変更されると、プロキシ オブジェクトの set メソッドがトリガーされます。この時点で、

emit

<pre class="brush:js;">const model = computed({ get() { return new Proxy(props.modelValue, { set(obj, name, val) { emit(&quot;update:modelValue&quot;, { ...obj, [name]: val }) return true } }) }, set(value) { emit(&quot;update:modelValue&quot;, { ...props.modelValue, keyword: value }) } })</pre>Modifiersv-model には、

.trim# などの組み込み修飾子があることがわかっています。 ##、

.number

および

.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(&#39;update:modelValue&#39;, value)
}
</script>

<template>
  <input :value="modelValue" @input="emitValue" />
</template>

modelModifiers に自動的に渡されます。

以上がvue3でのv-modelの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。