vue3第二十节(新增编译宏defineModel)

devtools/2024/10/18 16:52:55/

为什么会需要使用defineModel()

注意:defineModel() 需要在3.4及以上版本才可使用;

组件之间通讯,通过 props 和 emits 进行通讯,是单向数据流,比如:props是自上而下的(父组件数据修改导致子组件更新,而自己不能修改父组件传入的 props属性),而emits是自下而上的(子组件通过事件触发父组件事件);

defineModel() 返回的值是一个 ref
它可以像其他 ref 一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用:
defineModel() 实现原理defineModel() 的双向绑定是在编译之后,创建了一个modelref变量以及一个modelValue的props,并且watchprops中的modelValue;当子组件中的modelValue更新时,会触发update:modelValue事件,当父组件接收到这个事件时候,同时更新父组件的变量;
它的 .value 和父组件的 v-model 的值同步;
当它被子组件变更了,会触发父组件绑定的值一起更新

1、defineModel() 的双向绑定:

父组件:

<template><div class="my-define-module">This is a defineModel text page.// 使用v-model 绑定person对象<ChildMy v-model="person"/><hr>{{ person.name  }}---{{ person.age }}</div></template><script setup>import ChildMy from './child.vue'import { ref } from 'vue' const person = ref({name: 'Andy',age: 11})</script>

子组件

<template>
<div class="my-define-module">child -- {{person.name}} // 第一次打印的是父组件传递过来的 Andy<el-button type="primary" @click="updatedName">child btn</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// defineModel() 返回的是一个ref对象
const person = defineModel({name: 'child',age: 18
})
console.log('==person==child=', person.value)
const updatedName = () => {// 子组中更新person 属性,会同时更新父组件的person属性person.value.name = `${person.value.name}+$`person.value.age = person.value.age + 1
}
</script>

2、defineModel() 创建多个v-model

注意:需要都是基本类型,不能是引用类型,否子组件读到的是undefined
如图:
父组件:

<template><div class="my-define-module">This is a defineModel text page.<!-- <ChildMy  v-model="person"/> -->// 传入多个v-model时的person是Object,导致子组件中person无法通过defineModel获取<ChildMy v-model:person="person" v-model:job="job" v-model:num="num"/><hr>{{ person.name  }}---{{ person.age }} </div></template><script setup>import ChildMy from './child.vue'import { ref } from 'vue' const person = ref({name: 'Andy',age: 11})// 初始化定义时,当父组件没有传入默认值时候,子组件中的job值不父组件的值不同步,子组件展示的是子组件初始化的值--前端const job = ref()const num = ref(3)</script>

子组件:

  <template>
<div class="my-define-module">child -- {{person.name}}<hr>--job--{{ job }}<hr>num---{{num}}<el-button type="primary" @click="updatedName">child btn</el-button><el-button type="primary" @click="updatedJob">child job</el-button><el-button type="primary" @click="updatednum">child num</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// defineModel() 返回的是一个ref对象
const person = defineModel({name: 'child',age: 18,
})
const num = defineModel('num', 2)
const job = defineModel('job', '前端')
console.log('--job---', job) // value => 前端
console.log('--num---', num) // value => 3
console.log('==person==child=', person) // value => undefined
</script>

如图:
请添加图片描述

3、defineModel() 设置额外参数如类型、默认值

const job = defineModel('job', {default: '', type: String, required: true})
编译后的 
props:{job:{default: '',type: String,required: true}
}

4、defineModel() 添加自定义修饰符:

需要使用数组解构方法获取 model 和 modifiersmodel即为ref对象,modifiers即为修饰符对象
如:
父组件:

<template><div class="my-define-module">This is a defineModel text page.<ChildMy  v-model.upLow="job"/><hr>parents--s{{ job }} // 初始化 5</div></template><script setup>import ChildMy from './child.vue'import { ref } from 'vue' const job = ref(5)</script>

子组件:

<template>
<div class="my-define-module"><hr>--job--{{ model }}<hr><el-button type="primary" @click="updatedJob">child job</el-button>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const [model, modifiers] = defineModel({get(value) {console.log('-get-job---', value)return value},set(value) {if (modifiers.upLow) { // 有upLow修饰符的v-model 会将值累加 22return value + 22 }return value}
})
console.log('--job-model--', model)
console.log('--job-modifiers--', modifiers)
const updatedJob = () => {model.value = model.value + 10 // 更新model.value的值
}
</script>

http://www.ppmy.cn/devtools/6637.html

相关文章

网络协议——IS-IS协议详解

1. IS-IS是什么 IS-IS是一种基于链路状态并使用最短路径优先算法进行路由计算的一种IGP协议。IS-IS属于内部网关协议&#xff0c;用于自治系统内部。IS-IS是一种链路状态协议&#xff0c;使用最短路径优先算法进行路由计算。 2. 应用场景&#xff08;园区网和骨干网&#xff0…

OSPF的P2P和Broadcast

OSPF为什么会有P2P和BROADCAST两种类型 OSPF&#xff08;开放最短路径优先&#xff09;协议中存在P2P&#xff08;点对点&#xff09;和BROADCAST&#xff08;广播多路访问&#xff09;两种网络类型&#xff0c;主要是为了适应不同类型的网络环境和需求。具体分析如下&#xf…

【Python_PySide6学习笔记(三十六)】基于QGroupBox和QScrollArea实现带有滚动条的QGroupBox(分组框)

基于QGroupBox和QScrollArea实现带有滚动条的QGroupBox分组框 基于QGroupBox和QScrollArea实现带有滚动条的QGroupBox(分组框)前言正文1、创建QGroupBox并创建其内部布局2、创建QScrollArea并将QGroupBox设置为其内容3、将QScrollArea添加到主窗口的中心部件的布局中4、完整代码…

37、Tomato(VulnHub)

Tomato 一、nmap 2211是ssh的端口&#xff0c;21的ftp也不是弱密码 二、web渗透 随便看看 目录爆破 /seclists/Discovery/Web-Content/common.txt /antibot_image/antibots/readme.txt 发现该站点存在反爬机制 /antibot_image/antibots/info.php 提示我们该网页存在个参数 GET&…

k8s调度场景

15个KUBERNETES调度情景实用指南 Kubernetes调度是确保集群中的Pod在适当节点上运行的关键组件。通过灵活配置调度策略&#xff0c;可以提高资源利用率、负载平衡和高可用性。 在本文中&#xff0c;我们将深入探讨一些实际的Kubernetes调度场景&#xff0c;并提供相应的配置示…

D3-八数码

D3-八数码 题目描述解题思路代码如下 题目描述 解题思路 本题若直接在3*3网格中思考较为困难&#xff0c;可以转换为一维的字符串&#xff0c;在一维字符串中考虑较为简单&#xff0c;要注意本题中两个字符交换位置时只能是x和另外字符交换&#xff0c;本题另外一个难点在于如何…

图论学习总结

目录 图论学习总结前言一、基础知识图的存储图的遍历 二、最短路多源最短路 F l o y d Floyd Floyd​ 算法例题及变形 e g 1 &#xff1a; S o r t i n g I t A l l O u t eg1&#xff1a;Sorting\ It\ All\ Out eg1&#xff1a;Sorting It All Out ( 蓝书例题&#xff0c;传递…

C语言入门算法——选数

题目描述&#xff1a; 已知 n 个整数 x1​,x2​,⋯,xn​&#xff0c;以及 1 个整数 k&#xff08;k<n&#xff09;。从 n 个整数中任选 k 个整数相加&#xff0c;可分别得到一系列的和。例如当 n4&#xff0c;k3&#xff0c;4个整数分别为3,7,12,19 时&#xff0c;可得全部…