全网最通俗易懂的vue透传

概念:

Vue的透传是指在Vue组件中,使用特定的语法将父组件传递的属性或事件直接传递给子组件,实现了通过父组件传递数据或事件,再传递给子组件的功能。(传递给一个组件,却没有被该组件声明为 propsemits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。)

在vue2中,透传可以通过v-bind="$attrs"和v-on="$listeners"指令来实现。v-bind指令可以将父组件的属性直接绑定到子组件上,而v-on指令可以将父组件的事件直接绑定到子组件上。

而vue3中,将v-bind和v-on进行了合并,我们只需要v-bind="$attrs"这一个指令就能把父组件的属性和方法都绑定到子组件上。

作用:透传能给我们组件复用或者二次封装第三方库带来极大的便捷。

下面让我们来看看vue3和vue2的透传的实际用法吧:

Vue3:

如何使用透传

父组件:直接传属性和方法

<template>
  <div>
    <ChildComponent name="John Doe" age="25" @handleData="handleData"/>
  </div>
</template>
 
<script setup>
import ChildComponent from './ChildComponent.vue';

const handleData = () => {
   // ...逻辑
}
</script>

子组件:使用 $attrs 或 useAttrs() 接收属性和方法

<template>
  <div>
    <!-- 在模板的表达式中直接用 $attrs 访问到 -->
    <p>{{ $attrs.name }}</p>
    <!-- 也可以用 useAttrs() 访问到 -->
    <p>{{ attrs.age }}</p>
    <button @click="$attrs.handleData">按钮1</button>
    <button @click="onChange">按钮2</button>
  </div>
</template>
 
<script setup>
  // 在js里 使用 useAttrs() API 来访问到
  import { useAttrs } from 'vue'
 
  const attrs = useAttrs()
  console.log(attrs)
  const onChange = () => {
      attrs.handleData()
  }
</script>

透传注意点

当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。多个根节点的组件没有自动 attribute 透传行为。如果 $attrs 没有被显式绑定,或者没有被使用,将会抛出一个运行时警告。

把上面的子组件改一下,多一个div根节点:

下面是被透传的子组件

<template>
  <div>
    <h2>{{ name }}</h2>
  </div>
  // 多了一个根节点(Vue3是支持多个根节点的)
  <div></div>
</template>
 
<script setup>
  defineProps({
    name: String
  })
</script>

此时报错表示:vue不知道要将 attribute 透传到哪里。

解决办法:如果 $attrs 被显式绑定 或者 使用,或者 两者同时出现,则不会有警告。

下面是解决后的代码:

<template>
  <!-- 显示绑定 -->
  <div v-bind="$attrs">
    <h2>{{ name }}</h2>
  </div>
  <div>
    <!-- 使用 -->
    <p>{{ $attrs.age }}</p>
  </div>
</template>
 
<script setup>
  defineProps({
    name: String
  })
</script>

$attrs和显示绑定都能访问到属性和方法,但是它们的有些使用场景还是略有不同的,下面举个简单的栗子

修改一下父组件,添加一个id属性,子组件不变:

<template>
  <div>
    <ChildComponent id="custom-layout" name="John Doe" :age="25" />
  </div>
</template>
 
<script setup>
  import ChildComponent from './ChildComponent.vue'
</script>

这里可以看到的是,父组件传递下来的id属性,自动添加到了使用 v-bind 显式绑定的元素上了。而没有显式绑定的元素,是不会获得透传过来的id的

关闭透传

我们在使用vue2的透传的时候,可以设置inheritAttrs这个属性为false,来禁用透传,那么在Vue3中我们如何禁用透传呢?

其实从 3.3 开始我们就可以直接在 <script setup> 中使用 defineOptions来禁用透传。

我们需要明白,禁用透传只是禁用了自动透传,我们仍然可以通过显式$attrs访问到透传的属性和方法

<script setup>
defineOptions({
  inheritAttrs: false
})
// ...setup 逻辑
</script>

Vue2

vue2版本里,透传的属性可以使用this.$attrs获取到。在父级给组件绑定的事件可以用this.$listeners获取到。但是在vue3版本中,父组件透传来的属性都放在了$attrs里面,使用useAttrs()可以获取所有透传的属性和方法。

如何使用透传

$attrs:包含父作用域里除 class 和 style 除外的非 props 属性集合。通过 this.$attrs 获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过 v-bind="$attrs"

$listeners:包含父作用域里 .native 除外的监听事件集合。如果还要继续传给子组件内部的其他组件,就可以通过 v-on="$listeners"

// Parent.vue
<template>
    <Child :name="name" age="28" @output='handlePrint'></Child>
</template
import Child from './child.vue'
export default{
    data(){
        return {
            name:"独求求败"
        }
    },
    components:{
        Child,
    },
    methods:{
        handlePrint(){
            console.log('name',this.name)
        }
    }
}
// Child.vue
<template>
    // 继续传给孙子组件
    <sun-child v-bind="$attrs" @bind="$listeners"></sun-child>
</template>
import SunChild from './SunChild.vue'
export default{
    components:{
        SunChild,
    },
    mounted(){
        console.log(this.$attrs)
        //{ name:"独求求败", age:28 }
    },
}
// sun-child.vue
<template>
    // 孙子组件
    <button @click="onClick">打印</button>
    //<button @click="$listeners.output">打印</button>  也可以直接调用父组件方法
</template>
export default{
    methods:{
        onClick(){
            this.$listeners.output()
        }
    }
}

vue2关闭透传

为了关闭透传,你可以在子组件中设置inheritAttrs:false

 <script>
 export default {
   inheritAttrs: false, // 禁用
    data(){
        return { ... }
    },
    methods:{ ... }
 };
 </script>
  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零凌林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值