在父组件给子组件的按钮绑定点击事件时,并不是给按钮绑定了,而是给子组件的根元素绑定了事件
比如,给子组件的按钮绑定一个点击事件,这个时候点击子组件的其他部份也会执行此事件(红色为自组件区域,点击红色区域也会执行)
因为,Vu3默认所有的属性都绑定到根元素上了
父组件,给子组件Button绑定事件属性
template>
<div>
<Button @click="onClick"
@focus="onClick"
@mouseover="onClick"
size="small"
>button</Button>
</div>
</template>
<script lang="ts">
import Button from '../lib/Button.vue'
export default {
components: {
Button
},
setup() {
const onClick = () => {
console.log('hi')
}
return {
onClick
}
}
}
</script>
子组件,父元素绑定的事件,都在div上
<template>
<div>
<button>
<slot />
</button>
</div>
</template>
他会自动把方法绑定到子组件的根元素,所以点击子组件的任何一个部分都会触发执行该方法。
那我只想点击某一部分才会触发事件,该怎么办呢?
第一步:不让根元素继承属性
在子组件写 inheritAttrs:false 继承属性改为false
<template>
<div>
<button >
<slot />
</button>
</div>
</template>
<script lang="ts">
export default {
+ inheritAttrs:false
}
</script>
第二步:让事件绑定到某部分
$attrs是父组件传递过来的所有属性
<template>
<div>
+ <button v-bind="$attrs">
<slot />
</button>
</div>
</template>
<script lang="ts">
export default {
inheritAttrs:false
}
</script>
扩展:
把所有的事件分成两部分,分别给不同的元素 在子组件使用剩余操作符 ...
<template>
<div :size="size">
<button v-bind="rest">
<slot />
</button>
</div>
</template>
<script lang="ts">
export default {
inheritAttrs: false,
setup(props, context) {
//size作为一个方法,剩下的用rest包括了
const {
size,
...rest //剩下的就是rest
} = context.attrs
return {
size,
rest
}
}
}
</script>
props和attrs的区别
- props要先声明,才能取值,attrs不用声明
- props不包含事件,attrs包含
- props没有什么声明的属性,会跑到attrs里
- props支持string以为的类型,attrs只有string类型