ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
>[success] # v-model 1. 常见表单元素:`input(radio, text, address, email....)`、`select`、 `checkbox`、 `textarea` 2. 如果想在表单元素上进行双向绑定写法 ~~~ <input :value="text" @input="event => text = event.target.value"> ~~~ 3. `vue` 也提供了`v-model` 这个语法糖可以更简单的进行在表单元素上创建双向数据绑定 ~~~ <input v-model="text"> ~~~ 4. `v-model` 配合 `input `使用时候语法糖形式绑定事件也不同[源码参考](https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-dom/src/directives/vModel.ts#L52-L59) * `text `和 `textarea `元素使用 `value property` 和 `input `事件; * `checkbox `和 `radio `使用 `checked property` 和 `change `事件; * `select `字段将 `value `作为 `prop `并将 `change `作为事件。 5. 组件也可以使用`v-model` 具体参考组件章节 >[info] ## 原生实现类vue 双向绑定 1. `v-model`配合`input`使用时候语法糖形式绑定事件也不同[源码参考](https://github1s.com/vuejs/core/blob/HEAD/packages/runtime-dom/src/directives/vModel.ts#L52-L59)因此本质上还是对dom 操作,使用原生做一个类似实现效果 >[danger] ##### input[text] -- onInput ![](https://img.kancloud.cn/f0/ab/f0ab9d612e3beea6115be206da566acf_449x70.png) ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div> <div id="inputTextVal"></div> <input id="text" value="" /> </div> <script> // 普通文本输入 ;(function inputText() { const textDom = document.getElementById('text') textDom.addEventListener('input', function (e) { document.getElementById('checkboxVal').innerText = e.target.value console.log(e.target.value) }) })() </script> </body> </html> ~~~ >[danger] ##### input[checkbox] -- onChange 1. `checkbox` 在原生中如果被选中会在节点上增加`checked` 属性,只要收集`name`属性标记相同一组`checkbox` 中`value`属性即可 ![](https://img.kancloud.cn/05/46/0546afce7fa97a316890012d12f6ce68_466x112.png) ~~~html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div> <div id="checkboxVal"></div> <input type="checkbox" value="1" /> 足球 <input type="checkbox" value="2" /> 篮球 <input type="checkbox" value="3" /> 乒乓球 </div> <script> // checkbox 多选 ;(function inputCheckbox() { const ls = [] const checkList = document.querySelectorAll( 'input[type="checkbox"]' ) // 绑定事件 function checkChange(callback) { checkList.forEach((item) => { item.addEventListener('change', function (e) { if (e.target.checked) { ls.push(e.target.value) } else { const index = ls.findIndex((val) => { val === e.target.value }) ls.splice(index, 1) } callback?.() }) }) } // 数据渲染页面 checkChange(() => { document.getElementById('checkboxVal').innerText = ls.toString() }) })() </script> </body> </html> ~~~ >[danger] ##### radio -- onChange 1. `radio` 需要配合 `name` 字段形成互斥,绑定`change` 事件获取 `value` 即可 ![](https://img.kancloud.cn/6b/c2/6bc2e79b46019b066d797f5d90219883_226x78.png) ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div> <div id="radioVal"></div> <input type="radio" name="gender" value="1" /> 男 <input type="radio" name="gender" value="2" /> 女 </div> <script> ;(function inputRadio() { const radioChecked= document.querySelector( 'input[type="radio"]' ) // 绑定事件 function checkChange(callback) { radioChecked.addEventListener('change', function (e) { callback?.(e.target.value) }) } // 数据渲染页面 checkChange((val) => { document.getElementById('radioVal').innerText = val }) })() </script> </body> </html> ~~~ >[danger] ##### select -- onChange ![](https://img.kancloud.cn/88/7e/887e42a6ab8f96586a8779989259700e_318x181.png) ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div> <div id="selectedVal"></div> <select id="ss"> <option value="1">大连</option> <option value="2">上海</option> <option value="3">北京</option> <option value="4" id="op1">天津</option> </select> </div> <script> ;(function selected() { const selected = document.querySelector('#ss') // 绑定事件 selected.addEventListener('change', function (e) { console.log(e.target.value) const option = document.querySelector( `option[value="${e.target.value}"]` ) document.getElementById('selectedVal').innerText = e.target.value + ',' + option.textContent }) })() </script> </body> </html> ~~~ >[info] ## v-model 和 原生属性 1. `v-model`会忽略任何表单元素上初始的`value`、`checked`或`selected`attribute。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。你应该在 JavaScript 中使用`data`选项来声明该初始值。理解为在上面原生案例可以知道其实通过`dom `原生提供的固定标记属性来获取选中值,当你在`vue `中使用` v-model`,这些属性将会被忽略,v-model 只会对自己数据源负责 vue自己`true-value`和`false-value` 也需要后续补充 >[danger] ##### 修饰符 - lazy 1. 默认情况下,`v-model`在进行双向绑定时,绑定的是`input`事件,那么会在每次内容输入后就将最新的值和绑定的属性进行同步 2. `v-model`后跟上lazy修饰符,那么会将绑定的事件切换为 `change `事件,只有在提交时才会触发 ~~~ <!-- 在 "change" 事件后同步更新而不是 "input" --> <input v-model.lazy="msg" /> ~~~ >[danger] ##### 修饰符 - number 1. `v-model`绑定后的值总是`string`类型,`vue2`即使在我们设置`type`为`number`也是`string`类型,`vue3`在`number`修饰符会在输入框有`type="number"`时自动启用 2. 希望转换为数字类型,那么可以使用 `.number `修饰符 ~~~ <input v-model.number="age" /> ~~~ >[danger] ##### 修饰符 - .trim 1. 你想要默认自动去除用户输入内容中两端的空格,你可以在` v-model `后添加` .trim` 修饰 ~~~ <input v-model.trim="msg" /> ~~~ >[danger] ##### 官网给的提示 对于需要使用[IME](https://en.wikipedia.org/wiki/Input_method)的语言 (中文,日文和韩文等),你会发现`v-model`不会在 IME 输入还在拼字阶段时触发更新。如果你的确想在拼字阶段也触发更新,请直接使用自己的`input`事件监听器和`value`绑定而不要使用`v-model`。 >[danger] ##### 官网参考 [v-model](https://cn.vuejs.org/guide/essentials/forms.html#checkbox-2)