vue父子/兄弟组件的交互方式

1,362 阅读1分钟

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

截屏2021-11-24 下午4.46.53.png

组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,

  • A-B父子关系
  • A-C爷孙关系
  • B-C父子关系
  • C-D兄弟关系

1.通行方式一 props

props父组件A通过props的方式向子组件B传递,$emit是子组件向上传递方法的方式,而props传递下来的单属性,在子组件中是不允许直接修改父组件的属性值的,所以需要借助.sync去和子组件打通通信通道

// parent 
<template> 
    //子组件无法修改父组件传递的属性值
     <child :content="content"> 
     //需要修改父组件属性值的时候
     <child :content.sync="content">

</template> 

// child 承接父组件的属性
props: { content: String } 

//调用父组件的方法,实现父子通信,
this.$emit("father",data)

//子组件修改props的值
 this.$emit('update:content', data)

2.通行方式二 $emit/$on

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。

$emit相当于抛出组件当中的方法到全局
$on相当于其他组件中可以被调用执行的方法

vm.$emit('JS', '每日一题') 
// 触发当前实例上的事件
vm.$on('JS', function say(val) { 
// 执行事件并接收回传的参数 console.log('JS, ' + 每日一题) }) 

3.通行方式三 $attrs/$listeners

attrs和listeners 属性像两个收纳箱,一个负责收纳属性,一个负责收纳事件(不包含props声明过,以及内置特性绑定属性,如class,style等...)

爷孙组件之间通过这种方式实现属性和方法的传递和使用


//一级 
<div class="details">
      <h1>父组件---{{msg}}</h1>
      <myComponent :a="a" :b="b" @name="getname" @age="getage" @gender="getgender" ></myComponent>
 </div>

methods: {
    getname(e){
      window.console.log("name",e) // name 小编
    },
    getage(){
      window.console.log("age")
    },
    getgender(){
      window.console.log("gender")
  }
//二级 
<div class="child"  v-bind="$attrs">
    <Son v-on="$listeners"/>
</div>

 created () {
    window.console.log(this.$listeners) // {name: ƒ, age: ƒ, gender: ƒ} 
  } ,      

//三级 
<div class="son"  v-bind="$attrs">
    <h3 v-on="$listeners"></h3>
    <button @click="toname">点击</button>
</div>      
    
 data() {
    return {
      name: "小编"
    };
  },
 created() {
    window.console.log(this.$listeners);
  },
  methods: {
    toname() {
      this.$listeners.name(this.name);
    }
  }           

4.通行方式四 provide/ inject

provide,inject主要为高阶组件及组件库所用,理解为允许一个祖先组件为其所有子孙组件注入依赖

 // parent
<template>    
   <child />
</template>
provide: {    
     name: 'JS',
     value:'每日一题',
},

// child
inject: {
    name: String,
    value: String
}
console.log(this.name, this.value) // JS,每日一题