You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue2 Composition API下如何实现provide/inject响应式?

Vue2 + Composition API:Provide/Inject 响应式失效问题

环境版本

  • Vue.js 2
  • Composition API

问题描述

父组件通过provide提供响应式变量status,并在mounted钩子中定时修改其值;子组件用inject获取该值后,监听injStatus的watch未触发,无法捕获值的变化。

父组件代码

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld></HelloWorld>
</template>
<script>
import {computed} from 'vue'
import {InjectionKeys} from './assets/InjectionKeys.js'
import {HelloWorld} from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data() {
        return {
          status:undefined
        };
      },
    provide() {
        return {
            [InjectionKeys.PROVIDE_KEY_STATUS.description]: computed(() => this.compPropsStatus),
        };
    },
    computed:{
      compPropsStatus() {
        return this.status
      },
    },
    mounted() {
      setTimeout(() => {
          this.status = '1'
        }, 1000);
      
        setTimeout(() => {
          this.status = '2'
        }, 3000);
      
        setTimeout(() => {
          this.status = '3'
        }, 5000);

        setTimeout(() => {
          this.status = '4'
        }, 7000);
    }
}
</script>

子组件代码

<script>
import {InjectionKeys} from '../assets/InjectionKeys.js'

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  inject: {
        injStatus: { from: InjectionKeys.PROVIDE_KEY_STATUS.description },
    },
  watch:{
    injStatus(newVal, oldVal) {
      console.log({msg:' watched injStatus. oldVal:' + oldVal + ', and newVal: ', newVal});
    },
  },
    
}
</script>

解决方案

方案1:改用Composition API的setup注入并监听

在子组件中使用setup函数,通过Composition API的inject和watch方法实现响应式监听:

<script>
import { inject, watch } from 'vue'
import { InjectionKeys } from '../assets/InjectionKeys.js'

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup() {
    const injStatus = inject(InjectionKeys.PROVIDE_KEY_STATUS.description)

    watch(injStatus, (newVal, oldVal) => {
      console.log({msg: ' watched injStatus. oldVal:' + oldVal + ', and newVal: ', newVal})
    })

    return { injStatus }
  }
}
</script>

方案2:提供响应式对象而非单独值

将status包装在响应式对象中提供,利用Vue对对象属性的响应式追踪特性:

父组件修改:

<script>
import { reactive } from 'vue'
import { InjectionKeys } from './assets/InjectionKeys.js'
import { HelloWorld } from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data() {
    return {
      statusObj: reactive({ status: undefined })
    };
  },
  provide() {
    return {
      [InjectionKeys.PROVIDE_KEY_STATUS.description]: this.statusObj
    };
  },
  mounted() {
    setTimeout(() => {
      this.statusObj.status = '1'
    }, 1000);
  
    setTimeout(() => {
      this.statusObj.status = '2'
    }, 3000);
  
    setTimeout(() => {
      this.statusObj.status = '3'
    }, 5000);

    setTimeout(() => {
      this.statusObj.status = '4'
    }, 7000);
  }
}
</script>

子组件修改:

<script>
import { InjectionKeys } from '../assets/InjectionKeys.js'

export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  inject: {
    statusObj: { from: InjectionKeys.PROVIDE_KEY_STATUS.description },
  },
  watch:{
    'statusObj.status'(newVal, oldVal) {
      console.log({msg:' watched status. oldVal:' + oldVal + ', and newVal: ', newVal});
    },
  },
    
}
</script>

原因说明

Vue2的Options API中,直接监听inject获取的计算属性时,watch机制无法正确追踪其依赖变化。改用Composition API的watch可直接监听响应式值;而提供响应式对象的方式,是利用了Vue对对象属性的响应式追踪逻辑——只要对象引用不变,内部属性的变化就能被监听到。

内容的提问来源于stack exchange,提问作者user22470297

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:40:10