用于跨层级组件通信(避免 props 层层传递),适用于深层嵌套的组件。
<script>
export default {
provide() {
return {
appName: '我的应用', // 提供静态数据
user: this.currentUser // 提供响应式数据(需用函数包裹确保响应式)
};
},
data() {
return { currentUser: { name: '管理员' } };
}
};
</script>
<script>
export default {
inject: ['appName', 'user'], // 注入父组件提供的数据
mounted() {
console.log(this.appName); // 输出:我的应用
console.log(this.user.name); // 输出:管理员
}
};
</script>
- 注入的数据默认不是响应式的,若需响应式,应传递组件的响应式数据(如
this.currentUser);
- 适用于插件开发或大型组件库,普通场景优先用 Vuex 或事件总线。
Provide/Inject 本身不保证数据响应式,若提供的数据是非响应式的(如静态值),注入后无法监听变化。只有当提供的数据是组件的响应式数据(如 data 中的属性)时,注入后才能被监听
// 父组件(提供数据)
<script>
export default {
data() {
return {
userInfo: { name: "张三", age: 20 } // 响应式数据
};
},
provide() {
return {
// 提供响应式数据(必须传递组件实例的响应式属性)
user: this.userInfo
};
},
methods: {
updateUser() {
this.userInfo.age = 21; // 修改响应式数据
}
}
};
</script>
注入数据后,可通过 watch 监听其变化,但需注意监听的 “深度”(针对对象 / 数组)。
// 深层子组件(注入并监听)
<script>
export default {
inject: ["user"], // 注入父组件提供的 user
watch: {
// 监听注入的 user 对象(需深度监听)
user: {
handler(newVal, oldVal) {
console.log("用户信息变化:", newVal);
},
deep: true, // 监听对象内部属性变化
immediate: true // 初始化时立即执行一次
},
// 监听对象的某个具体属性(更高效)
"user.age"(newVal) {
console.log("年龄变化为:", newVal);
}
}
};
</script>
若提供的是字符串、数字等基本类型,直接监听即可(无需 deep):
// 父组件提供基本类型
provide() {
return { count: this.number }; // this.number 是 data 中的响应式数字
}
// 子组件监听
watch: {
count(newVal) {
console.log("数字变化:", newVal);
}
}
原因:
- 提供的不是响应式数据(如
provide() { return { user: { name: "张三" } } },这是普通对象,非响应式);
- 直接替换了整个对象(破坏了响应式引用),例如:
// 错误:直接替换对象,响应式失效
this.userInfo = { name: "李四", age: 22 }; // 新对象会丢失响应式关联
解决方案:
- 始终提供
data 中的响应式属性;
- 修改对象时,更新属性而非替换整个对象
// 正确:修改属性(保持响应式引用)
this.userInfo.name = "李四";
this.userInfo.age = 22;
解决方案:
- 对对象开启
deep: true(但性能开销较大);
- 精确监听具体属性(如
"user.age"),更高效。
解决方案:
在 watch 中添加 immediate: true,初始化时执行一次 handler
watch: {
user: {
handler(newVal) { /* 处理逻辑 */ },
deep: true,
immediate: true // 初始化立即执行
}
}
<!-- 爷爷组件(提供数据) -->
<template>
<button @click="updateUser">修改用户信息</button>
<parent-component />
</template>
<script>
import ParentComponent from './ParentComponent.vue';
export default {
components: { ParentComponent },
data() {
return {
user: { name: "初始姓名", age: 18 } // 响应式数据
};
},
provide() {
return { globalUser: this.user }; // 提供响应式数据
},
methods: {
updateUser() {
this.user.age += 1; // 修改属性(保持响应式)
}
}
};
</script>
<!-- 父亲组件(中间层,无需处理数据) -->
<template>
<child-component />
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default { components: { ChildComponent } };
</script>
<!-- 孙子组件(注入并监听) -->
<template>
<div>
<p>姓名:{{ globalUser.name }}</p>
<p>年龄:{{ globalUser.age }}</p>
</div>
</template>
<script>
export default {
inject: ["globalUser"],
watch: {
// 监听年龄变化
"globalUser.age"(newVal) {
console.log("年龄更新为:", newVal);
alert(`年龄变为${newVal}岁`);
},
// 深度监听整个对象
globalUser: {
handler(newVal) {
console.log("用户信息整体变化:", newVal);
},
deep: true
}
}
};
</script>
Provide/Inject 用于跨层级传递数据,但需确保提供的是响应式数据(data 中的属性);
- 注入后,可通过
watch 监听变化,对象需开启 deep: true,基本类型直接监听;
- 避免直接替换对象,应修改属性以保持响应式关联。