vue中v-model的學習

揹著泰山找黃河發表於2021-02-25
v-model在表單元素input、radio、checkBox、textarea建立雙向資料繫結,他會根據型別選取正確的方法來更新元素,本質不過是語法糖,負責監聽使用者的輸入操作以更新資料並對一些極端場景進行一些特殊處理
語法糖:也譯為糖衣語法,是由英國計算機科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指計算機語言中新增的某種語法,這種語法對語言的功能並沒有影響,但是更方便程式設計師使用。通常來說使用語法糖能夠增加程式的可讀性,從而減少程式程式碼出錯的機會。

官方文件連線:https://cn.vuejs.org/v2/guide/forms.html

新認識到的知識點:

.lazy

在預設情況下,v-model 在每次 input 事件觸發後將輸入框的值與資料進行同步 (除了上述輸入法組合文字時)。你可以新增 lazy 修飾符,從而轉為在 change 事件_之後_進行同步:

<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg">

.number

如果想自動將使用者的輸入值轉為數值型別,可以給 v-model 新增 number 修飾符

<input v-model.number="age" type="number">

這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會返回字串。如果這個值無法被 parseFloat() 解析,則會返回原始的值。

.trim

自動去除空格

<input v-model.trim="msg">

 

那麼在元件中如何使用呢?

首先v-model是寫在父元件中的

<VueRadio :msgs="strs" v-model="defaultValue"/>

因為vue也說過,v-model本質上是一個語法糖,所以以上程式碼是指上是

<VueRadio
      v-bind:checked="defaultValue"
      v-on:change="defaultValue= arguments[0]">
    </VueRadio>

其實也就是表單元素的值和一個change事件,首先可以將父元件的預設值傳送給子元件,子元件在發生值的變化時,父元件也能接收到。在input中,標識value和input預設值,在checkbox中標識checked和change

以上為在radio以及checkbox中v-model的含義,以下為官方例項

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: '
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >'
})

等價於

<base-checkbox v-model="lovingVue"></base-checkbox>

這裡的 lovingVue 的值將會傳入這個名為 checked 的 prop。同時當 <base-checkbox> 觸發一個 change 事件並附帶一個新的值的時候,這個 lovingVue 的 property 將會被更新。

注意你仍然需要在元件的 props 選項裡宣告 checked 這個 prop。

 

接下來是子元件中的使用

 

<template>
  <div>
    <div v-for="(str,index) in msgs" :key="index">
        <div>題目{{index+1}}
            <div v-for="(st,index) in str" :key="index">
                <div class="radio" v-if="st.disabled == true">
                    <input type="radio" v-on:change="$emit('change', $event.target.value)" :name="st.name" :value="st.value"/><span>{{st.value}}</span>
                </div>
                <div v-else>
                    <div class="radio" v-if="st.value == defaultV">
                        <input type="radio" 
                         :name="st.name" :value="st.value" checked
                         v-on:change="$emit('change', $event.target.value)"/><span>{{st.value}}</span>
                    </div>
                    <div class="radio" v-else>
                        <input type="radio" 
                        :name="st.name" :value="st.value" 
                        v-on:change="$emit('change', $event.target.value)"/><span>{{st.value}}</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'VueRadio',
  props: {
    msgs: Array,
    defaultV:String
  },
  model: {
      prop: 'defaultV',
      event: 'change',
  },
}
</script>

<style scoped>
    .radio{
        border: 1px solid #409eff;
        width: 40px;
        border-radius: 4px;
        margin-bottom: 5px;
    }
    span{
        color: #409eff;
    }
    
</style>

 

主要看標紅的幾處,以下為分解解釋,其實文件中有提示,注意你仍然需要顯性宣告 checked 屬性。所以還是主要再宣告一個預設值,然後就可以使用了。

 

 這樣就可以使用了,完整程式碼如下

父元件

<template>
  <div id="app">
    <VueRadio :msgs="strs" v-model="defaultValue"/>
    <h1>{{defaultValue}}</h1>
  </div>
</template>

<script>
import VueRadio from './components/VueRadio.vue'

export default {
  components: {
    VueRadio
  },
  data() {
      return {
          strs: [],
          defaultValue:"A"
      }
  },
  created() {
      var strsTemp = []
      for (var i = 0; i < 1; i++) {
        var rId = "r"+i;
        var st2 = [
          { name: rId, value: "A" },
          { name: rId, value: "B",disabled:true },
          { name: rId, value: "C" }
        ];
        strsTemp.push(st2)
      }
      this.strs = strsTemp;
  }
}
</script>

子元件

<template>
  <div>
    <div v-for="(str,index) in msgs" :key="index">
        <div>題目{{index+1}}
            <div v-for="(st,index) in str" :key="index">
                <div class="radio" v-if="st.disabled == true">
                    <input type="radio" v-on:change="$emit('change', $event.target.value)" :name="st.name" :value="st.value"/><span>{{st.value}}</span>
                </div>
                <div v-else>
                    <div class="radio" v-if="st.value == defaultV">
                        <input type="radio" 
                         :name="st.name" :value="st.value" checked
                         v-on:change="$emit('change', $event.target.value)"/><span>{{st.value}}</span>
                    </div>
                    <div class="radio" v-else>
                        <input type="radio" 
                        :name="st.name" :value="st.value" 
                        v-on:change="$emit('change', $event.target.value)"/><span>{{st.value}}</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'VueRadio',
  props: {
    msgs: Array,
    defaultV:String
  },
  model: {
      prop: 'defaultV',
      event: 'change',
  },
}
</script>

<style scoped>
    .radio{
        border: 1px solid #409eff;
        width: 40px;
        border-radius: 4px;
        margin-bottom: 5px;
    }
    span{
        color: #409eff;
    }
    
</style>

實現效果

參考連結:https://juejin.cn/post/6844903490653782029

     https://www.jianshu.com/p/695ca638783a

相關文章