不同组件之间是如何通信的

本文详细介绍了Vue中不同组件之间的通信方式,包括props/$emit的父传子、子传父通信,$children/$parent的直接访问,provide/inject的跨级通信,ref/refs的引用,eventBus的全局事件总线,Vuex的状态管理,以及LocalStorage的数据持久化。同时提到了$attrs/$listeners在多级组件通信中的应用。
摘要由CSDN通过智能技术生成

不同组件之间是如何通信的

请永远牢记vue是单向数据流

①props / $emit

父组件通过props的方式向子组件传递数据,而通过$emit子组件可以向父组件通信。

 1. 父组件向子组件传值:

接下来我们通过一个例子,说明父组件如何向子组件传递值:在子组件 Users.vue 中如何获取父组件 App.vue 中的数据 users:["Henry","Bucky","Emily"]

App.vue父组件


<template>
  <div id="app">
    <users v-bind:users="users"></users>//前者自定义名称便于子组件调用,后者要传递数据名
  </div>
</template>
<script>
import Users from "./components/Users"
export default {
  name: 'App',
  data(){
    return{
      users:["Henry","Bucky","Emily"]
    }
  },
  components:{
    "users":Users
  }
}

  users.vue子组件

 

//users子组件
<template>
  <div class="hello">
    <ul>
      <li v-for="user in users">{{user}}</li>//遍历传递过来的值,然后呈现到页面
    </ul>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props:{
    users:{           //这个就是父组件中子标签自定义名字
      type:Array,
      required:true
    }
  }
}
</script>

子组件通过props来接受数据

第一种方式:直接接收数组

props: ['childCom']

第二种方式:设置数组类型

props: {
    childCom: String //这里指定了字符串类型,如果类型不一致会警告的哦
}

第三种方式:限制数组 设置类型 默认值

props: {
    childCom: {
        type: String,
        default: 'sichaoyun' 
    }
}

 

2.子组件向父组件传值(通过事件形式)

vue2.0只允许单向数据传递,我们通过出发事件来改变组件的数据

接下来我们通过一个例子,说明子组件如何向父组件传递值:当我们点击“Vue.js Demo”后,子组件向父组件传递值,文字由原来的“传递的是一个值”变成“子向父组件传值”,实现子组件向父组件值的传递。

子组件 :子组件通过$emit触发父组件上的自定义事件,发送参数


<template>
  <header>
    <h1 @click="changeTitle">{{title}}</h1>//绑定一个点击事件
  </header>
</template>
<script>
export default {
  name: 'app-header',
  data() {
    return {
      title:"Vue.js Demo"
    }
  },
  methods:{
    changeTitle() {
      this.$emit("titleChanged","子向父组件传值");//自定义事件  传递值“子向父组件传值”
    }
  }
}
</script>

父组件通过绑定自定义事件,接受子组件传递过来的参数

<template>
  <div id="app">
    <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致
   // updateTitle($event)接受传递过来的文字
    <h2>{{title}}</h2>
  </div>
</template>
<script>
import Header from "./components/Header"
export default {
  name: 'App',
  data(){
    return{
      title:"传递的是一个值"
    }
  },
  methods:{
    updateTitle(e){   //声明这个函数
      this.title = e;
    }
  },
  components:{
   "app-header":Header,
  }
}
</script>

②$children / $parent

this.$children[0].msg = "hello world" //父组件修改子组件data中的数据

this.$parent.mag //子组件拿到父组件data中的数据

$children的值是数组,$parent的值是个对象

注意:$parent,$children它们的目的是作为访问数组的应急方法,更推荐用props和events实现父子组件通信。

③provide / inject

这是vue2.2.0新增的api,简单来说就是父组件中通过provide来提供变量,然后再子组件中通过inject来注入变量。

父组件

export default{

    name:"A",

    provide:{

        for:"demo"

    },

    components:{

        comB

    }

}

子组件

export default{

    name:"B",

    inject:["for"],

    data(){

        demo:this.for

    }

}

④ref / refs

ref:如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例,可通过实例直接调用组件的方法或访问数据。

父组件

<template>

    <component-a ref="comA"></component-a>

</template>

<script>

    export default{

        mounted(){

            const comA = this.$refs.comA;

            console.log(comA.name)//Vue.js

            comA.sayHello() //hello

        }

    }

</script>

 子组件

export default{

    data(){

        return {

            name:"Vue.js"

        }

    },

    methods:{

        sayHello(){

            console.log("hello")

        }

    }

} 

⑤eventBus(Bus总线):$emit  / $on

1. 初始化,全局创建$bus 

  注意,这种方式初始化一个 全局的事件总线 。
  直接在项目中的 main.js 初始化 $bus :

// main.js
window.$bus=new Vue();

2. 发送事件

   $bus.$emit("aMsg", '来自A页面的消息');

<!-- A.vue -->
<template>
   <button @click="sendMsg()">-</button>
</template>

<script> 
//import $bus from "../bus.js";
export default {
 methods: {
   sendMsg() {
     $bus.$emit("aMsg", '来自A页面的消息');
   }
 }
}; 
</script>

3. 接收事件
$bus.$on("事件名",callback)

<!-- IncrementCount.vue -->
<template>
 <p>{{msg}}</p>
</template>

<script> 
//import $bus  from "../bus.js";
export default {
 data(){
   return {
     msg: ''
   }
 },
 mounted() {
   $bus.$on("aMsg", (msg) => {
     // A发送来的消息
     this.msg = msg;
   });
 }
};
</script>

在组件中,可以使用$emit, $on, $off 分别来分发、监听、取消监听事件

⑥Vuex

介绍vuex原理:

Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更改 State 中的数据时,必须通过 Mutation 进行,Mutation 同时提供了订阅者模式供外部插件调用获取 State 数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走 Action,但 Action 也是无法直接修改 State 的,还是需要通过 Mutation 来修改 State 的数据。最后,根据 State 的变化,渲染到视图上。

 

 

⑦LocalStorage

vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在 vuex 里数据改变的时候把数据拷贝一份保存到 localStorage 里面,刷新之后,如果 localStorage 里有保存的数据,取出来再替换 store 里的 state。

⑧$attrs / $listeners

 将数据挂在到子组件的标签上去后,在子组件中使用this.$attrs直接获取到所有挂载的数据,返回的是一个对象。 

多级组件嵌套需要传递数据时,通常使用的方法是通过 vuex。但如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点大材小用。为此 Vue2.4 版本提供了另一种方法----$attrs/$listeners

  • $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。
  • $listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件

 总结:

常见使用场景可以分为三类:

  • 父子通信:
    父向子传递数据是通过 props,子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs / $listeners
  • 兄弟通信:
    Bus;Vuex
  • 跨级通信:
    Bus;Vuex;provide / inject API、$attrs / $listeners
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值