当前位置: 首页 > news >正文

vue3的深入组件-组件 v-model

组件 v-model
基本用法​

v-model 可以在组件上使用以实现双向绑定。

从 Vue 3.4 开始,推荐的实现方式是使用 defineModel() 宏:

<script setup>
const model = defineModel()function update() {model.value++
}
</script><template><div>Parent bound v-model is: {{ model }}</div><button @click="update">Increment</button>
</template>

父组件可以用 v-model 绑定一个值:

<script setup lang="ts">
import { useAppStore } from '@/store/modules/app'
const appStore =  useAppStore()
import modelChild from './components/test/modelChild.vue'
const textColor = computed(() => appStore.getTextColor)
appStore.initTheme()
const countModel = ref(10)
</script><template><ConfigGlobal><p :style="{'color':textColor}"  >p标签</p>{{ countModel }}<modelChild v-model="countModel"></modelChild></ConfigGlobal></template>

显示如下:
在这里插入图片描述

defineModel() 返回的值是一个 ref。它可以像其他 ref 一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用:

  • 它的 .value 和父组件的 v-model 的值同步;
  • 当它被子组件变更了,会触发父组件绑定的值一起更新。
    这意味着你也可以用 v-model 把这个 ref 绑定到一个原生 input 元素上,在提供相同的 v-model 用法的同时轻松包装原生 input 元素:
child.vue<script setup>
const model = defineModel()
</script><template><span>My input</span> <input v-model="model">
</template>
// app.vue
<script setup>
import Child from './Child.vue'
import { ref } from 'vue'const msg = ref('Hello World!')
</script><template><h1>{{ msg }}</h1><Child v-model="msg" />
</template>
底层机制

defineModel 是一个便利宏。编译器将其展开为以下内容:

  • 一个名为 modelValue 的 prop,本地 ref 的值与其同步;
  • 一个名为 update:modelValue 的事件,当本地 ref 的值发生变更时触发。
<!-- Child.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script><template><input:value="modelValue"@input="emit('update:modelValue', $event.target.value)"/>
</template><!-- Parent.vue -->
<template><ConfigGlobal><p :style="{'color':textColor}"  >p标签</p>{{ foo }}<modelChild :modelValue="foo"@update:modelValue="$event => (foo = $event)"></modelChild></ConfigGlobal></template>

因为 defineModel 声明了一个 prop,你可以通过给 defineModel 传递选项,来声明底层 prop 的选项:
子组件

<script setup>
const model = defineModel({required:true, default: 1 }) // 对应 model 参数
</script><template><input v-model="model" type="text"><!-- <input v-model="age" type="number"> -->
</template>

父组件

<script setup lang="ts">
const countModel = ref()
console.log(countModel.value,'countModel'); // undefined
</script>
<template><ConfigGlobal>{{ countModel }}<modelChild v-model="countModel"></modelChild></ConfigGlobal></template>

如果为 defineModel prop 设置了一个 default 值且父组件没有为该 prop 提供任何值,会导致父组件与子组件之间不同步。在下面的示例中,父组件的 countModel 是 undefined,而子组件的 model 是 1:

v-model 的参数
//子组件
<script setup>
const title = defineModel('title')
</script><template><input type="text" v-model="title" />
</template>// 父组件
<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'const bookTitle = ref('v-model argument example')
</script><template><h1>{{ bookTitle }}</h1><MyComponent v-model:title="bookTitle" />
</template>
不同属性绑定多个 v-model

父组件​

<UserForm v-model:username="user.name"v-model:age="user.age"
/>

子组件

<script setup>
const username = defineModel('username') // 对应 username 参数
const age = defineModel('age') // 对应 age 参数
</script><template><input v-model="username" type="text"><input v-model="age" type="number">
</template>
处理 v-model 修饰符

父组件
使用内置修饰符(如 .trim):

<Child v-model.trim="text" />

子组件

<script setup>
const [model, modifiers] = defineModel() // 解构出修饰符// 根据修饰符调整值
const processedModel = computed({get: () => model.value,set: (value) => {if (modifiers.trim) {model.value = value.trim()} else {model.value = value}}
})
</script><template><input v-model="processedModel" />
</template>
  • 使用自定义修饰符 .capitalize:
    创建一个自定义的修饰符 capitalize,它会自动将 v-model 绑定输入的字符串值第一个字母转为大写

父组件

<Child v-model.capitalize="text" />

子组件​​
通过 set 选项处理修饰符逻辑

<script setup>
const [model, modifiers] = defineModel({set(value) {if (modifiers.capitalize) {return value.charAt(0).toUpperCase() + value.slice(1)}return value}
})
</script><template><input type="text" v-model="model" />
</template>
带参数的 v-model 修饰符

父组件

<UserForm v-model:username.trim="user.name"v-model:age.number="user.age"
/>

子组件​​
分别处理每个参数的修饰符:

<script setup>
const [username, usernameModifiers] = defineModel('username')
const [age, ageModifiers] = defineModel('age')// 处理 username 的 trim 修饰符
const processedUsername = computed({get: () => username.value,set: (val) => {username.value = usernameModifiers.trim ? val.trim() : val}
})// 处理 age 的 number 修饰符
const processedAge = computed({get: () => age.value,set: (val) => {age.value = ageModifiers.number ? Number(val) : val}
})
</script><template><input v-model="processedUsername" /><input v-model="processedAge" type="number" />
</template>

相关文章:

  • 免费AI图像编辑平台,最新无损放大技术
  • 无刷电机控制算法策略
  • 985高校查重率“隐性阈值”:低于5%可能被重点审查!
  • 4:点云处理—去噪、剪切、调平
  • RT Thread Studio修改控制台串口
  • 【杂谈】Godot 2D游戏窗口设置
  • NeurIPS 2024 | 工业质检缺陷检测相关论文梳理
  • OpenCV定位地板上的书
  • 了解Dockerfile
  • cat、more和less的区别
  • WHAT - ahooks vs swr 请求
  • 【万字长文】深入浅出 LlamaIndex 和 LangChain:从RAG到智能体,轻松驾驭LLM应用开发
  • 关于form、自定义Hook、灰度发布、正则表达(只能输入数字和不要空格)
  • kafka logs storage
  • 【LeetCode 热题 100】二叉树 系列
  • 深入解析 C# 常用数据结构:特点、区别与优缺点分析
  • 快速上手Pytorch Lighting框架 | 深度学习入门
  • 经济体制1
  • 网络基础入门第6-7集(抓包技术)
  • 含铜废水循环利用体系
  • 国家主席习近平同普京总统出席签字和合作文本交换仪式
  • 妻子藏匿一岁幼儿一年多不让丈夫见,法院发出人格权侵害禁令
  • 北约年度报告渲染所谓“中国核威胁”,国防部回应
  • 胖东来发布和田玉、翡翠退货说明:不扣手续费等任何费用
  • 谜语的强制力:弗洛伊德与俄狄浦斯
  • 多地跟进官宣下调公积金贷款利率,最低降至2.1%