0


【Vue】v-model 的使用

双向绑定 v-model

  • v-model:value="值" 可简写为 v-model="值",用于双向绑定 [表单元素] 的信息
  • 双向绑定:表单元素的 value attribute 的值 ↔ data 中对应的值
  • 本质上,v-model 是由 v-bind 配合 input 事件实现的 ① v-bind 绑定 value 属性、② 在 input 事件的回调函数中更新 value 的值

文本 input [text]

<divid="app"><p>Message is: {{ msg }}</p><!-- 给 input 标签元素设置 v-model 属性 --><inputv-model="msg"type="text"/></div>
let vm =newVue({el:'#app',data:{msg:'superman'},});

上例中,input 的默认值为 data 中的 msg,更新 input 的 value 值 → msg 也会被更新 → p 显示的内容也会被更新

多行文本 textarea

  • 对于文本域标签 <textarea>,用法与 type=“text” 的 input 标签一样
  • 虽然 <textarea> 是双标签,但 <textarea> {{msg}} </textarea> 并不会生效,要设置 v-model 属性来替代
<textareav-model="msg"></textarea>

单选框 input [radio]

  • 因为 v-model 绑定的是 value 值所以,我们需要设置 value 属性;如果没有设置 value 属性,则获取到的值为 null
<inputtype="radio"id="male"value="male"v-model="sex"/><labelfor="male">male</label><br/><inputtype="radio"id="female"value="female"v-model="sex"/><labelfor="female">female</label><br/><span>sex: {{ sex }}</span>
let vm =newVue({el:'#app',data:{sex:'',// sex: "male" // 设置默认值 'male',默认选中 male 选项},});

复选框 input [checkbox]

  1. 没有配置 value 属性,收集的是 checkbox 的 checked 状态,所以会收集到布尔值
<inputtype="checkbox"id="checkbox"v-model="checked"/><labelfor="checkbox">{{checked}}</label>
let vm =newVue({el:'#app',data:{checked:true},// 绑定 [布尔值]});
  1. 配置了 value 属性,绑定 [非数组],收集的也还是 checkbox 的 checked 状态 所以也还是会收集到布尔值 → ture-全选、false-全不选
篮球
<inputtype="checkbox"value="篮球"v-model="checked"/>
足球
<inputtype="checkbox"value="足球"v-model="checked"/>
网球
<inputtype="checkbox"value="网球"v-model="checked"/><p>{{checked}}</p>
  1. 配置了 value 属性,绑定 [数组],才能收集到多选框的 value
篮球
<inputtype="checkbox"value="篮球"v-model="checked"/>
足球
<inputtype="checkbox"value="足球"v-model="checked"/>
网球
<inputtype="checkbox"value="网球"v-model="checked"/><p>{{checked}}</p>
let vm =newVue({el:'#app',data:{checked:[],// 绑定到数组},});
  • 能获取到多个值的表单元素,都应该绑定 [数组],以存储多个数据

选择框 select > option

  • 对于下拉菜单,推荐提供一个值为空的禁用选项,作为默认显示选项
<selectv-model="selected"><optiondisabledvalue="">
        国家
    </option><optionvalue="China">中国</option><optionvalue="America">美国</option><optionvalue="Japan">日本</option></select><span>Selected: {{ selected }}</span>
let vm =newVue({el:'#app',data:{selected:'',// selected: "China" // 设置默认值},});
  • 如果 option 标签不设置 value 属性,则获取到的是 option 标签的内容
<selectv-model="selected"><optiondisabledvalue="">
        国家
    </option><option>中国</option><option>美国</option><option>日本</option></select><span>Selected: {{ selected }}</span>
  • 多选时,绑定到一个数组
<selectmultiplev-model="selected"><optiondisabledvalue="">
        国家
    </option><option>中国</option><option>美国</option><option>日本</option></select><span>Selected: {{ selected }}</span>
let vm =newVue({el:'#app',data:{selected:[],// 绑定到数组},});

标签修饰符

  1. .lazy:在 change 事件之后同步,即失焦再同步(默认 input 事件之后同步,即一边写一边同步)
  2. .trim:过滤首尾空白字符
  3. .number:将输入数据使用 parseFloat() 转为 Number 类型;若这个值无法被 parseFloat() 解析,则会返回输入的字符串
<inputtype="text"v-model.lazy="username"/><span>{{ username }}</span><br/><inputtype="text"v-model.trim="password"/><span>{{ password }}</span><br/><!-- type="number" 能限制 input 只能输入数字 --><inputtype="number"v-model.number="age"/><span>{{ age }}</span><br/><!-- v-model.number="age" 会将数据转为 Number 类型 --><inputtype="text"v-model.number="height"/><span>{{ height }}</span>
表单提交事件
  • submit 提交表单时触发
  • .prevent 阻止默认行为
<[email protected]="console.log('submit successfully')"></form>

Vue2 组件使用 v-model

v-model

其实是

v-bind:value

+

v-on:input

的语法糖

<template><div>
        {{ demoText }}
        <input:value="demoText"@input="ev => (demoText = ev.target.value)"/><inputv-model="demoText"/></div></template><script>exportdefault{name:'App',data(){return{demoText:'demoText',};},};</script>

同理,在自定义组件上使用:

<template><div>
        {{ demoText }}
        <HelloWorld:value="demoText"@input="val => (demoText = val)"/><HelloWorldv-model="demoText"/></div></template><script>import HelloWorld from'@/components/HelloWorld.vue';exportdefault{name:'App',components:{ HelloWorld },data(){return{demoText:'demoText',};},};</script>

需要注意的是:自定义组件上的

:value

变成了自定义属性,

@input

变成了自定义事件

<template><inputtype="text":value="value"@input="$emit('input', $event.target.value)"/><!-- $emit('input', $event.target.value) 表示触发自定义事件, 传入 $event.target.value 作为参数--></template><script>exportdefault{name:'HelloWorld',props:['value'],// 接收自定义属性};</script>

.sync 修饰符

上例可以优化成:

<template><div>
        {{ demoText }}
        <HelloWorld:title="demoText"@update:title="demoText = $event"/></div></template>
<template><inputtype="text":value="title"@input="$emit('update:title', $event.target.value)"/></template><script>exportdefault{name:'HelloWorld',props:['title'],};</script>

这种写法可以使用语法糖

<template><div>
        {{ demoText }}
        <HelloWorldv-bind:title.sync="demoText"/></div></template>

注意:带有

.sync

修饰符的

v-bind

不能和表达式一起使用;eg:

v-bind:title.sync="doc.title + '!'"

是无效的

  • 当我们用一个对象同时设置多个 prop 的时候,也可以将这个 .sync 修饰符和 v-bind 配合使用
<HelloWorldv-bind.sync="doc"></HelloWorld>

这样会把

doc

对象中的每一个 property (如

title

) 都作为一个独立的 prop 传进去,然后各自添加用于更新的

v-on

监听器

注意:将

v-bind.sync

用在一个字面量的对象上,eg:

v-bind.sync="{ title: doc.title }"

,是无法正常工作的
因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑

Vue3 组件使用 v-model

  • 在普通标签元素上使用 v-model
<template>
    {{ textDemo }}
    <inputv-model="textDemo"/></template><scriptsetuplang="ts">import{ ref }from'vue';const textDemo =ref('textDemo');</script>

上例等价于

<template>
    {{ textDemo }}
    <input:value="textDemo"@input="textDemo = ($event.target as any).value"/></template>
  • 在自定义组件上使用 v-model
<template><HelloWorldv-model="textDemo"/></template><scriptlang="ts"setup>import{ ref }from'vue';import HelloWorld from'@/components/HelloWorld.vue';const textDemo =ref('Vue.js');</script>

上例等价于

<template><HelloWorld:modelValue="textDemo"@update:modelValue="(newValue:any) => (textDemo = newValue)"/></template>

此时,子组件内需要做两件事:
① 将原生

input

元素的

value

attribute 绑定到

modelValue

prop
② 当原生的

input

事件触发时,触发一个携带了新值的

update:modelValue

自定义事件

<template>
    {{ modelValue }}
    <inputtype="text":value="modelValue"@input="$emit('update:modelValue', ($event.target as any).value)"/></template><scriptlang="ts"setup>
defineProps<{modelValue: string }>();// 接收 `modelValue` prop
defineEmits<{(e:'update:modelValue',val: string):void}>();// 接收 `update:modelValue` 自定义事件</script>

v-model 的参数

  • 默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件
  • 可以给 v-model 指定一个参数来更改这些名字
<template><!-- 设置 v-model 的参数 title --><HelloWorldv-model:title="textDemo"/></template><scriptlang="ts"setup>import{ ref }from'vue';import HelloWorld from'@/components/HelloWorld.vue';const textDemo =ref('Vue.js');</script>
<template>
    {{ title }}
    <inputtype="text":value="title"@input="$emit('update:title', ($event.target as any).value)"/></template><scriptlang="ts"setup>
defineProps<{title: string }>();// v-model 的参数名 title 作为 prop
defineEmits<{(e:'update:title',val: string):void}>();// 自定义事件名也变成了 update:title</script>

v-model 的修饰符

  • v-model 有一些内置的修饰符 (.trim.number.lazy)
  • 若使用了自定义修饰符,可通过 modelModifiers prop 在组件内访问该自定义修饰符
  • 若 v-model 携带着参数,eg: v-model:title,则 prop 为 titleModifiers
<template>
    {{ title }}
    <inputtype="text":value="title"@input="$emit('update:title', ($event.target as any).value)"/></template><scriptlang="ts"setup>const props =withDefaults(
    defineProps<{title: string;titleModifiers:{};// 接收 prop titleModifiers}>(),{title:'',titleModifiers:()=>({}),// 设置默认值为空对象});
defineEmits<{(e:'update:title',val: string):void}>();

console.log(props.titleModifiers);// { capitalize: true }</script>

上例中,

props.titleModifiers

的值为

{ capitalize: true }

,是因为 v-model 使用了修饰符

capitalize

有了这个 prop,就可以检查

modelModifiers

对象的 key,并编写一个处理函数以改变抛出的值

<template>
    {{ title }}
    <inputtype="text":value="title"@input="emitValue"/></template><scriptlang="ts"setup>const props =withDefaults(
    defineProps<{title: string;titleModifiers:{};}>(),{title:'',titleModifiers:()=>({}),});const emit = defineEmits<{(e:'update:title',val: string):void}>();functionemitValue(e: any){let value = e.target.value;if((props.titleModifiers as any).capitalize){
        value = value.charAt(0).toUpperCase()+ value.slice(1);}emit('update:title', value);}</script>

本文转载自: https://blog.csdn.net/Superman_H/article/details/128834328
版权归原作者 JS.Huang 所有, 如有侵权,请联系我们删除。

“【Vue】v-model 的使用”的评论:

还没有评论