vue3.0深入v-model以及使用多个v-model
v-model原理
- 原理:其实是一个语法糖 通过props 和 emit组合而成的语法糖
- 默认值的改变
- prop:value -> modelValue;
- 事件:input -> update:modelValue;
- 注意点:就是 v-bind 的 .sync 修饰符和组件的 model 选项已移除 (因为 为了实现 update:modelValue值更新,暂居了之前的 .sync的写法)
- 注意点2:新增 支持多个v-model
- 注意点3:新增 支持自定义 修饰符
v-mode的实现 父子组件的通信
父组件 Main.vue
<template>
<div>
<div>Main - flag - {{ flag }}</div>
<button @click="flag = !flag">修改 flag</button>
<Dialog v-model="flag" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let flag = ref<Boolean>(true)
import Dialog from './childCom/Dialog.vue'
</script>
<script lang="ts">
export default {
name: 'Main',
}
</script>
子组件 Dialog.vue
<template>
<div v-if="modelValue" class="dialog">
<div class="dialog-header">
<span>标题</span>
<button @click="close">关闭</button>
</div>
<div class="dialog-main">
{{ modelValue }}
</div>
</div>
</template>
<script setup lang="ts">
type Props = {
modelValue: Boolean
}
defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const close = () => {
emit('update:modelValue', false)
}
</script>
<script lang="ts">
export default {
name: 'Dialog',
}
</script>
<style lang="scss" scoped>
.dialog {
width: 400px;
height: 250px;
border: 1px solid #ccc;
&-header {
height: 40px;
border: 1px solid #ccc;
}
&-body {
height: 210px;
}
}
</style>
- 效果
- 父组件之中,点击 修改flag的时候,可以控制dialog组件的显示和隐藏
- 子组件 dialog 之中 点击关闭的时候,可以修改父组件的 flag的值
v-model 使用多个
main.vue
<template>
<div>
<div>Main - 标志 - {{ flag }} 标题 - {{ title }}</div>
<button @click="flag = !flag">修改 flag</button>
<Dialog v-model="flag" v-model:title="title" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let flag = ref<Boolean>(true)
import Dialog from './childCom/Dialog.vue'
let title = ref<String>('我是小渣亮')
</script>
<script lang="ts">
export default {
name: 'Main',
}
</script>
<style lang="scss" scoped></style>
dialog.vue
<template>
<div v-if="modelValue" class="dialog">
<div class="dialog-header">
<span>标题 - {{ title }}</span>
<button @click="close">关闭</button>
</div>
<div class="dialog-main">
<button @click="changTitle">修改 标题</button>
{{ modelValue }}
</div>
</div>
</template>
<script setup lang="ts">
type Props = {
modelValue: Boolean
title: String
}
defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'update:title'])
const close = () => {
emit('update:modelValue', false)
}
const changTitle = () => {
emit('update:title', '我就是狗啊')
}
</script>
<script lang="ts">
export default {
name: 'Dialog',
}
</script>
<style lang="scss" scoped>
.dialog {
width: 400px;
height: 250px;
border: 1px solid #ccc;
&-header {
height: 40px;
border: 1px solid #ccc;
}
&-body {
height: 210px;
}
}
</style>
- 效果
v-model 自定义修饰符
- 给v-model自定义修饰符
- 也可以给另外的v-model:title添加自定义修饰符
给v-model自定义修饰符
main.vue
<template>
<div>
<div>Main - 标志 - {{ flag }} 标题 - {{ title }}</div>
<button @click="flag = !flag">修改 flag</button>
<!-- 添加xzl -->
<!-- <Dialog v-model.xzl="flag" v-model:title="title" /> 修饰符 -->
<!-- 没有添加 xzl修饰符 -->
<Dialog v-model="flag" v-model:title="title" />
<B />
<C />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let flag = ref<Boolean>(true)
import Dialog from './childCom/Dialog.vue'
import B from './childCom/B.vue'
import C from './childCom/C.vue'
let title = ref<String>('我是小渣亮')
</script>
<script lang="ts">
export default {
name: 'Main',
}
</script>
<style lang="scss" scoped></style>
dialog.vue
<template>
<div v-if="modelValue" class="dialog">
<div class="dialog-header">
<span>标题 - {{ title }}</span>
<button @click="close">关闭</button>
</div>
<div class="dialog-main">
<button @click="changTitle">修改 标题</button>
{{ modelValue }}
</div>
</div>
</template>
<script setup lang="ts">
type Props = {
modelValue: Boolean
title: String
modelModifiers?: {
xzl: Boolean
}
}
const propsData = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'update:title'])
const close = () => {
emit('update:modelValue', false)
}
const changTitle = () => {
if (propsData.modelModifiers?.xzl) {
emit('update:title', '我就是狗之zxl')
} else {
emit('update:title', '我就是狗之非xzl')
}
}
</script>
<script lang="ts">
export default {
name: 'Dialog',
}
</script>
<style lang="scss" scoped>
.dialog {
width: 400px;
height: 250px;
border: 1px solid #ccc;
&-header {
height: 40px;
border: 1px solid #ccc;
}
&-body {
height: 210px;
}
}
</style>
- 效果