Vue 進階教程之:幫你徹底理解 v-model 以及在組件上如何使用


背景

閱讀vue文檔時,到子組件使用v-model發現這塊描寫的不是那么容易讓我理解,於是網上查了相關的文檔並作為轉載.以備日后遺忘.

描述

Vue 官網教程上關於 v-model 的講解不是十分的詳細,寫這篇文章的目的就是詳細的剖析一下, 並介紹 Vue 2.2 v-model改進的地方,然后穿插的再說點 Vue 的小知識。

在 Vue 中,有許多方法和 Angular 相似,這主要是因為 Angular 是 Vue 早期開發的靈感來源。然而,Augular 中存在許多問題,在 Vue 中已經得到解決。

v-model 用在 input 元素上時
v-model雖然很像使用了雙向數據綁定的 Angular 的 ng-model,但是 Vue 是單項數據流,v-model 只是語法糖而已:↓

<input v-model="sth" />
<input :value="sth" @input="sth = $event.target.value" />

第一行的代碼其實只是第二行的語法糖,兩行代碼是等價的。

要理解這行代碼,首先你要知道 input 元素本身有個 oninput 事件,這是 HTML5 新增加的,類似 onchange ,每當輸入框內容發生變化,就會觸發 oninput ,把最新的value賦值給 sth變量。
如果你不知道 $event 是從哪來的,那你需要點擊它再復習一下文檔。

我們仔細觀察語法糖和原始語法那兩行代碼,可以得出一個結論:

在給<input />元素添加 v-model 屬性時,默認會把 value 作為元素的屬性,把 input 事件作為實時傳遞 value 的觸發事件
(理解上面那句話非常重要,如果沒有理解,務必再把上面的內容多看兩遍,多想想,直到理解為止)

當 v-model 用在組件上時
v-model 不僅僅能在 inputHTML 原生標簽上用,在 vue 組件上也能使用;下面是一個和 Vue 官網教程類似的例子:

實例演示.gif
父組件 price 的初始值是 100,子組件是一個輸入框;輸入框的值改變時,能實時更新父組件的 price

// 父組件
<template>
<div id="demo">
  <currency-input v-model="price"></currentcy-input>
  <span>{{price}}</span>
</div>
</template>

<script>
export default {
  data() {
    return {
      price: 100,
    }
  }
}
</script>
// 子組件 currency-input
<template>
  <input
    :value="value"
    @input="$emit('input', $event.target.value)"
  />
   <!--為什么這里把 'input' 作為觸發事件的事件名?`input` 在哪定義的?-->
</template>

<script>
export default {
  props: {
    value: String,  // 為什么這里要定義 value 屬性,父組件貌似沒有給子組件傳遞 value 啊?
  }
}
</script>

注釋里列了兩個問題,如果你都知道答案,那么恭喜你真正掌握了 v-model!
如果你沒明白,那么可以繼續往下看

我們對比下下面兩行代碼

<currency-input v-model="price"></currentcy-input>
<currency-input :value="price" @input="price = $event.target.value"></currency-input>

這兩行代碼實際上沒有任何區別,只不過第一行是第二行的語法糖而已!
現在你知道 value 和 input 從哪來的了吧。與上面總結的類似:

給組件添加 v-model 屬性時,默認會把value 作為組件的屬性,把 input作為給組件綁定事件時的事件名

v-model 的缺點和解決辦法
v-model 應用到組件上,會有一些體驗不好的場景。因為它默認會把 value 作為組件的屬性,把 input作為給組件綁定事件時的事件名。

// 父組件
<my-button v-model="number"></my-button>
<script>
data() {
  return {
    number: 1,
  }
}
</script>
// 子組件
<template>
  <button @click="add">點擊按鈕自增 1</button>
</template>

<script>
export default {
  props: {
    value: Number, //  屬性名必須是 value
  },

  methods: {
    add() {
      this.$emit('input', this.value + 1) // 事件名必須是 input
    },
  }
}
</script>

有時間我們不想用 value 當做默認的屬性名,也不想把 input 當做事件名。能不能自定義呢?

在 Vue 2.2 及以上版本,你可以在定義組件時通過 model 選項的方式來定制 prop/event:↓

// 父組件
<my-button v-model="number"></my-button>
<script>
data() {
  return {
    number: 1,
  }
}
</script>
// 子組件
<template>
  <button @click="add">點擊按鈕自增 1</button>
</template>

<script>
export default {
  model: {
    prop: 'num', // 自定義屬性名
    event: 'addNum' // 自定義事件名
  },
  props: {
    num: Number,
  },

  methods: {
    add() {
      this.$emit('addNum', this.num + 1)
    },
  }
}
</script>

看到這里我相信你肯定理解了 Vue 的 v-model,文中如有錯誤,歡迎在評論中指出,謝謝。
碼字辛苦,文章如對您有幫助,麻煩支持點贊~

轉載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM