详解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实例,内部做了监听。

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

相关推荐
qwfy14 小时前
我要用 AI-native 架构,从零重建一套制造业 ERP/MES
vue.js·spring boot·架构
dsyyyyy110115 小时前
Vue 3 Watch 监视完全指南
前端·javascript·vue.js
瞬时出道15 小时前
AI 回答为什么能一个字一个字蹦出来?前端搞懂 SSE 这一篇就够了
vue.js
u01110267517 小时前
Vue 3 实现图片裁剪框:拖动、缩放与固定宽高比
前端·javascript·vue.js
小小善后师17 小时前
用 Canvas + AI 实现登录页的 Logo 粒子动画
前端·vue.js
web打印社区19 小时前
远程打印:WebSocket 与 HTTP 轮询怎么选
前端·vue.js·websocket·网络协议·http·electron·pdf
朱 欢 庆21 小时前
el-table-v2 虚拟表格组件
前端·javascript·vue.js
今年下半年1 天前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
今年下半年2 天前
【前端】ant-design-vue 表格「行、列都动态」的处理方案
前端·javascript·vue.js
志尊宝2 天前
Vue3 零基础每日笔记(054):Pinia 三件套详解——state / getters / actions 全搞懂
前端·javascript·vue.js·vue·前端开发