文章目录
前言
今天写个小例子,实战DefineModel的使用方法细节
一、实战DefineModel
上文官方说的挺清楚,实战验证一下,新建DefineModel.vue(这是儿子):
javascript
<template>
<div>
<div>parent bound v-model is: {{ model }}</div>
<v-btn @click="update" color="light-green">点我更新儿子</v-btn>
</div>
</template>
<script setup lang="ts" name="">
const model:any = defineModel()
function update() {
model.value++
}
</script>
<style lang='scss' scoped>
</style>
再更改一下之前的about.vue测试(这是父亲):
javascript
<template>
<div>
<h3>About</h3>
<h3>姓名:{{userStore.name}}</h3>
<h3>简介:{{profile}}</h3>
<h3>年龄:{{age}}</h3>
<DefineModel v-model="age" />
<v-btn @click="update" color="red" class="mt-3">点我更新父亲</v-btn>
</div>
</template>
<script setup lang='ts' name="About">
function update(){
age.value++
}
const age = ref(1);
import DefineModel from './study/defineModel.vue';
import { ref } from 'vue';
</script>
<style lang='less' scoped>
</style>
运行:
点击父和子组件的按钮更新值age都会变化:
二、思考原理
为什么
const model = defineModel()
就绑定到了父的v-model了呢,因为defineModel 是一个便利宏。编译器将其展开为以下内容:
一个名为 modelValue 的 prop,本地 ref 的值与其同步;
一个名为 update:modelValue 的事件,当本地 ref 的值发生变更时触发。
在 3.4 版本之前,你一般会按照如下的方式来实现上述相同的子组件:
javascript
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
这也是刚刚断点时候这个属性的解释:
但是注意我们子组件属性的名字是随意的,例如:
const childage:any = defineModel()
那么:
javascript
<template>
<div>
<h3>parent bound v-model is: {{ childage }}</h3>
<v-btn @click="update" color="light-green">点我更新儿子</v-btn>
</div>
</template>
<script setup lang="ts" name="">
const childage:any = defineModel()
function update() {
childage.value++
}
</script>
<style lang='scss' scoped>
</style>
运行:
是不影响功能的。我开始对这里理解有点误解,备忘。
如果不想用默认的modelValue,也可以传递一个有意义的名字:
父:
javascript
<DefineModel v-model:childage="age" />
儿砸:
javascript
const childage:any = defineModel('childage')
总结
这样一来,通过 defineModel,子组件无需显式声明 props 和 emits,就能实现与父组件之间的自动双向绑定。
草长莺飞二月天,拂堤杨柳醉春烟 儿童散学归来早,忙趁东风放纸鸢