1️⃣ 基础用法1️⃣ input2️⃣ type=text 文本框2️⃣ textarea 多行文本2️⃣ type=checkbox 复选框3️⃣ 单个复选框3️⃣ 多个复选框2️⃣ 单选按钮2️⃣ type=radio 单选框1️⃣ 值绑定2️⃣ 复选框2️⃣ 单选按钮2️⃣ 选择框的选项1️⃣ 修饰符2️⃣ .lazy - 延迟更新2️⃣ .number - 只能输入数字2️⃣ .trim - 去除首尾空格2️⃣ 在组件上使用 v-model3️⃣ 父组件3️⃣ 子组件1️⃣ v-model 原理你可以用 v-model 指令在表单 、 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。 <a name="7foQW"></a></p> <h1 id="1xhh1w"><a name="1xhh1w" class="reference-link"></a><span class="header-link octicon octicon-link"></span>1️⃣ 基础用法</h1><p>可以在表单元素上创建双向数据绑定。即数据更新元素更新、元素更新数据也会更新。<br />本质上 v-model 为语法糖</p> <table> <thead> <tr> <th>元素类型</th> <th>属性</th> <th>事件</th> </tr> </thead> <tbody> <tr> <td>input[type=text]、textarea</td> <td>value</td> <td>input</td> </tr> <tr> <td>input[checkbox]、input[radio]</td> <td>checked</td> <td>change</td> </tr> <tr> <td>select</td> <td></td> </tr> </tbody> </table> <p>实现原理</p> <pre><code class="lang-html"><template> <div id="app"> <input type="text" v-on:input="inp" v-bind:value="val" /> <p>{{ val }}</p> </div> </template> <script> export default { data() { return { val: "实现原理", }; }, methods: { inp(e) { this.val = e.target.value; }, }, }; </script> </code></pre> <p><a name="7y7GJ"></a></p> <h1 id="amnj6k"><a name="amnj6k" class="reference-link"></a><span class="header-link octicon octicon-link"></span>1️⃣ input</h1><p><a name="4nvsx"></a></p> <h2 id="1iiibx"><a name="1iiibx" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ type=text 文本框</h2><pre><code class="lang-html"><template> <div id="app"> <input type="text" v-model="msg" /> <h1>{{ msg }}</h1> </div> </template> <script> export default { data() { return { msg: "v-model", }; }, }; </script> </code></pre> <p><a name="Wydio"></a></p> <h2 id="cmrbqd"><a name="cmrbqd" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ textarea 多行文本</h2><pre><code class="lang-html"><template> <div id="app"> <textarea v-model="msg" /> <h1>{{ msg }}</h1> </div> </template> <script> export default { data() { return { msg: "v-model", }; }, }; </script> </code></pre> <p><a name="drEdW"></a></p> <h2 id="1ae7q8"><a name="1ae7q8" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ type=checkbox 复选框</h2><p><a name="8qOph"></a></p> <h3 id="a6xizq"><a name="a6xizq" class="reference-link"></a><span class="header-link octicon octicon-link"></span>3️⃣ 单个复选框</h3><p>绑定到布尔值,v-model=”Boolean”</p> <pre><code class="lang-html"><template> <div id="app"> <input type="checkbox" v-model="checked" /> <label for="checkbox">{{ checked }}</label> </div> </template> <script> export default { data() { return { checked: true, }; }, }; </script> </code></pre> <p><a name="oeOHk"></a></p> <h3 id="6q0zy"><a name="6q0zy" class="reference-link"></a><span class="header-link octicon octicon-link"></span>3️⃣ 多个复选框</h3><p>绑定到同一个数组,v-model=”Array”,数组中的值为被选中的 input 框 value 值</p> <pre><code class="lang-vue"><template> <div id="app"> <input type="checkbox" id="cheng" value="one" v-model="checkedNum" /> <label for="one">ONE</label> <input type="checkbox" id="deng" value="two" v-model="checkedNum" /> <label for="two">TWO</label> <input type="checkbox" id="tong" value="three" v-model="checkedNum" /> <label for="three">THREE</label> <span>被选中的人数字有: {{ checkedNum }}</span> </div> </template> <script> export default { data() { return { checkedNum: [], }; }, }; </script> </code></pre> <p><a name="ArT1U"></a></p> <h2 id="13i0zo"><a name="13i0zo" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ 单选按钮</h2><blockquote> <p>注意:如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,可以提供一个值为空的禁用选项:</p> </blockquote> <p><code><option>A</option></code></p> <pre><code class="lang-vue"><template> <div id="app"> <select v-model="selected"> <!-- 提供一个值为空的禁用选项 --> <option :disabled="selected">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>选择: {{ selected === "请选择" ? "" : selected }}</span> </div> </template> <script> export default { data() { return { selected: "请选择", }; }, }; </script> </code></pre> <p><a name="NLwWM"></a></p> <h2 id="cbsaw8"><a name="cbsaw8" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ type=radio 单选框</h2><pre><code class="lang-vue"><template> <div id="app"> <input type="radio" id="1" value="one" v-model="picked" /> <label for="one">ONE</label> <input type="radio" id="2" value="two" v-model="picked" /> <label for="two">TWO</label> <input type="radio" id="3" value="three" v-model="picked" /> <label for="three">THREE</label> <span>被选中的人数字是: {{ picked }}</span> </div> </template> <script> export default { data() { return { picked: "", }; }, }; </script> </code></pre> <p><a name="r8GwC"></a></p> <h1 id="252ni2"><a name="252ni2" class="reference-link"></a><span class="header-link octicon octicon-link"></span>1️⃣ 值绑定</h1><p>对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 ( 对于复选框也可以是布尔值 ):</p> <pre><code class="lang-vue"><template> <div id="app"> <!-- 当选中时,`picked` 为字符串 "a" --> <input type="radio" v-model="picked" value="a" /> <p>{{ picked }}</p> <!-- `toggle` 为 true 或 false --> <input type="checkbox" v-model="toggle" /> <p>{{ toggle ? "true" : "选中时值为 true" }}</p> <!-- 当选中第一个选项时,`selected` 为字符串 "abc" --> <select v-model="selected"> <option value="abc">ABC</option> </select> <p>{{ selected }}</p> </div> </template> <script> export default { data() { return { picked: "选中时值为 a", toggle: false, selected: "选中时值为 abc", }; }, }; </script> </code></pre> <p>但是有时我们可能想把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind 实现,并且这个 property 的值可以不是字符串。 <a name="dWE8R"></a></p> <h2 id="185rge"><a name="185rge" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ 复选框</h2><blockquote> <p>这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(即“yes”或“no”),请换用单选按钮。</p> </blockquote> <pre><code class="lang-vue"><template> <div id="app"> <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" /> <p>{{ toggle }}</p> </div> </template> <script> export default { data() { return { toggle: false, }; }, }; </script> </code></pre> <p><a name="35f1J"></a></p> <h2 id="bp3m29"><a name="bp3m29" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ 单选按钮</h2><pre><code class="lang-vue"><template> <div id="app"> <input type="radio" v-model="pick" v-bind:value="xz" /> <p>{{ pick }}</p> </div> </template> <script> export default { data() { return { pick: false, xz: "选中啦", }; }, }; </script> </code></pre> <p><a name="il4lY"></a></p> <h2 id="f2svzd"><a name="f2svzd" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ 选择框的选项</h2><pre><code class="lang-vue"><template> <div id="app"> <select v-model="selected"> <!-- 内联对象字面量 --> <option v-bind:value="{ number: 123 }">123</option> </select> <p>{{ selected.number }}</p> </div> </template> <script> export default { data() { return { selected: false, }; }, }; </script> </code></pre> <p><a name="rmT2B"></a></p> <h1 id="277stc"><a name="277stc" class="reference-link"></a><span class="header-link octicon octicon-link"></span>1️⃣ 修饰符</h1><p><a name="oejMH"></a></p> <h2 id="79k9kk"><a name="79k9kk" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ .lazy - 延迟更新</h2><p>在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 ( 除了上述输入法组合文字时 )。你可以添加 lazy 修饰符,从而转为在 确定之后进行同步 ( input 失焦后更新 )</p> <pre><code class="lang-vue"><template> <div id="app"> <input v-model.lazy="msg" /> <p>{{ msg }}</p> </div> </template> <script> export default { data() { return { msg: "message", }; }, }; </script> </code></pre> <p><a name="hQDei"></a></p> <h2 id="53b3h4"><a name="53b3h4" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ .number - 只能输入数字</h2><p>如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:</p> <pre><code class="lang-vue"><template> <div id="app"> <input v-model.number="msg" type="number" /> <p>{{ msg }}</p> </div> </template> <script> export default { data() { return { msg: 10, }; }, }; </script> </code></pre> <p>这通常很有用,因为即使在 type=”number” 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。 <a name="Reu0h"></a></p> <h2 id="cbukxe"><a name="cbukxe" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ .trim - 去除首尾空格</h2><p>如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:</p> <pre><code class="lang-vue"><template> <div id="app"> <input v-model.trim="msg" /> <p>{{ msg }}</p> </div> </template> <script> export default { data() { return { msg: "message", }; }, }; </script> </code></pre> <p><a name="cQadb"></a></p> <h2 id="1d0hfl"><a name="1d0hfl" class="reference-link"></a><span class="header-link octicon octicon-link"></span>2️⃣ 在组件上使用 v-model</h2><p>HTML 原生的输入元素类型并不总能满足需求。幸好,Vue 的组件系统允许你创建具有完全自定义行为且可复用的输入组件。这些输入组件甚至可以和 v-model 一起使用! <a name="GIAuE"></a></p> <h3 id="27kkqb"><a name="27kkqb" class="reference-link"></a><span class="header-link octicon octicon-link"></span>3️⃣ 父组件</h3><pre><code class="lang-vue"><template> <div id="app"> <comp-one v-model="val"></comp-one> </div> </template> <script> import compOne from "./view/compOne.vue"; export default { components: { compOne, }, data() { return { val: { a: 1, b: 2, c: 3, }, }; }, }; </script> </code></pre> <p><a name="RLlTI"></a></p> <h3 id="49da2v"><a name="49da2v" class="reference-link"></a><span class="header-link octicon octicon-link"></span>3️⃣ 子组件</h3><pre><code class="lang-vue"><template> <div class="comp-one"></div> </template> <script> export default { props: { value: { // 子组件必须使用 value 来接收, 父组件的 v-model 传值 type: Object, default: () => { return {}; }, }, }, created() { console.log(this.value); /* {__ob__: Observer} a: (…) b: (…) c: (…) __ob__: Observer {value: {…}, dep: Dep, vmCount: 0} get a: ƒ reactiveGetter() set a: ƒ reactiveSetter(newVal) get b: ƒ reactiveGetter() set b: ƒ reactiveSetter(newVal) get c: ƒ reactiveGetter() set c: ƒ reactiveSetter(newVal) [[Prototype]]: Object */ }, }; </script> </code></pre> <p><a name="gRgqn"></a></p> <h1 id="2nlizu"><a name="2nlizu" class="reference-link"></a><span class="header-link octicon octicon-link"></span>1️⃣ v-model 原理</h1><p><code>v-model</code> 即可以作用于表单元素,又可作用于自定义组件,无论是哪一种情况,它都是一个语法糖,最终会生成一个属性和一个事件<br />当其作用于表单元素时,<code>vue</code> 会根据作用的表单元素类型而生成合适的属性和事件。例如,作用于普通文本框的时候,它会生成 <code>value</code> 属性和 <code>input</code> 事件,而当其作用于单选框或多选框时,它会生成 <code>checked</code> 属性和 <code>change</code> 事件。<br /><code>v-model</code>也可作用于自定义组件,当其作用于自定义组件时,默认情况下,它会生成一个 <code>value</code> 属性和 <code>input</code> 事件。</p> <pre><code class="lang-vue"><Comp v-model="data" /> <!-- 等效于 --> <Comp :value="data" @input="data=$event" /> </code></pre> <p>开发者可以通过组件的<code>model</code>配置来改变生成的属性和事件</p> <pre><code class="lang-vue">// Comp const Comp = { model: { prop: "number", // 默认为 value event: "change" // 默认为 input } // ... } <Comp v-model="data" /> <!-- 等效于 --> <Comp :number="data" @change="data = $event" /> </code></pre>