vue组件通信的方法

  前言

 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。但是,在实际的项目开发中,形如页面和页面之间需要通信一样,Vue 组件和组件之间肯定也需要互通有无、共享状态。接下来在了解组件通信之前,我们先来了解一下组件间的几种关系:

    

 如图所示:

  • A 和 B、B 和 C、B 和 D 都是父子关系
  • C 和 D 是兄弟关系
  • A 和 C 是隔代关系(可能隔多代)

 针对不同的组件关系我们会有更适合的通信方式,接下来就让我们来看一下吧。

 

  组件通信

  1、父组件向子组件传值props

  props 以单向数据流的形式可以很好的完成父子组件的通信。所谓单向数据流:就是数据只能通过 props 由父组件流向子组件,而子组件并不能通过修改 props 传过来的数据修改父组件的相应状态。至于为什么这样做,Vue 官网做出了解释:

  所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。  

  额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    ——Vue 官网
<!--父组件-->
<template>
  <div>
    <children :child="message"></children> //前者自定义名称便于子组件调用,后者要传递的数据名
  </div>
</template>
<script>
import children from "@/views/send/children";//引入子组件
export default {
  name: "parent",
  data(){
    return{
      message: '我是父组件的值!'
    }
  },
  components:{
    children
  },
}
</script>

 

<!--子组件-->
<template>
<div>
<h1>{{child}}</h1>
</div>
</template>
<script>
export default {
name: "children",
props:["child"], //也可以使用下面的对象类型接收数据
props:{
child:{
type:String,
require:true //表示用这个组件的时候就必须传值child,否则报错
}
},
}
</script>

 

  2、子组件向父组件传值 $emit

<!--子组件-->
<template>
<div>
  <input type="text" v-model="message">
  <button @click="click">Send</button>
</div>
</template>
<script>
export default {
  name: "children",
  data(){
    return{
      message:'我是子组件的值!'
    }
  },
  methods:{
    click(){
      this.$emit('childFn',this.message);//自定义事件名childFn
    }
  }
}
</script>

 

<!--父组件-->
<template>
  <div>
    <children @childFn="parentFn"></children> //注意在组件上要对方法名进行绑定
    <p>子组件传来的值:{{paMess}}</p>
  </div>
</template>
<script>
import children from "@/views/send/children";
export default {
  name: "Cart",
  data(){
    return{
      paMess:''
    }
  },
  components:{
    children
  },
  methods:{
    parentFn(payload){
      this.paMess = payload;//payload就是子组件传来的值,父组件接收
    }
  }
}
</script>

 

3、ref 和 $refs 传值

  • 父组件向子组件传值
<!--父组件-->
<template>
  <div>
<!--    点击触发方法将数据传给子组件-->
    <button @click="sendData">send</button>
    <children ref="myChild"></children>
  </div>
</template>
<script>
import children from "@/views/send/children";
export default {
  name: "parent",
  data(){
    return{
    }
  },
  components:{
    children
  },
  methods:{
    sendData(){
      //父组件触发子组件的init方法
      this.$refs.myChild.init("waq",22)
    }
  }
}
</script>

 

<!--子组件-->
<template>
<div>
  <h1>{{name}}</h1>
  <h1>{{age}}</h1>
</div>
</template>
<script>
export default {
  name: "children",
  data(){
    return{
      name: '',
      age: ''
    }
  },
  methods:{
    init(name,age){
      this.name = name;
      this.age = age;
    }
  }
}
</script>

 

  • 父组件还可以通过ref获取子组件的值,即子组件向父组件传值
<!--父组件-->
<template>
  <div>
<!--    点击触发方法获取子组件的数据-->
    <button @click="getData">send</button>
    <children ref="myChild"></children>
    <p>{{parMes}}</p>
  </div>
</template>
<script>
import children from "@/views/send/children";
export default {
  name: "parent",
  data(){
    return{
      parMes:'',
    }
  },
  components:{
    children
  },
  methods:{
    getData(){
      //父组件获取子组件message值
      this.parMes = this.$refs.myChild.message;
    }
  }
}
</script>

 

<!--子组件-->
<template>
<div>
</div>
</template>
<script>
export default {
  name: "children",
  data(){
    return{
      message:'我是子组件的值!!'
    }
  },
}
</script>

 

 4、$parent 和 $children

 $parent 就是父组件的实例对象,

 $children 就是当前实例的直接子组件实例了,不过这个属性值是数组类型的,且并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。父组件也可以通过this.$children 访问它所有的子组件

<!--父组件-->
<template>
  <div>
    <button @click="changeChild">change</button>
    <children></children>
  </div>
</template>
<script>
import children from "@/views/send/children";
export default {
  name: "parent",
  data(){
    return{
      message:'hello'
    }
  },
  components:{
    children
  },
  methods:{
    changeChild(){
      this.$children[0].mymessage = 'hello';
    }
  }
}
</script>

 

<!--子组件-->
<template>
<div>
  <input type="text" v-model="mymessage" @change="changeValue">
</div>
</template>
<script>
export default {
  name: "children",
  data(){
    return{
      mymessage: this.$parent.$message
    }
  },
  methods: {
    changeValue(){
      this.$parent.message = this.mymessage;//通过如此调用可以改变父组件的值
    }
  }
}
</script>

  在上面实例代码中,分别定义了 parent 和 child 组件,这两个组件是直接的父子关系。两个组件分别在内部定义了自己的属性。在 parent 组件中,直接通过 this.$children[0].mymessage = 'hello';child 组件内的 mymessage 属性赋值,而在 child 子组件中,同样也是直接通过this.$parent.messageparent 组件中的 message 赋值,形成了父子组件通信。

 
5、Vuex 状态管理

  关于此方法的通信会在下一篇博客详细介绍。

 

 

 


 

参考文章:https://juejin.cn/post/6844903784963899405#heading-7 

 

posted @ 2021-10-31 20:30  打遍天下吴敌手  阅读(206)  评论(0编辑  收藏  举报