0
点赞
收藏
分享

微信扫一扫

Vue组件通信的其他方式


Vue组件通信的其他方式

  • ​​一、序言​​
  • ​​二、组件通信的其他实现方式​​
  • ​​2.1 访问根实例​​
  • ​​2.2 访问父组件实例​​
  • ​​2.3 访问子组件实例或子元素​​
  • ​​2.4 provide和inject​​

一、序言

总结一下前面介绍的组件通信的3种方式:

  • 父组件通过prop向子组件传递数据。
  • 子组件通过自定义事件向父组件发起通知或进行数据传递。
  • 子组件通过​<slot>​元素充当占位符,获取父组件分发的内容;也可以在子组件的​<slot>​元素上使用v-bind指令绑定一个插槽prop,向父组件提供数据。
    现在介绍组件通信的其他实现方式

二、组件通信的其他实现方式

2.1 访问根实例

  在每一个根组件实例的子组件中,都可以通过​​$root​​属性访问根实例。例如:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<parent></parent>
</div>

<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
price: 188
}
},
computed: {
totalPrice(){
return this.price * 10;
}
},
methods: {
hello(){
return "Hello, Java无难事";
}
}
})

app.component('parent', {
template: '<child></child>'
})

app.component('child', {
methods: {
accessRoot(){
console.log("单价:" + this.$root.price);
console.log("总价:" + this.$root.totalPrice);
console.log(this.$root.hello());
}
},
template: '<button @click="accessRoot">访问根实例</button>'
})

app.mount('#app');
</script>
</body>
</html>

  在浏览器单击“访问根实例”按钮,Console窗口中输出如下:

Vue组件通信的其他方式_html


  不管组件是根实例的子组件,还是更深层级的后代组件,$root属性总是代表了根实例。

2.2 访问父组件实例

  与​​$root​​​类似,​​$parent​​​属性用于在一个子组件中访问父组件的实例,这可以替代父组件通过​​prop​​​向子组件传数据的方式。
例如:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<parent></parent>
</div>

<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({});
app.component('parent', {
data(){
return {
price: 188
}
},
computed: {
totalPrice(){
return this.price * 10;
}
},
methods: {
hello(){
return "Hello, Java无难事";
}
},
template: '<child></child>'
})

app.component('child', {
methods: {
accessParent(){
console.log("单价:" + this.$parent.price);
console.log("总价:" + this.$parent.totalPrice);
console.log(this.$parent.hello());
}
},
template: '<button @click="accessParent">访问父组件实例</button>'
})

app.mount('#app')
</script>
</body>
</html>

Vue组件通信的其他方式_Vue_02

​$parent​​属性只能用于访问父组件实例,如果父组件之上还有父组件,那么该组件是访问不到的。

2.3 访问子组件实例或子元素

  现在反过来,如果父组件要访问子组件实例,应该怎么办?在Vue.js中,父组件要访问子组件实例或子元素,可以给子组件或子元素添加一个特殊的属性​​ref​​​,为子组件或子元素分配一个引用ID,然后父组件就可以通过​​$refs​​属性访问子组件实例或子元素。代码示例如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<parent></parent>
</div>

<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({});
app.component('parent', {
mounted(){
// 访问子元素<input>,让其具有焦点
this.$refs.inputElement.focus();
// 访问子组件<child>的message数据属性
console.log(this.$refs.childComponent.message)
},
template: `
<div>
<input ref="inputElement"><br> <!--子元素-->
<child ref="childComponent"></child> <!-- 子组件-->
</div>`
})

app.component('child', {
data(){
return {
message: 'Java无难事'
}
},
template: '<p>{{message}}</p>'
})

app.mount('#app');
</script>
</body>
</html>

Vue组件通信的其他方式_ide_03


  需要注意的是,​​$refs​​​属性只在组件渲染完成之后生效,并且它们都不是响应式的。要避免在模板和计算属性中访问​​$refs​​。

2.4 provide和inject

  ​​$root​​​属性用于访问根实例,​​$parent​​​属性用于访问父组件实例,但如果组件嵌套的层级不确定,某个组件的数据或方法需要被后代组件所访问,又该如何实现呢?这时需要用到两个新的实例选项:​​provide和inject​​​。​​provide​​​选项允许指定要提供给后代组件的数据或方法,在后代组件中使用​​inject​​选项接收要添加到该实例中的特定属性。代码如下所示:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<parent></parent>
</div>

<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({});
app.component('parent', {
data() {
return {
msg: 'Java无难事'
}
},
methods: {
sayHello(name){
console.log("Hello, " + name);
}
},
provide(){
return {
// 数据message和sayHello方法可供后代组件访问
message: this.msg,
hello : this.sayHello
}
},
template: '<child/>',
})

app.component('child', {
// 接收message数据属性和hello方法
inject: ['message', 'hello'],
mounted(){
// 当自身的方法来访问
this.hello('zhangsan');
},
// 当自身的数据属性来访问
template: '<p>{{message}}</p>'
})

const vm = app.mount('#app')
</script>
</body>
</html>

  使用​​provide​​​和​​inject​​​,父组件不需要知道哪些后代组件要使用它提供的属性,后代组件不需要知道被注入的属性来自哪里。
  不过上述代码也存在一些问题。首先注入的message属性并不是响应式的,当修改父组件的msg数据属性时,message属性并不会跟着改变。这是因为默认情况下,provide/inject绑定并不是响应式的,可以通过传递ref属性或reactive对象更改这个行为。(后面再说吧)
  其次,provice和inject将应用程序中的组件与它们当前的组织方式耦合起来,使得重构变得更加困难。
  如果数据需要在多个组件中访问,并且能够相应更新,可以考虑真正的状态管理解决方案–​​​Vuex​​。


举报

相关推荐

0 条评论