详解Vue3的setup语法中defineExpose

我们知道defineExpose是Vue3的setup语法下提供的api,setup语法下组件数据对外是默认关闭的,必须要通过该api暴露后父组件才能调用,那么如果子组件暴露的变量父组件可以通过修改该变量进而改变子组件的变量吗?做了一些测试下面说明。

案例一:

父组件

子组件loginPanel

输出结果为:

可以看到导出的变量a被修改成122,输出loginPanel.value.a也变成122了, 但是b函数确输出了1, 这说明子组件内a变量并没有真正被修改

案例二:

父组件不变,依旧和上一案例一致

子组件的 a = 1 变为 a = ref(1)

输出结果为:

可以看到a被改成122后b函数输出的是RefImpl对象, 当中的值也被改成122了,也就是说 子组件的 a 变量被真正的修改了

为什么两者不一致?

前面说到使用了 setup 后组件数据对外关闭,需要使用 defineExpose 暴露,该 api 暴露的并不是子组件真正实例本身,从输出就可以看到,其暴露的变量和函数都是使用一个新的对象包裹并且通过 Proxy 代理的新对象,输出 loginPanel.value 它是这样的

案例一所以直接通过 loginPanel.value!.a 修改的导出来的被Proxy封装的新对象的 a, 子组件 a 并没有被真正更改;

案例二类推, 直接通过 loginPanel.value!.a 修改的是 a 的 RefImpl对象的value, ref底层使用的Reflect.defineProperty, 该 RefImpl 对象正是子组件 a 变量引用的对象, 故子组件 a 变量的值即 a.value被真正修改。 既然 a 是ref对象,为什么不是 loginPanel.value!.a.value = 122 这样呢, 不用 .value就能直接改? 这就是这里神奇的地方,在setup语法使用defineExpose父组件中使用子组件暴露的ref数据是会自动解包的,不需要 .value, 赋值也不用,因为在修改通过父组件 loginPanel.value!.a = 122 修改的时候,由于loginPanel.value 是Proxy实例,内部做了监听。

最后:这只是个人学习测试好奇,开发中最好不要在父组件中直接修改子组件的数据,并且官方也不推荐这么做,至少要通过暴露的函数形式来修改子组件数据,否则容易造成混乱难以维护,被改了也不知道不能够进行规范约束,要改也要弄个暴露函数内部做监控。

相关推荐
麦麦大数据8 小时前
F032 材料科学文献知识图谱可视化分析系统(四种知识图谱可视化布局) | vue + flask + echarts + d3.js 实现
vue.js·flask·知识图谱·数据可视化·论文文献·1024程序员节·科研图谱
web打印社区9 小时前
使用React如何静默打印页面:完整的前端打印解决方案
前端·javascript·vue.js·react.js·pdf·1024程序员节
小光学长9 小时前
基于Vue的课程达成度分析系统t84pzgwk(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
麦麦大数据11 小时前
F033 vue+neo4j图书智能问答+知识图谱推荐系统 |知识图谱+neo4j+vue+flask+mysql实现代码
vue.js·flask·nlp·neo4j·智能问答·图书·1024程序员节
橙子1991101611 小时前
在 Kotlin 中,ViewModel 的获取
开发语言·vue.js·kotlin
疯狂的沙粒13 小时前
前端开发【工具函数】基于dayjs 封装的DateUtils工具函数,可以直接拿着使用
前端·javascript·vue.js·1024程序员节
海鸥两三16 小时前
Uni-App(Vue3 + TypeScript)项目结构详解 ------ 以 Lighting-UniApp 为例,提供源代码
vue.js·typescript·uni-app·1024程序员节
知识分享小能手16 小时前
uni-app 入门学习教程,从入门到精通,uni-app中uCharts组件学习((8)
vue.js·学习·ui·微信小程序·小程序·uni-app·echarts
布兰妮甜16 小时前
彻底清理:Vue项目中移除static文件夹的完整指南
vue.js·前端框架·static·1024程序员节