组件通信的方式总结

组件通信的方式

  • props
  • $emit
  • $listener 和 $attrs
  • 全局事件总线
  • vuex

props

父组件

<template>
  <div>
    First
    <second :fatherMessage="fatherMessage" />
  </div>
</template>

<script>
import second from './Second'
export default {
    name: 'First',
    data(){
        return {
          fatherMessage:'come from first'
        }
    },
    components: {
      second
    },
}
</script>

子组件

<template>
  <div>
    {{fatherMessage}}
  </div>
</template>

<script>
export default {
    name: 'Second',
    props: {
        fatherMessage:{
            type: String,
            default: ''
        }
    },
    data(){
        return {}
    }
}
</script>

效果
在这里插入图片描述
其中props可以自定义验证方式:

  • type:用来指值的类型,有以下值可选
    String
    Number
    Boolean
    Array
    Object
    Date
    Function
    Symbol
    当有多个可能的类型时,可以通过propA: [String, Number]方式传递

  • required:是否必传

  • default:默认值
    对于对象或数组的默认值需要通过一个工厂函数获取

    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    

    允许自定义函数进行验证

    propE: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
    

prop存在单向数据流这种规定,即:子组件不能修改父组件传入的值。

$emit

子组件

<template>
  <div>
    <button @click="sendMsgToFirst">向First发送消息</button>
  </div>
</template>

<script>
export default {
    name: 'Second',
    data(){
        return {}
    },
    methods: {
      sendMsgToFirst(){
        this.$emit('getMsgFromSecond','msg from second')
      }
    }
}
</script>

父组件

<template>
  <div>
    First
    <second v-on:getMsgFromSecond="getMsgFromSecond"/>
  </div>
</template>

<script>
import second from './Second'
export default {
    name: 'First',
    data(){
        return {
          fatherMessage:'come from first'
        }
    },
    components: {
      second
    },
    methods: {
      getMsgFromSecond(val){
        console.log(val);
      }
    }
}
</script>

效果
在这里插入图片描述
该方法用于vue实例,仅限于子组件向父组件传值

$listener 和 $attrs

孙子(及以下)组件

<template>
  <div>
    adasd
  </div>
</template>

<script>
export default {
    name: 'Third',
    data(){
        return {}
    },
    components: {
    },
    mounted(){
      console.log('this.$attrs',this.$attrs);
      console.log('this.$listeners',this.$listeners);
      this.$listeners.eventFromFirst()
    }
}
</script>

子组件

<template>
  <div>
    second
    <third v-bind="$attrs" v-on="$listeners"/>
  </div>
</template>

<script>
import third from './Third'
export default {
    name: 'Second',
    data(){
        return {}
    },
    components: {
      third
    },
    methods: {
    }
}
</script>

父组件

<template>
  <div>
    First
    <second :msgFromFirst="msgFromFirst" @eventFromFirst="eventFromFirst"/>
  </div>
</template>

<script>
import second from './Second'
export default {
    name: 'First',
    data(){
        return {
          msgFromFirst:'come from first'
        }
    },
    components: {
      second
    },
    methods: {
      eventFromFirst(){
        console.log('a event from first');
      }
    }
}
</script>

效果
在这里插入图片描述
此种方式较prop更适合多及组件的通信。同时,只要我们在子组件接收某个属性,那么该属性就会被子组件“截胡”,孙子组件们就无法在拿到了。
用官方的话来说,即:

$attrs包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (classstyle 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (classstyle 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

对于$listeners来说

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

全局事件总线

main.js

new Vue({
    ......
    beforeCreate(){
        Vue.prototype.$bus = this // 安装全局事件总线,$bus就是当前应用的vue
    }
    ......
})

组件A

<template>
  <div>
    First
    <second/>
  </div>
</template>

<script>
import second from './Second'
export default {
    name: 'First',
    data(){
        return {
        }
    },
    components: {
      second
    },
    methods: {
    },
    mounted(){
      this.$bus.$emit('globalEvent','a msg from first')
    }
}
</script>

组件B(主要表示C和A不是父子关系)

<template>
  <div>
    second
    <third/>
  </div>
</template>

<script>
import third from './Third'
export default {
    name: 'Second',
    data(){
        return {}
    },
    components: {
      third
    },
    methods: {
    }
}
</script>

组件C

<template>
  <div>
    third
  </div>
</template>

<script>
export default {
    name: 'Third',
    data(){
        return {}
    },
    components: {
    },
    mounted(){
      this.$bus.$on('globalEvent',(val)=>{
        console.log('this is third >>>',val);
      })
    }
}
</script>

效果
在这里插入图片描述
该种方法可以做到任意组件的通信,但是要注意在组件创建后注册事件,在组件销毁后通过$off解绑

Vuex

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
详见文档:https://vuex.vuejs.org/zh/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值