目录
一、背景
最新也是在学习vue,看到公司前端大佬写的代码,父组件调用子组件prop和emits时,发现有好多种写法,了解了一下发现是不同版本的写法差异,花了半天时间学习一下,特此记录一下。
二、前提
使用defineModel、defineProps、defineEmits此类的宏函数,需要在vue3环境下配合组合式API中使用。其中宏函数是内置的函数,可以直接使用而无需引用。
三、旧用法(vue 3.4之前)
此前我一直使用的如下的方法,将参数和暴露的方法通过props和emits传递给子组件,子组件修改值后,调用父组件的emits事件方法。最终在父组件里完成修改,也符合数据单项流通原则。
// Parent.vue
<template>
<p style="text-align: center;">{{ title }}</p>
<p style="text-align: center;">{{ content }}</p>
<Child :title="title" @updateTitle="updateTitle"
:content="content" @updateContent="updateContent"
/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './components/text.vue';
const title = ref('我是标题')
const content = ref('我是内容')
// title被修改时,回调的函数
function updateTitle(newValue){
title.value = newValue
}
// content被修改时回调
function updateContent(newValue){
content.value= newValue
}
</script>
// Child.vue
<template>
<div>
<span>Title:</span>
<el-input v-model="title" @input="changeTitle"></el-input>
<span>Content:</span>
<el-input v-model="content" @input="changeContent"></el-input>
</div>
</template>
<script setup>
import { toRef, ref } from 'vue'
const props = defineProps(['title', 'content'])
const emits = defineEmits(['updateTitle', 'updateContent'])
const title = ref(props.title)
const content = ref(props.content)
// value是v-model绑定自动传递过来的
function changeTitle(value){
emits('updateTitle', value)
}
function changeContent(value){
emits('updateContent', value)
}
</script>
四、defineModel新用法(3.4及以后)
新方法通过使用defineModel宏函数自动接收并处理来自调用方传入的props、emits参数和事件。
// Parent.vue
<template>
<p style="text-align: center;">{{ title }}</p>
<p style="text-align: center;">{{ content }}</p>
<Child v-model:title="title"
v-model:content="content"
/>
</template>
<script setup>
import { ref } from 'vue'
import Child from './components/text.vue';
const title = ref('我是标题')
const content = ref('我是内容')
</script>
// Child.vue
<template>
<div>
<span>Title:</span>
<el-input v-model="titleModel"></el-input>
<span>Content:</span>
<el-input v-model="contentModel"></el-input>
</div>
</template>
<script setup>
// // 如果只有一个参数时,可以不指定参数名
// const model = defineModel()
// 多个参数时,指定参数名。返回的是一个ref对象
const titleModel = defineModel('title')
const contentModel = defineModel('content')
</script>
五、总结
可以看到使用defineModel前后可以省略很大一部分代码,v-model绑定的defineModel可以自动处理update:xxx方法的修改。
引用AI的回答:
v-model:xxx="data" 等价于
:xxx="data"
@update:xxx="data = $event"
此方法提高了开发效率,并使代码看起来更简洁。但对我这种新手,刚开始会感觉看不懂,莫名其妙的感觉,慢慢了解前因后果后才会懂。