通过Vue 2 组件基础一文的学习,我们知道组件之间可以通过传递props或事件来进行通信。
但在一些情况下,我们使用下面的方法将更有用。
1.访问根实例
根实例可通过this.$root
获取。
我们在所有子组件中都可以像上面那样访问根实例,它就像一个vuex
中的全局store
。
这样我们可以在根实例上定义方法和属性,这些方法和属性可以在所有组件中访问。
根实例也可以用作事件总线,你可以触发根实例上的自定义事件,在其他组件上监听这些事件以进行通信。一个示例如下:
<!DOCTYPE html>
<html>
<head>
<title>Vue 事件总线</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="sendMessage">Send Message By Root</button>
<child-component></child-component>
</div>
<script>
// 注册组件
Vue.component('child-component', {
data: function () {
return {
childMessage:'childMsg'
}
},
template:
`
<div>
<p>Message in ChildComponent:{{childMessage}}</p>
</div>
`,
created(){
//通过 this.$root 监听`message-sent`事件
this.$root.$on('message-sent',message=>{
this.childMessage=message
})
}
});
var vm = new Vue({
el: '#app',
data:{
message:'rootMsg'
},
methods:{
sendMessage(){
//在根实例上触发自定义事件'message-sent'
this.$emit('message-sent',this.message)
}
}
});
</script>
</body>
</html>
<script>
2.访问父组件实例、访问子组件实例或子元素
之前我们可以通过传递prop
来达到 子组件访问父组件实例 或者称为 父组件向子组件传值 的目的。
现在我们可以使用$parent
property来访问父级组件实例。
之前我们也通过触发自定义事件传递抛出值
的方式来访问子组件实例。
同样的,我们可以通过ref
attribute为子组件或子元素添加一个ID引用。
<child-component ref="child"></child-component>
于是可以使用this.$refs.child
来访问子组件实例。
通过ref引用子组件示例:
<!DOCTYPE html>
<html>
<head>
<title>Vue ref 示例</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="toggleColor">Toggle Color</button>
<p :style="{ color: textColor }">This text color can be toggled.</p>
<child-component ref="childRef"></child-component>
</div>
<script>
// 子组件
Vue.component('child-component', {
template:
`
<div>
<p>This is a child component.</p>
</div>
`,
methods: {
sayHello() {
console.log('Hello from child component!');
}
}
});
var vm = new Vue({
el: '#app',
data: {
textColor: 'black',
isChildVisible: true
},
methods: {
toggleColor() {
this.textColor = this.textColor === 'black' ? 'red' : 'black';
// 通过 ref 访问子组件实例中的方法
this.$refs.childRef.sayHello();
}
}
});
</script>
</body>
</html>
3.依赖注入
不管是this.$parent
、this.$refs
,都可能会陷入深层嵌套的风险,我们可能会通过this.$parent.$parent.$parent
来访问上层某个组件实例。这无疑是不合理的。
针对较深层级的组件访问,Vue设计了依赖注入的模式。它允许我们将一个依赖注入到某个组件里,以便组件可以访问这个依赖而不需要显示传递它。这对于共享全局配置或服务非常有用,例如国际化(i18n)配置、数据请求服务等。
具体的,我们通过在父组件provide
选项提供依赖,然后在子组件的inject
选项注入依赖。
示例:
//在父组件中
provide:{
userSevice:new UserService()
}
//在子组件中
inject:['userService'],
created(){
this.userService.doSomething()
}
为什么我们不使用$root
实现这种方案呢?我认为,依赖注入适合小范围的配置共享,而全局共享则适用于$root
。