vue中v-model的学习

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

posted @ 2021-02-25 09:20  背着泰山找黄河  阅读(311)  评论(0编辑  收藏  举报