Vue3 Options API中inject获取值为undefined的原因及解决方法
问题原因
- provide执行时机太晚:你把
provide('isToggled')放在了按钮点击的onDigitizePolygon方法里,只有用户点击按钮时才会执行provide操作。但注入者组件在mounted阶段就尝试获取注入值,此时provide还没执行,自然拿到undefined。 - Options API中provide的错误用法:在Options API里,
provide应该在组件初始化阶段(比如created钩子)执行,或者通过组件的provide选项声明,而不是在触发式的方法中调用——因为注入是组件初始化时就会完成的操作,晚于注入时机的provide无法被感知。
解决方案
下面提供两种符合Options API规范的解决方式:
方式一:使用组件的provide选项声明要提供的值
将响应式对象通过provide选项暴露,组件初始化时就完成提供,注入者组件可以直接拿到值,后续修改响应式对象的value时,注入者会自动感知变化。
修改后的提供者组件:
<template> <button id="idBtnDigitizePolygon" class="clsBtnDigitizePolygon" @click="onDigitizePolygon()" :disabled="isBtnDigitizePolygonDisabled"> test </button> </template> <script> import { ref } from 'vue'; export default { data() { return { // 将响应式对象放到data中,方便方法里修改 isToggleBtnLabelDigitizePolygon: ref(true) }; }, props: { isBtnDigitizePolygonDisabled: { type: Boolean, default: false, }, }, // 通过provide选项提供响应式对象 provide() { return { isToggled: this.isToggleBtnLabelDigitizePolygon }; }, methods: { onDigitizePolygon() { // 直接修改响应式对象的value即可,无需再次调用provide this.isToggleBtnLabelDigitizePolygon.value = !this.isToggleBtnLabelDigitizePolygon.value; }, }, }; </script>
方式二:在created钩子中调用provide
如果更习惯用组合式API的provide函数,可以在组件的created钩子中执行provide,确保注入者初始化时能拿到值:
修改后的提供者组件:
<template> <button id="idBtnDigitizePolygon" class="clsBtnDigitizePolygon" @click="onDigitizePolygon()" :disabled="isBtnDigitizePolygonDisabled"> test </button> </template> <script> import { provide, ref } from 'vue'; export default { data() { return { isToggleBtnLabelDigitizePolygon: ref(true) }; }, props: { isBtnDigitizePolygonDisabled: { type: Boolean, default: false, }, }, created() { // 组件初始化时执行provide,注入者能及时获取 provide('isToggled', this.isToggleBtnLabelDigitizePolygon); }, methods: { onDigitizePolygon() { this.isToggleBtnLabelDigitizePolygon.value = !this.isToggleBtnLabelDigitizePolygon.value; }, }, }; </script>
注入者组件的优化
建议使用Options API的inject选项来声明要注入的值,这样可以直接通过this访问,也能设置默认值避免undefined:
<script> import { inject } from 'vue' export default { name: 'HelloWorld', props: { msg: String }, // 用inject选项声明要注入的key inject: ['isToggled'], mounted() { console.log('injected', this.isToggled); // 现在能拿到响应式ref对象 // 监听状态变化 this.$watch('isToggled.value', (newState) => { console.log('按钮切换状态:', newState); }); } } </script>
内容的提问来源于stack exchange,提问作者Amrmsmb
相关产品推荐
相关产品推荐

