前端面试 vue 部分 (5)——VUE组件之间通信的方式有哪些

  • A+
所属分类:Web前端
摘要

常见使用场景可以分为三类:父子通信:兄弟通信:跨级通信:$emit / $busA触发B

前端面试 vue 部分 (5)——VUE组件之间通信的方式有哪些

VUE组件之间通信的方式有哪些(SSS)

前端面试 vue 部分 (5)——VUE组件之间通信的方式有哪些

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

  • 父子通信:

    • null
      父向子传递数据是通过 props ,子向父是通过 $emit / $on
    • $emit / $bus
    • Vuex
    • 通过父链 / 子链也可以通信( $parent / $children
    • ref 也可以访问组件实例
  • 兄弟通信:

    • $emit / $bus
    • Vuex
  • 跨级通信:

    • $emit / $bus
    • Vuex
    • provide / inject API
    • $attrs/$listeners

$emit / $bus

// main.js  Vue.prototype.$bus = new Vue() // event Bus 用于无关系组件间的通信。  

A触发B

 //  A   this.$bus.$emit('new-messsage-at-me', {      data: { conversationID: message.conversationID }    })             
//  B    mounted() {      this.$bus.$on('new-messsage-at-me', event => {        if (          event.data.conversationID === this.conversation.conversationID &&          this.conversation.conversationID !==            this.currentConversation.conversationID        ) {          this.hasMessageAtMe = true        }      })    },  

父子组件通信

  1. 父组件向子组件传值( props ):
//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子组件   // 注:组件中的数据共有三种形式:data、props、computed  <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>  
  1. 子组件向父组件传值(B 组件中 $emit, A 组件中 v-on ):
// 子组件  <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>  

$ref 与 $parent $children

  • 使用 this.$parent查找当前组件的父组件。
  • 使用 this.$children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的。
  • 使用 this.$root查找根组件,并可以配合$children遍历全部组件。
  • 使用 this.$refs查找命名子组件( )( this.$refs.one )

$attrs / $listeners

  • 两者的出现使得组件之间跨组件的通信在不依赖 vuex 和事件总线的情况下变得简洁,业务清晰。
  • A->B->C 多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点杀鸡用牛刀。Vue 2.4 版本提供了另一种方法,使用 v-bind=”$attrs”, 将父组件中不被认为 props特性绑定的属性传入子组件中,通常配合 interitAttrs 选项一起使用。
  • 简单来说:$attrs 与 $listeners 是两个「对象」,$attrs 里存放的是父组件中绑定的非 Props 属性, 唯一缺点 没在props定义的属性 会显示在生成的html标签上, 解决办法:通过inheritAttrs:false,避免顶层容器继承属性; $listeners里存放的是父组件中绑定的非原生事件。

A父组件

<template>   <div>     <child-dom      :foo="foo"      :coo="coo"       v-on:upRocket="reciveRocket"     >     </child-dom>   </div>  </template>  <script>   import childDom from "@/components/ChildDom.vue";   export default {     name:'demoNo',     data() {       return {         foo:"Hello, world",          coo:"Hello,rui"      }    },   components:{childDom},   methods:{     reciveRocket(){        console.log("reciveRocket success")     }   }  }  </script>  

B子组件

<template>     <div>       <p>foo:{{foo}}</p>       <p>attrs:{{$attrs}}</p>       <childDomChild v-bind="$attrs" v-on="$listeners"></childDomChild>     </div>  </template>  <script>  import childDomChild from './childDomChild';  export default {     name:'child-dom'     props:["foo"],     inheritAttrs:false,  }  </script>  

C子组件的子组件

<template>      <div>         <p>coo:{{coo}}</p>         <button @click="startUpRocket">我要发射火箭</button>     </div>  </template>  <script>   export default {     name:'childDomChild',     props:['coo'],     methods:{       startUpRocket(){         this.$emit("upRocket");         console.log("startUpRocket")       }     }   }  </script>  

provide / inject

  • 适用于 隔代组件通信 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
  • 如果是单一的只是拿数据使用,在父组件定义,则在所有子组件都能为之所用
  • 官网不建议在应用中直接使用该办法,理由很直接:他怕你"管不好"

1.一般情况使用都是在app.vue配置为:

provide () {    return {      isTest: this    }  },  

2.所有子组件都可以引用 拿到app.vue里面的所有数据

 inject: ['isTest'],  

欢迎留言~~~