文章目录
- 透传属性
- 如何禁止“透传属性和事件”
- 多根节点设置透传
- 访问“透传属性和事件”
- `$props`、`$attrs`和`$listeners`的使用详解
透传属性
- 透传属性和事件并没有在子组件中用
props
和emits
声明 - 透传属性和事件最常见的如
@click
和class
、id
、style
- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上;如果根元素已有
class
或style
属性,它会自动合并
如何禁止“透传属性和事件”
- 在选项式 API 中,你可以在组件选项中设置
inheritAttrs: false
来阻止; - 在组合式 API 的
<script setup>
中,你需要一个额外的<script>
块来书写inheritAttrs: false
选项声明来禁止
<script>
export default {inheritAttrs: false // 阻止自动透传给唯一的根组件
}
</script>
多根节点设置透传
多根节点的组件并没有自动“透传属性和事件”的行为,由于Vue不确定要将“透传属性和事件”透传到哪里,所以我们需要v-bind="$attrs"
来显式绑定,否则将会抛出一个运行时警告。
<button class="chip" v-bind="$attrs">普通纸片</button>
访问“透传属性和事件”
在选项式 API 中,我们可通过this.$attrs
来访问“透传属性和事件”
在组合式 API 中的<script setup>
中引入useAttrs()
来访问一个组件的“透传属性和事件”
<script setup>
import { useAttrs } from 'vue';// 透传的属性和事件对象
let attrs = useAttrs()// 在 JS 中访问透传的属性和事件
function showAttrs() {console.log(attrs)console.log(attrs.class)console.log(attrs.title)console.log(attrs.style)attrs.onClick()
}
</script><template><button class="chip" v-bind="attrs"></button><h6>{{ attrs }}</h6><ul><li>{{ attrs.title }}</li><li>{{ attrs.class }}</li><li>{{ attrs.style }}</li></ul><button @click="attrs.onClick()">执行透传的事件</button><button @click="showAttrs">在 JS 中访问透传的属性和事件</button>
</template><style>
.chip {border: none;background-color: rgb(231, 231, 231);padding: 8px 15px;margin: 10px;
}.rounded {border-radius: 100px;
}
</style>
$props
、$attrs
和$listeners
的使用详解
$props
:当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问。$attrs
:包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。$listeners
:包含了父作用域中(不含.native
修饰器的)v-on
事件监听器。他可以通过v-on="listeners"
传入内部组件
1、父组件
<template><div><div>父亲组件</div><Child:foo="foo":zoo="zoo"@handle="handleFun"></Child></div>
</template><script>
import Child from './Child.vue'
export default {components: { Child },data() {return {foo: 'foo',zoo: 'zoo'}},methods: {// 传递事件handleFun(value) {this.zoo = valueconsole.log('孙子组件发生了点击事件,我收到了')}}
}
</script>
2.儿子组件(Child.vue)
在儿子组件中给孙子组件添加v-bind="$attrs"
,这样孙子组件才能接收到数据。
$attrs
是从父组件传过来的,且儿子组件未通过props接收的数据,例如zoo
<template><div class='child-view'><p>儿子组件--{{$props.foo}}与{{foo}}内容一样</p><GrandChild v-bind="$attrs" v-on="$listeners"></GrandChild></div>
</template><script>
import GrandChild from './GrandChild.vue'
export default {// 继承所有父组件的内容inheritAttrs: true,components: { GrandChild },props: ['foo'],data() {return {}}
}
</script>
3.孙子组件(GrandChild.vue)
在孙子组件中一定要使用props接收从父组件传递过来的数据
<template><div class='grand-child-view'><p>孙子组件</p><p>传给孙子组件的数据:{{zoo}}</p><button @click="testFun">点我触发事件</button></div>
</template><script>
export default {// 不想继承所有父组件的内容,同时也不在组件根元素dom上显示属性inheritAttrs: false,// 在本组件中需要接收从父组件传递过来的数据,注意props里的参数名称不能改变,必须和父组件传递过来的是一样的props: ['zoo'],methods: {testFun() {this.$emit('handle', '123')}}
}
</script>