vue2 vs vue3 v-model 的語法糖

<input v-model="str" />

// 等同于 

<input :value="str" @input="str = $event.target.value" />

通過上面的代碼,我們可以分析得出,也就是說:<font color=red> v-model="str" 是 :value="str" @input="str = $event.target.value" 的縮寫。</font>

解釋:

$event 指代當(dāng)前觸發(fā)的事件對(duì)象。

$event.target 指代當(dāng)前觸發(fā)的事件對(duì)象的dom

$event.target.value 就是當(dāng)前dom的value值

在@input方法中,value => str

在:value中:str => value

如此,形成了一個(gè)閉環(huán),也就是所說的數(shù)據(jù)的雙向綁定。

自定義組件怎么實(shí)現(xiàn)v-model

<my-component v-model="price"></my-component>

我們可以根據(jù)規(guī)則來拆解

<my-component :value="price" @input="price = $event.target.value"></my-component>

那么我們在還原組件的封裝

<template>
  <div>
    <input type="text" :value="value" @input="$emit('input', $event.target.value)">
  </div>
</template>
<script>
export default {
 props: {
    value: String
  }
 }
 </script>

看到上面的代碼或許你就恍然大悟了,他又回到了,我們之前學(xué)過的 父子組件的來回傳值。

細(xì)心的同學(xué)可能會(huì)發(fā)現(xiàn),我們 props 里面的值是 value 那我能不能隨便定義一個(gè)變量呢?還有 $emit()里面?zhèn)魅氲氖录凳莍nput我能不能也隨便定義一個(gè)事件呢?

當(dāng)我們在一個(gè)自定義組件上使用v-model并不能實(shí)現(xiàn)雙向綁定,因?yàn)樽远ǖ慕M件并沒有默認(rèn)的value和input事件,在使用時(shí),我們需要按照上面那樣顯式的去聲明定義這些東西。這時(shí),model選項(xiàng)就派上用場了,在定義組件的時(shí)候,指定prop的值和監(jiān)聽的事件。
組件的用法是不變的,子組件可以這么寫

<template>
  <div>
    <input type="text" :value="xxxx" @input="$emit('xxxx', $event.target.value)">
  </div>
</template>

<script>
export default {
    model:{
        prop:'xxxx',
        event:'xxxx' // 代表自定義的事件名稱
    }

    props: {
        xxxx: String // 代表自定義的變量名稱
     }
}
</script>

這就是vue 的 model 選項(xiàng)的作用。

以上是vue2.0的v-model語法糖講解,vue3.0是怎么用的呢?

其實(shí)vue3的v-model跟vue2的使用區(qū)別不大,只是跟vue2的 <font color=red>sync</font> 修飾符進(jìn)行了合并,所以在vue3中就移除了 <font color=red>sync</font> 修飾符。下面我們看看怎么在 <font color=red>composition api</font>
中怎么寫 <font color=red>v-model</font>

// 自定義一個(gè)TestModel組件
<template>
 <div>
   <input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
 </div>
</template>

<script>
export default {
 props: {
   modelValue: {
     type: String
   }
 }
}
</script>

在vue3中默認(rèn)的不在是value 而是modelValue

然后在其他頁面使用

<template>
  <h1>vue3中使用v-model {{msg}}</h1>
  <testModel v-model="msg"></testModel>
  <!-- 等同于下面語法 默認(rèn)傳入一個(gè)modelValue 然后子組件接收這個(gè)modelValue -->
 <testModel :modelValue="msg" @update:modelValue="msg = $event"></testModel>
</template>

<script>
import { ref } from 'vue';
import testModel from './TestModel.vue';
export default {
  components: {
    testModel
  },
  setup(){
    const msg = ref('')
    return { msg }
  },
}
</script>

有的小伙伴可能有疑問,如果我不想用 modelValue 怎么辦呢?當(dāng)然也可以寫成其他的名字

// 父組件
<template>
  <h1>vue3中使用v-model {{msg}}</h1>
  <testModel v-model:msg="msg"></testModel>
</template>

子組件接收的props就要改成msg了

// 子組件
<template>
  <div>
    <input type="text" :value="msg" @input="$emit('update:msg', $event.target.value)" />
  </div>
</template>

<script>
export default {
  props: {
    msg: {
      type: String
    }
  }
}
</script>

當(dāng)然提到雙向綁定,你可能第一時(shí)間就會(huì)想到表單元素,雙向綁定不一定是表單元素,你可以定義各種各樣的組件,比如通過click事件改變父組件的值

// 父組件
<template>
  <div>{{count}}</div>
  <testModel v-model:count="count"></testModel>
</template>

<script>
export default {
  components: {
    testModel
  },
  setup(){
    const count = ref(0)
    return { count }
  }
}
</script>



// 子組件
<template>
  <!-- 一定是+1 不是+=1 或者++ 否則vue會(huì)觸發(fā)一個(gè)不讓子組件直接改變props的警告 -->
  <div @click="$emit('update:count', count + 1)">click me count + 1!</div>
</template>

<script>
export default {
  props: {
    count: {
      type: Number
    }
  }
}
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容