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

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

相关推荐
OpenTiny社区4 分钟前
TinyVue v3.31 更新速览:新组增件 + 文档优化,多项实用能力升级
vue.js
用户62960593247058 分钟前
一次位置调整引发的画布失忆:深入 Vue2 虚拟 DOM 复用机制
前端·vue.js
Sterting10 分钟前
条件渲染与列表渲染
前端·vue.js
木公子30 分钟前
Vue3源码精读03:响应式核心依赖追踪机制|track与trigger底层源码全解析
前端·vue.js
看到我请叫我铁锤1 小时前
vue编写web端在线预览文档
前端·javascript·vue.js
90后的晨仔13 小时前
Mac 开发 uni-app 终极方案:让安卓模拟器彻底脱离 Android Studio 独立运行
前端·vue.js
C++、Java和Python的菜鸟18 小时前
第12章 前端Web进阶(Vue工程化+ElementPlus)
前端·javascript·vue.js
妙码生花19 小时前
让各大 AI 整理出来的前端工程命名最简实践(Vue + TS)
前端·javascript·vue.js
用户8417948145621 小时前
vxe-table 实现编辑列的权限控制:列级与表级权限管理
vue.js
Tian_Hang21 小时前
Vue3 父子组件通讯
前端·javascript·vue.js