一、v-model的作用和使用场景

1.1 v-model指令介绍

  • 期望的绑定值类型:根据表单输入元素或组件输出的值而变化

  • 可以下下面元素使用:

    • <input>
    • <select>
    • <testarea>
    • components
    • <checkbox>
    • <radio>
    • <select>

    表单输入元素都是可以使用的

  • v-model支持的修饰符:

    • .lazy——监听 change 事件而不是 input
    • .number ——将输入的合法符串转为数字
    • .trim—移除输入内容两端空格

1.2 v-model指令的作用

在表单输入元素或组件上创建双向绑定。

它会根据控件类型自动选取正确的方法来更新元素。

它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。

毕竟表单提交是开发中非常常见的功能,也是和用户交互的重要手段。

用户在登录、注册时需要提交账号密码,检索、新建、更新数据时,需要提交数据,这些都离不开表单提交。

1.3 什么是双向绑定

Vue中的的双向数据绑定是指model模型(Vuedata下定义的变量)和view(视图)的双向绑定。

其中一个发生改变,另一个也会更新改变。

但是更通俗和常用的讲就是当表单元素的值发生变化时。和它绑定的Vue中的data变量也发生改变。,

二、v-model的基本使用

2.1 代码示例和解析

<div id="app"><!-- 1.使用v-model实现input的双向绑定 --><input type="text" v-model="message"><h2>input: {{message}}</h2><hr><!-- 2.使用v-model实现textarea的双向绑定 --><textarea cols="30" rows="10" v-model="content"></textarea><h2>textarea: {{content}}</h2><hr><!-- 3.使用v-model实现checkbox的双向绑定 --><!-- 3.1 checkbox单选框: 绑定到属性中的值是一个Boolean --><!-- label的作用是点击label中的文本时,相当于点击到绑定的input元素 --><label for="agree"><input id="agree" type="checkbox" v-model="isAgree"> 同意协议</label><h2>checkbox单选: {{isAgree}}</h2><hr><!-- 3.2 checkbox多选框: 绑定到属性中的值是一个Array --><!--  checkbox单选框; 绑定到属性中的值是单选框的value --><div class="hobbies"><h2>请选择你的爱好:</h2><label for="sing"><input id="sing" type="checkbox" v-model="hobbies" value="sing"> 唱</label><label for="jump"><input id="jump" type="checkbox" v-model="hobbies" value="jump"> 跳</label><h2>爱好: {{hobbies}}</h2></div><hr><!-- 4.使用v-model实现radio的双向绑定 --><!-- radio单选框: 绑定到属性中的值是单选框的value --><div class="gender"><label for="male"><input id="male" type="radio" v-model="gender" value="male"> 男</label><label for="female"><input id="female" type="radio" v-model="gender" value="female"> 女</label><h2>性别: {{gender}}</h2></div><hr><!-- 4.使用v-model实现select的双向绑定 --><!-- 4.1 select单选框的值绑定 --><select v-model="fruit"><option v-for="item in allFruits" :key="item.value" :value="item.value">{{item.text}}</option></select><h2>单选: {{fruit}}</h2><!-- 4.2 select多选框的值绑定 --><select multiple size="3" v-model="fruits"><option v-for="item in allFruits" :key="item.value" :value="item.value">{{item.text}}</option></select><h2>多选: {{fruits}}</h2><hr>
</div><script src="../lib/vue.js"></script>
<script>// 1.创建appconst app = Vue.createApp({data() {return {message: "Hello Model",       //v-model绑定的input数据content: "",               //v-model绑定的textarea数据isAgree: false,               //v-model绑定的checkbox单选框数据 hobbies: []                   //v-model绑定的checkbox多选框数据gender: "female"         //v-model绑定的radio单选框数据fruit: "orange",            //v-model绑定的select单选框数据fruits: [],                  //v-model绑定的select多选框数据allFruits: [{ value: "apple", text: "苹果" },{ value: "orange", text: "橘子" },{ value: "banana", text: "香蕉" },],                            // 水果}}})// 2.挂载appapp.mount("#app")
</script>

可以看到,使用v-model的方式非常简单:

  • 在支持v-model的表单输入元素上加上v-model指令
  • Vuedata选项API中定义数据变量,赋值给v-model就实现了数据的双向绑定

这些也都是对基础的表单元素进行操作。实际开发大多会使用各种各样的组件库开发。

但是使用的方式和原理都是一样的。

2.2 v-model和值绑定:

所谓值绑定,其实并不是很高深的东西,只是Vue官方提供的一个概念。

意思就是表单元素中的value值并不是写死的,而是来自于服务器或者配置文件。

我们就可以先将值请求下来,绑定到data返回的对象中,

再使用条件渲染指令和列表渲染指令把值动态绑定到表单元素上,最后通过v-bind指令来进行绑定。

这个过程就是值绑定

例如上面代码中select的绑定方式:

<div id="app"> <!-- select单选框的值绑定 --><select v-model="fruit"><option v-for="item in allFruits" :key="item.value" :value="item.value">{{item.text}}</option></select><h2>单选: {{fruit}}</h2></div><script src="../lib/vue.js"></script>
<script>// 1.创建appconst app = Vue.createApp({data() {return {fruit: "orange",          //v-model绑定的select单选框数据      allFruits: [{ value: "apple", text: "苹果" },{ value: "orange", text: "橘子" },{ value: "banana", text: "香蕉" },],                          // 水果}}})// 2.挂载appapp.mount("#app")
</script>

在这段代码中,<select><option>的值并不是直接写死在表单元素上的。

它们的值来自allFruits数组,这个数组可能来自于服务器或者配置文件。

这也是开发中常见的情况。

三、v-model的修饰符

3.1 v-model支持的修饰符:

  • .lazy ——监听 change 事件而不是 input

    • 默认情况下,v-model在进行双向绑定时,绑定的是input事件。

      那么会在每次内容输入后就将最新的值和绑定的属性进行同步。

    • 如果在v-model后跟上lazy修饰符,那么会将绑定的事件切换为 change 事件。

      只有在提交(或者回车)时才会触发。

  • .number ——将输入的合法符串转为数字

  • .trim ——移除输入内容两端空格

3.2 代码示例

<div id="app"><!-- 1.lazy: 绑定change事件  --><input type="text" v-model.lazy="message"><h2>message: {{message}}</h2><hr><!-- 2.number: 自动将内容转换成数字 --><!-- 这里有个冷知识:vue2.x中 如果input中输入的是数字,v-model也会自动把数字转为字符串,除非加上.number修饰符vue2.x中 如果input中输入的是数字,将可以直接获取到数字,而不用再加.number修饰符--><input type="text" v-model.number="counter"><h2>counter:{{counter}}-{{typeof counter}}</h2><input type="number" v-model="counter2"><h2>counter2:{{counter2}}-{{typeof counter2}}</h2><hr><!-- 3.trim: 去除收尾的空格 --><input type="text" v-model.trim="content"><h2>content: {{content}}</h2><hr><!-- 4.使用多个修饰符 --><input type="text" v-model.lazy.trim="content"><h2>content: {{content}}</h2>
</div><script src="../lib/vue.js"></script>
<script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {message: "Hello Vue",counter: 0,counter2: 0,content: ""}},watch: {content(newValue) {console.log("content:", newValue)}}})// 2.挂载appapp.mount("#app")
</script>

四、手写v-model原理

官方文档中有提到,v-model的原理其实是背后有两个操作:

  • v-bind绑定value属性的值

  • v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中

依旧上面的原理,可以手写一个v-model的实现:

<div id="app"><!-- 手动的实现双向绑定:先使用v-bind语法糖把message绑定到input的value上再使用v-on语法糖绑定input元素的input事件--><input type="text" :value="message" @input="change">
</div><script src="../lib/vue.js"></script>
<script>// 1.创建appconst app = Vue.createApp({data() {return {message: "Hello Model"}},methods: {change(event) {// 获取当前input表单元素中的内容this.message = event.target.value}}})// 2.挂载appapp.mount("#app")
</script>

至于如果程序中的message发送变化,Vue会有另一部分代码监听数据的变化,并把变化的数据渲染到视图上。

再结合v-model就完成了Vue中数据的双向绑定。

五、v-model用于组件上

5.1 v-model在组件上的基本使用

通过上面的说明可以知道,表单元素上的v-model使用方式如下:

<input v-model="searchText" />

上面的代码其实等价于下面这段 (编译器会对 v-model 进行展开):

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

而当使用在一个组件上时,v-model 会被展开为如下的形式:

<CustomInput:modelValue="searchText"@update:modelValue="newValue => searchText = newValue"
/>

因此<CustomInput> 组件内部需要做两件事:

  • 将内部原生 input 元素的 value属性绑定到 modelValueprop组件上

  • 输入新的值时在 input 元素上触发 update:modelValue 事件

<!-- CustomInput.vue -->
<template><input:value="modelValue"@input="$emit('update:modelValue', $event.target.value)"/>
</template><script>
export default {props: ['modelValue'],emits: ['update:modelValue']
}
</script>

5.2 自定义组件中处理v-model 的参数

默认v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。

我们可以通过给 v-model 指定一个参数来更改这些名字。

<MyComponent v-model:title="bookTitle" />

此时子组件应声明一个 title prop,并通过触发 update:title 事件更新父组件值:

<!-- MyComponent.vue -->
<template><inputtype="text":value="title"@input="$emit('update:title', $event.target.value)"/>
</template><script>
export default {props: ['title'],emits: ['update:title']
}
</script>

5.3 自定义组件中处理多个v-model 绑定

我们可以在一个组件上创建多个 v-model 双向绑定,每一个 v-model 都会同步不同的prop

<UserNamev-model:first-name="first"v-model:last-name="last"
/>
<script>
export default {props: {firstName: String,lastName: String},emits: ['update:firstName', 'update:lastName']
}
</script><template><inputtype="text":value="firstName"@input="$emit('update:firstName', $event.target.value)"/><inputtype="text":value="lastName"@input="$emit('update:lastName', $event.target.value)"/>
</template>

5.4 自定义组件中处理 v-model 修饰符

v-model 有一些内置的修饰符。例如 .trim.number.lazy

在某些场景下,你可能想要一个自定义组件的 v-model 支持自定义的修饰符。

例如创建一个自定义的修饰符 capitalize,它会自动将 v-model 绑定输入的字符串值第一个字母转为大写:

<MyComponent v-model.capitalize="myText" />

组件的 v-model 上所添加的修饰符,可以通过 modelModifiers prop 在组件内访问到。

在下面的组件中,声明了 modelModifiers 这个 prop,它的默认值是一个空对象:

<script>
export default {props: {modelValue: String,modelModifiers: {default: () => ({})}},emits: ['update:modelValue'],created() {console.log(this.modelModifiers) // { capitalize: true }}
}
</script><template><inputtype="text":value="modelValue"@input="$emit('update:modelValue', $event.target.value)"/>
</template>

注意

组件prop中的 modelModifiers的 包含了 capitalize 且其值为 true

因为它在模板中的 v-model 绑定上被使用了。

有了 modelModifiers 这个 prop,我们就可以在原生事件侦听函数中检查它的值。

然后决定触发的自定义事件中要向父组件传递什么值。

<script>
export default {props: {modelValue: String,modelModifiers: {default: () => ({})}},emits: ['update:modelValue'],methods: {emitValue(e) {let value = e.target.value// 如果有capitalize的值为true,则做一些对应的操作if (this.modelModifiers.capitalize) {value = value.charAt(0).toUpperCase() + value.slice(1)}this.$emit('update:modelValue', value)}}
}
</script><template><input type="text" :value="modelValue" @input="emitValue" />
</template>

对于又有参数又有修饰符的 v-model 绑定,生成的 prop 名将是 arg + "Modifiers"

示例:

<MyComponent v-model:title.capitalize="myText">
export default {props: ['title', 'titleModifiers'],emits: ['update:title'],created() {console.log(this.titleModifiers) // { capitalize: true }}
}

六、v-model官方文档

https://cn.vuejs.org/api/built-in-directives.html#v-model

Vue基础--Vue中的双向绑定v-model指令相关推荐

  1. vue基础小节 v-mode属性双向绑定 跑马灯 十秒挑战 计算器 v-for和key属性 v-if与v-show用法区别 tap切换

    vue代码基本结构 <!-- 视图层 --><div class="app"><!-- 差值表达式 --><div>{{mge}} ...

  2. Vue之组件间的双向绑定

    何为组件间双向绑定 我们都知道当父组件改变了某个值后,如果这个值传给了子组件,那么子组件也会自动跟着改变,但是这是单向的,使用v-bind的方式,即子组件可以使用父组件的值,但是不能改变这个值.组件间 ...

  3. vue与elementUI中给el-input绑定键盘按键--按键修饰符

    vue怎么写键盘事件 vue允许将按键值作为修饰符来使用,如监听回车事件,有两种写法,如下代码: <input type="text" @keyup.13="con ...

  4. react中的双向绑定

    前言:因为项目原因需要学习另一个超级火的框架react, 因为之前一直使用vue进行开发,所以在学习react中会不自觉的代入一些vue中的概念来理解react中的实现,下面就通过对比学习的方式记录下 ...

  5. iviewUI组件库中select双向绑定不生效

    前端小伙伴们有没有遇到过这样的场景,iviewUI组件库中select双向绑定数据时,修改了绑定值,但是页面中渲染的值还是之前的值,不管是去打印还是使用vue插件去查看变量,均显示绑定值已修改,可是页 ...

  6. Vue 中实现双向绑定的 4 种方法

    1. v-model 指令 <input v-model="text" /> 复制代码 上例不过是一个语法糖,展开来是: <input:value="t ...

  7. VUE 入坑系列 一 双向绑定

    html代码 <div id="app"><p>{{message}}</p><span>message1</span> ...

  8. vue.js 入门案例,双向绑定实现任务清单

    vue.js 开发环境安装成功. http://localhost:8080/ 使用vue.js双向绑定实现类似这样一个任务清单页面. 下面是我的学习笔记. //app.vue页面 <templ ...

  9. Vue是怎么实现数据双向绑定的

    vue数据双向绑定原理 vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,那么vue是如果进行数据劫持的,我们可以先来看一下通过控制台输出一个定义在vue初始化数据上的对象是个什么 ...

最新文章

  1. python中二进制以什么开头_Python二进制表示和位操作
  2. 瘫痪小姐姐“自主”行走视频火了,曾借助轮椅完成舞蹈表演,网友:灵魂是战士...
  3. 记录几个vim的命令
  4. Python3.X新特性之print和exec
  5. 提升销售人员的信息处理能力
  6. OpenCASCADE:拓扑 API之历史支持
  7. OpenLiberty:注入时出错,适用于TomEE和Wildfly
  8. .rpt文件内容读取java_好程序员前端教程-nodejs如何读取文件夹目录的内容
  9. 地震与地球的内部构成
  10. 【机器学习】隐马尔可夫模型及其三个基本问题(三)模型参数学习算法及python实现
  11. JS中var和let
  12. JAVA程序打包为EXE
  13. 一线顶级互联网公司offer的成功经验【转自IT面试】
  14. 大数据可视化(七)复杂数据可视化
  15. 引力波数据居然是用 Python 分析的
  16. 移动端某些网络下域名无法解析的DNS问题
  17. SpringAOP实现报错Bean named ‘userServiceImpl‘ is expected to be of type ‘.....‘
  18. 第三届上海大学生网络安全大赛 - 登机牌WP
  19. python彼岸图网爬取1200像素预览图
  20. MySQL入门实战 一

热门文章

  1. 期望最大化算法(EM)简介
  2. 2022-2027年中国食用甜味剂行业市场全景评估及发展战略规划报告
  3. Java—数据类型与运算符
  4. 用R语言scorecard包做一张标准评分卡
  5. 微信新消息,任务栏一闪一闪问题处理
  6. 企业级高速、高匿爬虫代理IP、千万IP出口池
  7. 华为鸿蒙系统历史性,倒计时8天!华为“历史性时刻”即将到来
  8. 利用python编写一段手柄控制程序
  9. html常见的块元素与内联(行内)元素用法说明
  10. 激光熔覆comsol热流耦合模型,温度场分布和三维流场分布