vue3.0 goes deep into v-model and uses multiple v-models

vue3.0 goes deep into v-model and uses multiple v-models

v-model principle

  • Principle: In fact, it is a syntactic sugar composed of props and emit
  • Changes to default values
    • prop:value -> modelValue;
    • 事件:input -> update:modelValue;
  • Note: The .sync modifier of v-bind and the model option of the component have been removed (because in order to implement update:modelValue value update, the previous .sync writing is temporarily used)
  • Note 2: Added support for multiple v-models
  • Note 3: Added support for custom modifiers

V-mode implements communication between parent and child components

Parent component 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>

Child component 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>
  • Effect
    • In the parent component, when you click to modify the flag, you can control the display and hiding of the dialog component
    • When you click close in the subcomponent dialog, you can modify the value of the flag of the parent component

v-model uses multiple

main.view

<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.view

<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>

  • Effect
    insert image description here

v-model custom modifier

  • Custom modifiers for v-model
  • You can also add custom modifiers to another v-model:title

Custom modifiers for v-model

main.view

<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.view

<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>

  • Effect
    insert image description here

Guess you like

Origin blog.csdn.net/weixin_43845137/article/details/123534181