Vue中如何使用$attrs和$listeners进行组件通讯?

1. 介绍

Vue作为一个前端框架,应用于组件化开发。在Vue中,父组件和子组件之间还有其他组件之间的通讯问题。Vue提供了一组API用于处理这些问题,最简单的是通过props和自定义事件传递数据,但是当组件层级嵌套较深时,这种方式会变得累赘。在这篇文章中,我们将会详细介绍Vue中如何使用 $attrs 和 $listeners 组件通讯。

2. $attrs属性

在Vue中,当我们在一个父组件中使用一个自定义组件时,如果这个组件有一些props属性,那么有些时候这些属性不会直接渲染到这个组件上,这通常是因为这些props并不是该组件使用的属性,而是它所包含的子组件的属性。在这种情况下,我们就可以使用 $attrs 属性来传递这些属性。

2.1 使用方式

在Vue中使用 $attrs 的方式非常简单,只需要在子组件上添加 “v-bind” 指令,然后将“$attrs” 作为参数,即可很方便的将父组件传入的属性和方法绑定到子组件上:

// 子组件 MyComponent

<template>

<div>

<ChildComponent v-bind="$attrs"></ChildComponent>

</div>

</template>

以上代码中,我们在MyComponent组件的模板中渲染了 <ChildComponent> 组件,并使用了 v-bind 将我们从父组件传递的所有属性和方法绑定到子组件上。这时, <ChildComponent> 组件就可以通过 $attrs 访问到这些属性和方法。

2.2 案例分析

为了更深入的了解 $attrs 的使用方式,我们可以看一个简单的案例。假设我们需要在父组件中使用一个自定义的button组件:

// 自定义组件Button

<template>

<button :class="classes">

<span v-if="icon" :class="iconClasses"></span>

{{ label }}

</button>

</template>

<script>

export default {

name: 'Button',

props: {

label: {

type: String,

default: ''

},

icon: {

type: String,

default: ''

},

primary: {

type: Boolean,

default: false

},

danger: {

type: Boolean,

default: false

}

},

computed: {

classes () {

const result = {

'button': true,

'button-primary': this.primary,

'button-danger': this.danger

}

return result

},

iconClasses () {

return `icon-${this.icon}`

}

}

}

</script>

通过以上代码,我们已经定义了一个button组件。该组件接受label、icon、primary、danger等多个props属性。在父组件中使用该组件:

// 父组件

<template>

<div>

<Button label="Submit" icon="submit" primary />

</div>

</template>

<script>

import Button from './Button'

export default {

name: 'MyComponent',

components: {

Button

}

}

</script>

在这个例子中,我们将 “label”、“icon” 和“primary”属性传递给 <Button> 组件。但在子组件中,并没有定义这些属性,因此它们是不会传递到 <button> 标签上的。如果我们想要访问传递给组件的这些属性,我们就可以在子组件中使用 $attrs:

// Button 组件的模板

<template>

<button v-bind="$attrs" :class="classes">

<span v-if="icon" :class="iconClasses"></span>

{{ label }}

</button>

</template>

// 在这里直接使用了 $attrs 传递的所有属性和方法

通过这样的处理,我们的Button组件就可以正常接收并使用父组件传递的属性和方法了。

3. $listeners属性

使用 $attrs 可以很方便的将组件的所有属性和方法绑定到子组件上,但是如果我们需要将子组件的事件传递到父组件,该怎么办呢?这时,我们就可以使用 $listeners属性了。

3.1 使用方式

在Vue中使用 $listeners 的方式也是非常简单的,只需要在父组件中,将“$listeners” 作为参数传递给子组件即可。然后在子组件中,使用 $listeners 将事件绑定到组件上。

// 子组件 MyComponent

<template>

<div @click="$listeners['click']">

<Button v-bind="$attrs" />

</div>

</template>

在这个例子中,我们使用了 $listeners 属性将“click”事件绑定到了 <div> 标签上。通过这样的处理,我们的Button组件就可以正常触发 “click” 事件,并将其传递到父组件中。

3.2 案例分析

接下来,我们看一个简单的例子,通过使用 $attrs 和 $listeners 属性,来实现父组件和子组件之间的通讯:

// 父组件

<template>

<div>

<MyComponent @click="handleClick"></MyComponent>

</div>

</template>

<script>

import MyComponent from './MyComponent'

export default {

name: 'ParentComponent',

components: {

MyComponent

},

methods: {

handleClick () {

console.log('click from MyComponent')

}

}

}

</script>

在这个例子中,我们在父组件中定义了一个方法 “handleClick”。这个方法将会在 <MyComponent> 组件触发 “click” 事件时进行调用。

// 子组件 MyComponent

<template>

<div @click="$listeners['click']">

<button :class="classes">

{{ label }}

</button>

</div>

</template>

<script>

export default {

name: 'MyComponent',

props: {

label: {

type: String,

default: ''

}

},

computed: {

classes () {

return 'my-component'

}

}

}

</script>

在 <MyComponent> 组件中,我们使用了 $listeners 属性将组件上的 “click” 事件绑定到了 <div> 标签上。这样当 <div> 被点击时,事件将会触发,并将它传递给父组件。

4. 总结

在Vue中使用 $attrs 和 $listeners 属性可以很方便的实现组件之间的通讯。使用 $attrs 可以访问到所有从父组件中传递过来的属性和方法,而使用 $listeners 则可以将子组件的事件传递到父组件中。这两个API的使用非常灵活,可以根据具体的需求进行自由的组合。对于 Vue 组件通讯,除了此外还有很多其它的方法,这里只是简单的介绍了Vue中使用$attrs和$listeners进行组件通讯。祝大家在Vue的开发中能够游刃有余。