前言
今天重新翻看了vuejs文档,看到v-model的有关使用,想到vue2和vue3中有些不同,今天在这里整理下两个的使用。首先看到v-model,大多数小伙伴都会想到“响应式”、“双向绑定”,v-model 确实是实现了双向绑定数据,用过vue的人都比较熟悉。v-model 是 Vue 内置的指令,vue2和vue3中的v-model使用有点不太一样,那具体是哪里不一样呢?
在Vue2中v-model的使用
1.在组件上使用 v-model 相当于prop中添加 value属性 并触发 input 事件:
父组件
<template>
<div>
<div>父组件中的---------{{count}}</div>
<ChildTpl v-model="count" />
<!-- 等价于 -->
<ChildTpl :value="count" @input="value = $event" />
</div>
</template>
<script>
import ChildTpl from '@/components/ChildTpl.vue';
export default {
components:{
ChildTpl
},
data() {
return {
count:0,
};
}
};
</script>
子组件
<template>
<div>
<span>{{value}}</span>
<button @click="changeValue">count+1</button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
props:{
value:{
default:0,
}
},
methods: {
changeValue(){
this.$emit('input', this.value+1)
}
}
}
</script>
2.如果想要更改 prop属性或事件名称,则需要在 ChildTpl 组件中添加 model 选项:
父组件
<template>
<div>
<div>父组件中的---------{{ count }}</div>
<ChildTpl v-model="count" />
<!-- 等价于 -->
<ChildTpl :customParams="count" @change="count = $event" />
</div>
</template>
<script>
import ChildTpl from "@/components/ChildTpl.vue";
export default {
components: {
ChildTpl,
},
data() {
return {
count: 0,
};
},
};
</script>
子组件
<template>
<div>
<span>{{ customParams }}</span>
<button @click="changeValue">count+1</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
model: {
prop: "customParams", // 将默认value属性改为customParams
event: "change", // 将默认input事件改为change
},
props: {
customParams: {
type: Number,
default: 0,
},
},
methods: {
changeValue() {
this.$emit("change", this.customParams + 1);
},
},
};
</script>
3.使用.sync修饰符实现v-model
父组件
<template>
<div>
<div>父组件中的---------{{ count }}</div>
<ChildTpl :num.sync="count" />
<!-- 等价于 -->
<ChildTpl :num="count" @update:num="count = $event" />
</div>
</template>
<script>
import ChildTpl from "@/components/ChildTpl.vue";
export default {
components: {
ChildTpl,
},
data() {
return {
count: 0,
};
},
};
</script>
子组件
<template>
<div>
<span>{{ num }}</span>
<button @click="changeValue">count+1</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
props: {
num: {
type: Number,
default: 0,
},
},
methods: {
changeValue() {
this.$emit("update:num", this.num + 1);
},
},
};
</script>
在Vue3中v-model的使用
vue3的v-model官方使用介绍
1.v-model 相当于在prop添加了modelValue属性 并接收抛出 update:modelValue 事件:
父组件
<template>
<span>父组件中的---------{{ count }}</span>
<ChildTpl v-model="count" />
<!-- 等价于 -->
<ChildTpl :modelValue="count" @update:modelValue="count = $event" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import ChildTpl from "./components/ChildTpl.vue";
const count = ref(0);
</script>
<style scoped>
</style>
子组件
<template>
<div>
<span>{{ modelValue }}</span>
<button @click="changeValue">count+1</button>
</div>
</template>
<script lang="ts" setup>
const emits = defineEmits(["update:modelValue"]);
const props = defineProps({
modelValue: {
type: Number,
default: 0,
},
});
const changeValue = () => {
emits("update:modelValue", props.modelValue + 1);
};
</script>
2.默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:
父组件
<template>
<span>{{ count }}</span>
<ChildTpl v-model:num="count" />
<!-- 等价于 -->
<ChildTpl :num="count" @update:num="count = $event" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import ChildTpl from "./components/ChildTpl.vue";
const count = ref(0);
</script>
<style scoped>
</style>
子组件
<template>
<div>
<span>{{ num }}</span>
<button @click="changeValue">count+1</button>
</div>
</template>
<script lang="ts" setup>
const emits = defineEmits(["update:num"]);
const props = defineProps({
num: {
type: Number,
default: 0,
},
});
const changeValue = () => {
emits("update:num", props.num + 1);
};
</script>
Vue3的v-model多了哪些特性
1.Vue3移除了model选项和sync修饰符实现v-model
2.Vue3支持使用多个v-model
我们可以在单个组件实例上创建多个 v-model 双向绑定
组件上的每一个 v-model 都会同步不同的 prop,而无需额外的选项
父组件
<template>
<div>
<span>父组件-------first:{{ first }},last:{{ last }}</span>
</div>
<ChildTpl v-model:first-name="first" v-model:last-name="last" />
<!-- 等价于 -->
<ChildTpl
:first-name="first"
:last-name="last"
@update:first-name="first = $event"
@update:last-name="last = $event"
/>
</template>
<script setup lang="ts">
import { ref } from "vue";
import ChildTpl from "./components/ChildTpl.vue";
const first = ref("first");
const last = ref("last");
</script>
<style scoped></style>
子组件
<template>
<div>
<input
type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"
/>
<input
type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"
/>
</div>
</template>
<script lang="ts" setup>
const props = defineProps({
firstName: {
type: String,
default: "",
},
lastName: {
type: String,
default: "",
},
});
</script>
3.自定义v-model修饰符
我们知道了 v-model 有一些内置的修饰符,例如 .trim,.number 和 .lazy。在某些场景下,你可能想要一个自定义组件的 v-model 支持自定义的修饰符,以按需处理绑定值。
比如下面自定义capitalize修饰符实现首字母大写
组件的 v-model 上所添加的修饰符,可以通过 modelModifiers prop 在组件内访问到。在下面的组件中,我们声明了 modelModifiers 这个 prop,有了这个 prop,我们就可以检查 modelModifiers 对象的键,并编写一个处理函数来改变抛出的值。
父组件
<template>
<div>
<span>父组件-------myText:{{ myText }}</span>
</div>
<ChildTpl v-model.capitalize="myText" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import ChildTpl from "./components/ChildTpl.vue";
const myText = ref("first");
</script>
<style scoped></style>
子组件
<template>
<div>
<input type="text" :value="modelValue" @input="emitValue" />
</div>
</template>
<script lang="ts" setup>
import { onMounted } from "vue";
const emits = defineEmits(["update:modelValue"]);
const props = defineProps({
modelValue: {
type: String,
default: "",
},
modelModifiers: {
default: () => ({ capitalize: false }),//这里为了满足ts验证默认设为false
},
});
onMounted(() => {
console.log(props.modelModifiers); // { capitalize: true }
});
const emitValue = (e: any) => {
let value = e.target.value;
if (props.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1);
}
emits("update:modelValue", value);
};
</script>
对于又有参数又有修饰符的 v-model 绑定,生成的 prop 名将是 arg + "Modifiers"。
父组件
<template>
<div>
<span>父组件-------myText:{{ myText }}</span>
</div>
<ChildTpl v-model:title.capitalize="myText" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import ChildTpl from "./components/ChildTpl.vue";
const myText = ref("first");
</script>
<style scoped></style>
子组件
<template>
<div>
<input type="text" :value="title" @input="emitValue" />
</div>
</template>
<script lang="ts" setup>
import { onMounted } from "vue";
const emits = defineEmits(["update:title"]);
const props = defineProps({
title: {
type: String,
default: "",
},
titleModifiers: {
type: Object,
default: () => ({}),
},
});
onMounted(() => {
console.log(props.titleModifiers); // { capitalize: true }
});
const emitValue = (e: any) => {
let value = e.target.value;
value = value.charAt(0).toUpperCase() + value.slice(1);
emits("update:title", value);
};
</script>
以上是我看了文档后的总结了,如有不意见,欢迎评论指正。这里也附上我的博客网站。
本文详细对比了Vue2与Vue3中v-model的使用差异,包括基本用法、自定义属性及事件名称、多个v-model绑定等内容,并介绍了Vue3新增的支持自定义修饰符等功能。
2469

被折叠的 条评论
为什么被折叠?



