最近看到vue版本更新到3.4.x了,其中有个defineModel API,defineModel在3.3的时候是作为实验特性发布的,在3.4中逐渐稳定。这个API就是Vue3简化组件v-model的写法的,所以这篇就一块儿来总结一下vue中的组件v-model
官网的示例
先说下vue2中的使用,再说下vue3中的使用
V2
单个v-model绑定
下面这个单个v-model中,默认是向子组件传递的value属性,子组件接受value获取到父组件的值,通过$emit发送input事件更新该值。也可以通过配置model修改接受的字段名称和事件名称,具体看如下代码
父组件示例:
<template><div class="mytest"><div>父组件的name:{{ name }}</div><Child v-model="name" /></div>
</template>
<script>
import Child from './child.vue'
export default {data() {return {name: 'WFT'}},components: { Child }
}
</script>
子组件示例:
<template><div class="child"><div>我是子组件</div><el-input v-model="name" placeholder="请输入内容"></el-input></div>
</template>
<script>
export default {model: {prop: 'value', // 默认就是valueevent: 'input' // 默认就是input},props: {value: {type: String,default: ''}},computed: {name: {get() {return this.value},set(val) {this.$emit('input', val)}}}
}
</script>
多个v-model绑定
多个v-model绑定,通过.sync传递,子组件可以通过传递的对应名称接受、通过$emit发送update:名称的事件方式更新对应的父组件中的值
父组件示例:
<template><div class="mytest"><div>父组件的name:{{ name }}</div><div>父组件的age:{{ age }}</div><Child :name.sync="name" :age.sync="age" /></div>
</template>
<script>
import Child from './child.vue'
export default {data() {return {name: 'WFT',age: 18}},components: { Child }
}
</script>
子组件示例:
<template><div class="child"><div>我是子组件</div><el-input v-model="propName" placeholder="请输入内容"></el-input><el-input v-model.number="propAge" placeholder="请输入内容"></el-input></div>
</template>
<script>
export default {props: {name: {type: String,default: ''},age: {type: Number,default: 0}},computed: {propName: {get() {return this.name},set(val) {this.$emit('update:name', val)}},propAge: {get() {return this.age},set(val) {this.$emit('update:age', val)}}}
}
</script>
V3
Vue3中介绍单个v-model绑定和多个v-model绑定中的传统方式和defineModel方式
defineModel是一个新的<script setup>宏,旨在简化支持v-model的组件的实现。它以前在3.3.x中作为实验特性发布,并在3.4.x中逐渐稳定。它现在为使用v-model修饰符提供了更好的支持。无需引入,直接使用即可,同defineProps、defineEmits
单个v-model绑定
传统方式
父组件示例:
<template><div class="wft-projects"><div>父组件的name:{{ name }}</div><Child v-model="name" /></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './child.vue'const name = ref('WFT')</script>
子组件示例:
<template><div class="child"><h3>我是子组件</h3><el-input v-model="propName"></el-input></div>
</template>
<script setup lang='ts'>
import { computed } from 'vue'const props = withDefaults(defineProps<{modelValue?: string
}>(), {modelValue: '哈哈'
})const emits = defineEmits<{(e: 'update:modelValue', params: string): void
}>()const propName = computed({get() {return props.modelValue},set(val) {emits('update:modelValue', val)}
})
</script>
defineModel
父组件示例:
同传统方式
<template><div class="wft-projects"><div>父组件的name:{{ name }}</div><Child v-model="name" /></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './child.vue'const name = ref('WFT')</script>
子组件示例:
<template><div class="child"><h3>我是子组件</h3><el-input v-model="propName"></el-input></div>
</template>
<script setup lang='ts'>const propName = defineModel<string>('modelValue', { default: 'default value' })</script>
使用defineModel真的是简化了太多代码,使用很方便
多个v-model绑定
传统方式
父组件示例:
<template><div class="wft-projects"><div>父组件的name:{{ name }}</div><div>父组件的age:{{ age }}</div><Child v-model:name="name" v-model:age="age" /></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './child.vue'const name = ref('WFT')
const age = ref(18)</script>
子组件示例:
<template><div class="child"><h3>我是子组件</h3><el-input v-model="propName"></el-input><el-input v-model.number="propAge"></el-input></div>
</template>
<script setup lang='ts'>
import { computed } from 'vue'const props = withDefaults(defineProps<{name?:string,age?: number
}>(), {name: 'default name',age: 0
})const emits = defineEmits<{(e: 'update:name', params: string): void(e: 'update:age', params: number): void
}>()const propName = computed({get() {return props.name},set(val) {emits('update:name', val)}
})
const propAge = computed({get() {return props.age},set(val) {emits('update:age', val)}
})</script>
defineModel
父组件示例:
同传统方式
<template><div class="wft-projects"><div>父组件的name:{{ name }}</div><div>父组件的age:{{ age }}</div><Child v-model:name="name" v-model:age="age" /></div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child from './child.vue'const name = ref('WFT')
const age = ref(18)</script>
子组件示例:
<template><div class="child"><h3>我组件</h3><el-input v-model="propName"></el-input><el-input v-model.number="propAge"></el-input></div>
</template>
<script setup lang='ts'>const propName = defineModel<string>('name', { default: 'default name' })
const propAge = defineModel<number>('age', { default: 0 })</script>