Vue 3 组合式 API 中 provide/inject 传递 ref 的核心陷阱 在 Vue 3 组合式 API 里,用 provide 传递 ref 对象时,最容易踩的坑之一就是:子组件通过 inject 拿到的到底是 ref 本身,还是它背后那个 .value。 关键判断:provide
在 Vue 3 组合式 API 里,用 provide 传递 ref 对象时,最容易踩的坑之一就是:子组件通过 inject 拿到的到底是 ref 本身,还是它背后那个 .value。
你可能已经知道,provide 传 ref 是正确的做法,例如:
长期稳定更新的攒劲资源: >>>点此立即查看<<<
const selectedReceipt = ref([]);
provide('selectedReceipt', selectedReceipt);
到这里没问题,你给出去的确实是一个 Ref 实例。但到了子组件那边,很多人会下意识地想:在模板里是不是应该手动写 .value?其实不是。
子组件注入得到的 selectedReceipt 本身就是一个 Ref 类型的对象——它包含了 .value 属性,但在模板里反而不能直接用 .value。
为什么?因为 Vue 3 的模板语法对 Ref 类型有自动解包机制。简单说,当你写 selectedReceipt.id 的时候,Vue 模板会自动帮你读取 selectedReceipt.value.id。如果你非要写成 selectedReceipt.value.id,不仅冗余,而且会在首次渲染时因为响应式依赖没被正确触发而报 undefined——这个错误非常隐蔽,抓狂是常有的事。
来看正确的写法:
而下面这种写法,就是典型的“踩坑”姿势:
这里尤其要敲黑板:逻辑代码和模板,是两个截然不同的世界。
selectedReceipt.id 就够,Vue 会帮你自动解包,但仅限于顶层属性的访问。比如 selectedReceipt.hospitals.en_name 仍然正确,因为模板解包只作用于 selectedReceipt 这个顶层 Ref,后续的链式访问是你自己的逻辑。setup()、watch、computed 中):你必须显式写 .value。因为这里没有模板的自动解包,你需要手动告诉 Vue:“我要读这个 ref 的当前值”。还有一点很容易忽略:watch 监听的对象应该是 .value,而不是 ref 本身。
你现在写的 watch(() => selectedReceipt, ...) 实际上监听的是 selectedReceipt 这个引用是否变成了另一个对象——这几乎不会发生。你要监听的是它的 值 变化:
watch(() => selectedReceipt.value, (newVal) => {
if (newVal && newVal.length > 0) {
const receipt = newVal[0];
master_Filter.value.hospital_id = receipt.hospitals.en_name;
master_Filter.value.assessment_date = receipt.assessment_date;
master_Filter.value.maktoob_no = receipt.maktoob_no;
master_Filter.value.maktoob_date = receipt.maktoob_date;
getDetails();
}
}, { immediate: true, deep: true });
这里还有个小细节:selectedReceipt 初始值是 ref([]),所以首次注入时,selectedReceipt.value 是空数组。访问 selectedReceipt.value.id 肯定是个 undefined。所以 防御性检查 不能省——在模板里用可选链 .id,在 watch 里加判空逻辑,都是好习惯。
provide 传的是 ref,inject 接收到的也是 ref。injectedRef.prop,Vue 会自动解包。injectedRef.value。watch 监听 () => injectedRef.value,配合 immediate: true 保证初始值触发。selectedReceipt.value[0]),始终做存在性校验。这套规则吃透了,selectedReceipt 在模板里报 undefined、链接跳转失败的问题就能彻底解决,响应式更新也会稳稳当当。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述