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


    file

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

    图片

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

    • 父子通信:

      • 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'], 
    

    欢迎留言~~~

  • 相关阅读:
    Next Permutation leetcode java
    用户上网行为管理之Panabit
    ROS之冗余线路Recursive Route
    ros的romon功能介绍以及使用条件
    nf_conntrack: table full, dropping packet. 终结篇
    nf_conntrack满之解决方法nginx报502错误
    Ros之BGP学习87-88课
    ros关于动态路由ospf优先级cost和priority的区别和联系
    ros ppp隧道up或者down的时候,可以写脚本,脚本可以调用的参数$user $local-address $remote-address $caller-id $called-id $interface
    ROS 6.X目前限速比较稳定的一个脚本小包优先
  • 原文地址:https://www.cnblogs.com/zhaoduoduo/p/13444879.html
Copyright © 2020-2023  润新知