阅读 71

Vue 表单输入绑定(1)

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Vue 中,我们可以使用 v-model 指令在表单的 <input><textarea><select> 元素上创建双向数据绑定。v-model 会根据控件类型自动选取正确的方法来更新元素。

1. v-model 的基本使用及原理

  • 表单提交是开发中非常常见的功能,也是和用户交互的重要手段:
    • 比如用户在登录、注册时需要提交账号密码;
    • 比如用户在检索、创建、更新信息时,需要提交一些数据;
  • 这些都要求我们可以在代码逻辑中获取到用户提交的数据,我们通常会使用 v-model 指令来完成:
    • v-model 指令可以在表单的 <input><textarea> 以及 <select> 元素上创建双向数据绑定
    • 它会根据控件类型自动选取正确的方法来更新元素;
    • 尽管有些神奇,v-model 本质上不过是语法糖,它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理;

我们先来思考一个问题:假设现在有一个页面,页面上有一个文本框和一个标题,我们想要让文本框中的内容和标题的内容始终保持一致(标题的内容要绑定到文本框中,并且文本框中的内容修改后,标题的内容也要同时修改),该怎么实现呢?

我们可以利用前面讲过的属性绑定 v-bind 指令和事件监听 v-on 指令实现这一需求,以下为 <body> 元素中的代码:

<div id="app"></div>

<template id="my-app">
  <input type="text" :value="message" @input="inputChanged">
  <h2>{{ message }}</h2>
  <button @click="message = '哈哈哈'">修改标题</button>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    data() {
      return {
        message: '你好啊'
      }
    },
    methods: {
      inputChanged(event) {
        this.message = event.target.value;
      }
    },
    template: '#my-app'
  };

  Vue.createApp(App).mount('#app');
</script>
复制代码

页面效果如下:

表单输入绑定--自己实现.gif

可见,一方面,通过 v-bind 指令动态绑定 <input> 元素的 value 属性的值为 message,可以实现将 message 的值绑定到文本框中去,只要 message 的值发生改变,文本框的值也会同时改变;另一方面,通过 v-on 指令绑定 <input> 元素的 input 事件,并在监听到 input 事件时修改 message 属性的值,又可以实现文本框的值发生改变,message 的值也会同时改变。如此一来,不就实现双向数据绑定了吗?

上面的操作其实可以总结为两步:

  1. v-bind 绑定 value 属性的值;
  2. v-on 绑定 input 事件,在监听 input 事件的函数中,函数可以获取最新的值,然后赋值给绑定的属性(这里即 message 属性);

而在开发中,对于 <input> 输入框来说,这两步操作一般都是要做的,因此,Vue 给我们提供了一种更加简便的写法,即使用 v-model 的写法,于是,上面的两步就可以简写为:v-model="message" 了。<body> 元素中的代码如下:

<div id="app"></div>

<template id="my-app">
  <!-- <input type="text" :value="message" @input="inputChanged"> -->
  <input type="text" v-model="message">
  <h2>{{ message }}</h2>
  <button @click="message = '哈哈哈'">修改标题</button>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    data() {
      return {
        message: '你好啊'
      }
    },
    methods: {
      inputChanged(event) {
        this.message = event.target.value;
      }
    },
    template: '#my-app'
  };

  Vue.createApp(App).mount('#app');
</script>
复制代码

所以,通过使用 v-model 指令,也就实现了双向数据绑定了:message 的最新的值会绑定到 <input>value 上,同时,当 <input>value 发生改变时,也会用其最新的值更新 message 的值。

官方也有说到,v-model 的原理其实是背后有两个操作:

image-20210916214726681.png

当然,官方文档这里绑定 input 事件时用的是表达式语句,而我们前面是把这个表达式抽取成了方法,本质上是一样的。

不过,虽然 v-model 的使用和原理看起来都很简单,但事实上,在 Vue 把模板编译(我们知道,模板是不能直接渲染成浏览器中的 DOM 的,而是需要先进行编译的)成一些函数,之后调用这些函数生成对应的 VNode 的过程中,一旦我们使用了 v-model,编译出来的代码是有点复杂的。这里的 <input> 上使用了 v-model 后,编译出来的 render 函数如下:

image-20210923215726679.png

源码流程如下:

image-20210923221929699.png

其中,"onUpdate:modelValue" 对应的函数就是我们在 methods 选项中编写的对应方法或者是前面提到的 Vue 文档中 @input 的内容。当然,这里涉及到的东西有点多,有模板的编译、指令的使用、指令中还有生命周期等等,因此,我们目前先做个简单了解即可。

文章分类
前端
文章标签