vue3下的v-model和vue2的区别:
//子组件:TimeOutModel.vue
<script setup lang="ts">
import {computed} from "vue";
interface Props {
modelValue: boolean;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "update:model-value", show: boolean): void;//真正的 emit 方法在这里, show 只是参数名称,可以自定义为自己想要的
}>();
const isModalVisible = computed({
get: () => props.modelValue,
//当前组件的值发生变化的时候,通过emit通知父组件,实现双向绑定,这一步可以对value 做一定的处理,比如:set: (value) => emit("update:title-info", value.charAt(0).toUpperCase() + value.slice(1)),
//注意,我开始以为需要可以在父组件里定义 @update:model-value="otherFun()",然后在otherFun()里获取这个 value,后来发现不行,感觉前面这个写法相当于是内置的,就只用于v-model的双向绑定,@update:model-value
//不需要在父组件里写,可以参考最下面的链接
set: (value) => emit("update:model-value", value),
});
</script>
<template>
<QModal v-model="isModalVisible" :hideCloseIcon="true" :persistent="true">
<template #header>
<div class="infoHear">
<img src="~/assets/img/notice.svg" class="notice-img"/>
<h3>Time is up!</h3>
</div>
</template>
<template #body>
<p class="body-info">Do you want to submit or discard changes</p>
</template>
<template #footer>
<div class="flex gap-2">
<QButton size="sm" class="flex-1" variant="secondary" @click="close">Discard</QButton>
<QButton size="sm" class="flex-1" variant="primary" @click="submit">Submit</QButton>
</div>
</template>
</QModal>
</template>
<script lang="ts">
export default {
name: "DsModal",
methods: {
close(){
this.$emit('close') //还是可以在这里定义对外的emit方法
},
submit(){
this.$emit('submit')
}
}
}
</script>
<style scoped lang="postcss">
.infoHear{
display: flex;
flex-direction: column;
align-items: center;
.notice-img{
display: block;
width: 3.3125rem;
height: 3.625rem;
}
}
.body-info{
display: flex;
justify-content: center;
padding: 1.25rem 0.625rem;
}
</style>
上面的vue组件,要求 script setup 中的 lang 和 script 中的 lang 要定义相同
参考:https://v3-migration.vuejs.org/breaking-changes/v-model.html
//经过改造以后,实现子组件修改数据,触发set方法 ,主要是通过 @click="tt" 修改字符串的内容,这样就验证了,这个set 方法中的emit的作用,实现双向绑定
<script setup lang="ts">
import {computed} from "vue";
interface Props {
modelValue: boolean,
titleInfo: string
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: "update:model-value", show: boolean): void;
(e: "update:title-info", str: string): void;
}>();
const isModalVisible = computed({
get: () => props.modelValue,
set: (value) => emit("update:model-value", value),
});
const titleStr = computed({
get: () => props.titleInfo,
set: (value) => emit("update:title-info", value.charAt(0).toUpperCase() + value.slice(1)),
})
const tt = () => {
titleStr.value = "good bye" + (new Date())
}
</script>
<template>
<QModal v-model="isModalVisible" :hideCloseIcon="true" :persistent="true">
<template #header>
<div class="infoHear">
<img src="~/assets/img/notice.svg" class="notice-img"/>
<h3 @click="tt">{{titleStr}}</h3>
</div>
</template>
<template #body>
<p class="body-info">Do you want to submit or discard changes</p>
</template>
<template #footer>
<div class="flex gap-2">
<QButton size="sm" class="flex-1" variant="secondary" @click="close">Discard</QButton>
<QButton size="sm" class="flex-1" variant="primary" @click="submit">Submit</QButton>
</div>
</template>
</QModal>
</template>
<script lang="ts">
export default {
name: "DsModal",
methods: {
close(){
this.$emit('close')
},
submit(){
this.$emit('submit')
}
}
}
</script>
<style scoped lang="postcss">
.infoHear{
display: flex;
flex-direction: column;
align-items: center;
.notice-img{
display: block;
width: 3.3125rem;
height: 3.625rem;
}
}
.body-info{
display: flex;
justify-content: center;
padding: 1.25rem 0.625rem;
}
</style>
//vue3下v-model 自定义数据预处理,有时候我们需要在用户输入内容的的时候,对输入的数据做预处理,比如 去掉空格,转大写等
参考:https://vuejs.org/guide/components/v-model.html#handling-v-model-modifiers //我自己测试失败了
