Vue中组件间通信方式总结

使用props和$emit进行组件间数据传递

这是最常用的组件通信方式,适用于父子组件间数据传递

  • 父传子:子组件中props定义好要接受的数据,父组件中使用v-bind传递子组件props中定义好的数据。
  • 子传父: $emit(‘自定义事件名’,arguments),子组件中使用 $emit自定义事件及一个或多个参数,父组件中监听自定义事件并作相应业务处理

使用$attrs$listeners来实现父子组件间数据通信

适用场景

嵌套的多层父子组件(只有父子组件两个建议使用props$emit

基本步骤
  • 在组件中使用v:bind="$attrs"来实现父级向子组件传递数据
  • 使用v-on="$listeners"来监听子组件传递的事件和数据
  • 子组件使用$attrs拿到父组件中data中定义的属性
  • 在嵌套的父子组件中的html部分步骤1和步骤2都不可以缺少
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>局部组件的使用</title>
</head>
<body>
    <div id="app">
        <h1>在有template选项时,#app里的内容不展示</h1>
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">

Vue.component('A', {
   template: `
    <div>
        {{$attrs}}
        <B v-bind="$attrs" v-on="$listeners" @getCData="getCData"/>
    </div>
   `,
   
   methods: {
    getCData(val) {
        console.log('我是A组件'+val)
    }
   }
 
})
Vue.component('B', {
   template: `
    <div>
        {{$attrs}}
        <C v-bind="$attrs" v-on="$listeners" @getCData="getCData"/>
    </div>
   `,
   methods: {
    getCData(val) {
        console.log('我是B组件'+val)
    }
   }
   
   
})
Vue.component('C', {
   template: `
   <div>
        {{$attrs}}
        <p @click="my_click">{{$attrs.dataA}}</p>
    </div>
  
   `,
   methods: {
       my_click() {
           this.$emit('getCData', '111')
       }
   }
})
let vm = new Vue({
    el: '#app',
    template: `
    <div>
        <input type="text" v-model="data"/>
        <A :dataA="data" :anotherData="anotherData"/>
    </div>
    `,
    data() {
        return {
            data: '这是给c的数据',
            anotherData: '测试数据'
        }
    },
    
})
</script>
</html>
网页截图

在这里插入图片描述
从这里可以看到KaTeX parse error: Expected '}', got 'EOF' at end of input: … this.emit(‘getCData’, ‘111’)
}` 会触发getCData事件,在B和A组件中都监听了该事件,从而每点击一次C组件文本,都会在控制太打印出相应的内容。如下图所示
在这里插入图片描述

使用中央事件总线进行组件间通信

当组件不是父子组件关系,比如平行组件间数据通信,或者有两个平行组件A和B,A组件的子组件是C。A和C组件间的数据通信可以使用中央事件总线。

适用场景

非父子组件数据通信

基本步骤
  • let bus = new Vue() 创建中央事件总线
  • bus.$emit(‘自定义事件名’,要传递的值)使用bus.$emit传递自定义事件和值
  • bus.$on(‘自定义事件名’, eventHandler) 使用bus.$on 在组件的mounted阶段监听自定义事件并在回调函数eventHandler中作相应的业务处理
Vue.component('A', {
    template: `
        <input type="text" v-model="valueA" @click="my_click" />
    `,
    data() {
        return {
            valueA: '我是A组件的值'
        }
    },
    methods: {
        my_click() {
            bus.$emit('getAData', this.valueA)
        }
    },
    mounted() {
        bus.$on('getCValue', val => this.valueA = val)
    }
})
Vue.component('B', {
    template: `
     <C/>
    `,
    data() {
        return {
          
        }
    }
})

Vue.component('C', {
    template: `
        <input type="text" v-model="valueC" @change="changeValue(valueC)"/>
    `,
    data() {
        return {
            valueC: ''     
       }
    },
    methods: {
        changeValue(value) {
            bus.$emit('getCValue', value)
        }
    },
    mounted() {
        bus.$on('getAData', val => {
            this.valueC = val
        })
    }
})

let bus = new Vue()
let vm = new Vue({
    el: '#app',
    template: `
    <div>
        <A/>
        <B/>
    </div>
    `
    
})

上述代码中定义了三个全局组件A,B,C。其中A和B是平行组件,C是B的子组件。
页面效果如下图
在这里插入图片描述

A组件中data函数定义了valueA:‘我是A组件的值’,现在想把valueA展示在C组件文本框中。通过点击事件
my_click() { bus.$emit('getAData', this.valueA) } 使用bus.$emit 传递出事件getADatavalueA的值。
在C组件的mounted阶段使用bus.$on('getAData', val => { this.valueC = val }) 将传递来的valueA赋值给valueC从而将值在C组件中展示。
当C组件的值发生改变时A组件同样能监听到事件从而使文本框的值发生改变。

使用中央事件总线进行数据通信时,需要在同一个Vue实例中使用$on监听事件和$emit来触发事件。上述代码中的事件监听和传递都是在VM实例中的。

在vue中组件间通信还有更多其他方式比如使用$parent,$children,或者使用父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。(这两种很少使用,故不多作赘述)
以及针对大型项目中vuex都能实现组件间通信。

上面讲述的三种组件间通信方式基本满足日常开发需求,根据具体场景选择合适的方式即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值