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?: {
    // default: () => {}
    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>

  • 效果
    在这里插入图片描述
Logo

前往低代码交流专区

更多推荐