Vue2中的v-model
v-model即可以作用于表单元素,又可作用于自定义组件,无论是哪一种情况,它都是一个语法糖,最终会生成一个属性和一个事件
| <Comp v-model="data" /> |
| |
| <Comp :value="data" @input="data=$event" /> |
可以通过组件的model
配置来改变生成的属性和事件
| // Comp |
| const Comp = { |
| model: { |
| prop: "number", // 默认为 value |
| event: "change" // 默认为 input |
| } |
| // ... |
| } |
| Comp v-model="data" /> |
| |
| <Comp :number="data" @change="data=$event" /> |
Vue2比较让人诟病的一点就是提供了两种双向绑定:v-model和.sync
| |
| <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> |
| |
| <ChildComponent :title.sync="pageTitle" /> |
Vue3的变化
为了让v-model更好的针对多个属性进行双向绑定,Vue3作出了以下修改。
- 当对自定义组件使用v-model指令时,绑定的属性名由原来的value变为modelValue,事件名由原来的input变为update:modelValue。
| |
| <ChildComponent :value="pageTitle" @input="pageTitle = $event" /> |
| |
| <ChildComponent v-model="pageTitle" /> |
| |
| |
| <ChildComponent |
| :modelValue="pageTitle" |
| @update:modelValue="pageTitle = $event" |
| /> |
| |
| <ChildComponent v-model="pageTitle" /> |
- 去掉了.sync修饰符,它原本的功能由v-model的参数替代
| |
| <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> |
| |
| <ChildComponent :title.sync="pageTitle" /> |
| |
| |
| <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" /> |
| |
| <ChildComponent v-model:title="pageTitle" /> |
-
model配置被移除
-
允许自定义v-model修饰符
组件内部使用使用props的modelModifiers属性接受自定义修饰符
| <template> |
| <div> |
| <custom-input v-model.hello.word="message" v-model:msg.sss="message" /> |
| <p>Message: {{ message }}</p> |
| </div> |
| </template> |
| |
| <script setup lang="ts"> |
| import { ref } from 'vue'; |
| import CustomInput from './CustomInput.vue'; |
| |
| const message = ref('ssssssss'); |
| </script> |
| |
| <template> |
| <input :value="modelValue" @input="emit('update:modelValue', $event.target.value)"> |
| </template> |
| |
| <script setup> |
| import { defineProps, defineEmits } from 'vue'; |
| |
| const { modelValue, modelModifiers, msg } = defineProps(['modelValue', 'modelModifiers', 'msg']); |
| |
| console.log(modelValue,msg,modelModifiers); |
| |
| const emit = defineEmits(['update:modelValue']); |
| </script> |
使用computed拦截v-model
| <template> |
| <div> |
| <custom-input v-model="params" /> |
| </div> |
| </template> |
| |
| <script setup lang="ts"> |
| import { ref } from 'vue'; |
| import CustomInput from './CustomInput.vue'; |
| |
| const params = ref({ |
| name: '张三', |
| age: 18, |
| gender: '男', |
| }); |
| |
| </script> |
| <template> |
| <form> |
| <input v-model="modelRef.name"/> |
| <input v-model="modelRef.age" /> |
| <input v-model="modelRef.gender" /> |
| </form> |
| </template> |
| |
| <script setup> |
| import {defineEmits,defineProps, computed } from 'vue'; |
| |
| const props = defineProps(['modelValue']); |
| |
| const emit = defineEmits(['update:modelValue']); |
| |
| |
| function useVmodel(props, prop, emit) { |
| return computed({ |
| get() { |
| return new Proxy(props[prop], { |
| get(target, key) { |
| |
| return Reflect.get(target, key) |
| }, |
| set(target, key, value) { |
| |
| emit('update:' + prop, { |
| ...target, |
| [key]: value |
| }) |
| return true |
| } |
| }) |
| }, |
| set(value) { |
| emit('update:'+prop, value) |
| } |
| }) |
| } |
| |
| const modelRef = useVmodel(props, 'modelValue', emit) |
| </script> |
| |
| <style> |
| input { |
| border: 1px solid #000; |
| margin: 20px; |
| } |
| </style> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南