Skip to content

Vue 组件透传-Attributes

起因:

由于业务需求,需要做一个搜索栏,input+table,搜索商品后下拉展开表格,选中商品后隐藏,并添加事件返回商品的数据

开始

我的想法,分为两个组件,一个是商品数据表格的组件,一个是搜索框+下拉的组件,设A组件为搜索框组件, B组件为表格组件

js
 //B组件,他有一个emit事件,用于给父组件传递数据
<table onCellClick={(e)=>emit('clickRow',e)}></table>
//A组件,引入B组件
improt B from './B'
import {defineComponent} from 'vue'
export default defineComponent({
  setup(props,{emit,atts}){
  
    return ()=>(
      <div>
        <input/>
          //下拉部分,这时候写一个事件用来接收子组件的传参,再把它传递给A组件的父组件
        <div>
          <B onClickRow={(e)=>{emit('clickRow',e)}}/>
        </div>
      </div>
    )
  }
})
//页面
import A from './A'
const handleClickRow = (e)=>{
  //这个事件我们就能接到B组件传递过来的数据
}
//jsx部分
<PageView>
  <A onClickRow={handleClickRow}/>
<PageView>

截至到这我写的代码看起来也没什么问题

但是!!! 我再A组件加了attrs

js
//A组件
improt B from './B'
import {defineComponent} from 'vue'
export default defineComponent({
  setup(props,{emit,attrs}){
  
    return ()=>(
      <div>
        <input/>
          //下拉部分,这时候写一个事件用来接收子组件的传参,再把它传递给A组件的父组件
        <div>
          <B 
            {...attrs} //这里是关键,这样就会导致clickRow事件触发两次
            onClickRow={(e)=>{emit('clickRow',e)}}
           />
        </div>
      </div>
    )
  }
})

原因

根据阅读vue官方文档得知 “透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。 由于我没有再组件中生命emits 所以导致函数透传,从而执行两边, 解决办法//两种

js
//A组件
improt B from './B'
import {defineComponent} from 'vue'
export default defineComponent({
  emits:['clickRow'],//第一种:声明emits
  setup(props,{emit,attrs}){
  
    return ()=>(
      <div>
        <input/>
          //下拉部分,这时候写一个事件用来接收子组件的传参,再把它传递给A组件的父组件
        <div>
          <B 
            {...attrs} //这里是关键,这样就会导致clickRow事件触发两次
            //onClickRow={(e)=>{emit('clickRow',e)}} 第二种:直接删除这里的事件,由父级穿透至子集
           />
        </div>
      </div>
    )
  }
})

有趣的知识增加了