在父组件给子组件的按钮绑定点击事件时,并不是给按钮绑定了,而是给子组件的根元素绑定了事件
比如,给子组件的按钮绑定一个点击事件,这个时候点击子组件的其他部份也会执行此事件(红色为自组件区域,点击红色区域也会执行)
因为,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类型