首頁  >  文章  >  web前端  >  vue3中的v-model怎麼使用

vue3中的v-model怎麼使用

王林
王林轉載
2023-05-10 11:07:321804瀏覽

綁定單一屬性

基礎綁定

以自訂元件 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 元件內部需要做兩件事:

  • ##將內部原生 

    d5fd7aea971a85678ba271703566ebfd 元素的 value attribute 綁定到 modelValue prop

  • 當原生的 

    input

1111167703好的 ##事件觸發時,觸發一個攜帶了新值的 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 在元件上都是使用 modelValue 作為prop,並以update:modelValue

作為對應的事件

但我們可以透過給 

v -model

 指定一個參數來改變這些名字:

<template>
    <CustomInput v-model:first-name="first" v-model:last-name="last" />
</template>

同樣的,也可以用兩種方式綁定,只是 

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>
綁定物件在一個複雜的元件中,如果多個欄位需要雙向綁定,如果使用上文所示方法的話,會有一些繁瑣

介紹兩種雙向綁定物件的做法

定義父元件 
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

<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>

如果傳入物件的話,如註解所介紹的d78f68ab62ee45d15a833ea4e4e1b0c7雖然可以直接進行雙向綁定,但是這樣會破壞

單項資料流

和上文的

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 中傳回 一個 代理物件! getter

中傳回 一個

代理物件! getter 中傳回 一個 代理物件!

因為

proxy

代理程式的物件是和被代理物件屬性是保持一致的,所以我們使用

proxy 包裹原物件那麼v-model 綁定的是代理之後的對象,如果代理對象屬性發生了改變,則會觸發代理對像中的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
    })
  }
})
修飾符

我們知道 

v-model 有一些內建的修飾符,例如 .trim#,.number

 和 

.lazy在某些場景下,我們可能想要一個自訂元件的 v-model 支援自訂的修飾符。 我們來建立一個自訂的修飾符 capitalize

,它會自動將 ###v-model### 綁定輸入的字串值第一個字母轉為大寫:###
  <CustomInput v-model.capitalize="txt" />
###我們加入了###capitalize###修飾符,他會被自動傳入到 ###prop### 中的 ######modelModifiers#######中###
<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>

以上是vue3中的v-model怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除