v-model 的本质是语法糖?

2,902 阅读1分钟

举个栗子: 输入用户名与密码,回车打印出信息

<template>
  <div>
    <form @submit="onSubmit">
      <label>
        <span>用户名:</span>
        <input type="text" v-model="user.username">
      <!-- <input type="text" :value="user.username" @input="user.username = $event.target.value"> -->
      </label>
      <label>
        <span>密码:</span>
        <input type="password"  v-model="user.password">
      </label>
      <hr>
      <button type="submit">确定</button>
    </form>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      user: {
        username: "",
        password: ""
      }
    };
  },
  methods: {
    onSubmit() {
      console.log(`用户名:${this.user.username} 密码:${this.user.username}`);
    }
  }
};
</script>

v-model 的实质

在text 和 textarea 元素中,v-model="xxx" 的扩展写法为::value="xxx" @input="xxx = $event">

  • 将 xxx 的值绑定给 value
  • 当 value 发生变化会触发 input 事件并附带一个新的值,将新值赋给 xxx
  • 即监听用户的输入事件以更新数据

那 input 干了啥呢,我们可以自己封装 input

自定义 input 组件

myInput.vue

<template>
  <div>
    <input :value="value" @input="onInput">
  </div>
</template>
<script>
export default {
  props: {
    value:String
  },
  methods: {
    onInput(e) {
      this.$emit("input", e.target.value); //把结果暴露出去
    }
  }
};
</script>

使用它:

 <label>
        <span>用户名:</span>
        <my-input v-model="user.username"/>
        <!-- <my-input :value="user.username" @input="user.username = $event"/> -->
      </label>
      <label>
  • 给 input value 绑定了外部变量 value ,即获取 xxx 的值
  • 当 value 变化时,$emit 会触发 input 事件,并且将新值暴露出去给 xxx 使用

事实上,一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件却并不是这样做。

  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

自定义 checkbox 组件的 v-model

实际上与 input 组件相类似,区别:

  • 在组件的 props 选项里声明 checked 外部属性。
  • 添加 model 选项里声明prop 与 event myCheckbox.vue
<template>
  <div id="red">
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  </div>
</template>
<script>
export default {
  model: {
    prop: "checked",
    event: "change"
  },
  props: {
    checked: Boolean
  }
}

在组件中使用它

 <myCheckbox v-model="checked1"/>
 <!-- <my-checkbox :checked="checked1" v-on:change="checked1=$event"/> -->
  • checked1 的值将会传入这个名为 checked 的 prop。
  • checked 变化会触发 change 事件并附带一个新的值
  • checked1 的值将会被更新。

双向绑定 即 v-model

  • 当绑定了一个变量,在变量变化的时候 UI 会变化,在用户改变 UI 的时候,变量会变化
  • v-model 是 v-bind:value 和 v-on:input 的语法糖。
  • v-on:input=""里面有什么分两种情况
  • 若在原生组件中使用 xxx = $event.target.value
  • 若在自定义组件中使用 xxx = $event

input 实现回车后自动刷新

在 input 上监听键盘事件太麻烦,可以这样做

  • 写一个 form 表单并且绑定提交事件
  • form 表单里需要一个按钮,可点击触发提交事件