Vue学习:18-透传属性和事件

一、如何透传属性和事件

透传是一个通讯层面的概念,指的是在通讯中不管传输的业务内容如何,只负责将传输的内容由源地址传输到目的地址,而不对业务数据内容做任何改变。

在vue上来讲,我们的组件存在深层嵌套的场景,例如:A -> B -> C

父组件在使用子组件的时候,如何“透传属性和事件”给子组件呢?

1、透传属性和事件并没有在子组件中用props和emits声明

2、透传属性和事件最常见的如@click和class、id、style

3、当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上;如果根元素已有class或style属性,它会自动合并

实例:

子组件Chip.vue

<script setup>

</script>

<template>
  <!-- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上
  如果根元素已有class或style属性,它会自动合并 -->
  <button class="chip" style="box-shadow: 0 0 8px grey;">
    普通纸片
  </button>
</template>

<style>
  .chip {
    border: none;
    background-color: rgb(231,231,231);
    padding: 8px 15px;
  }

  .rounded {
    border-radius: 100px;
  }

</style>

父组件App.vue

<script setup>
  import ChipVue from './components/Chip.vue'

  function say() {
    alert('Hello')
  }

</script>

<!-- 视图区域(view) -->
<template>
  <!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
  <!-- 透传的事件(click)在子组件中并没有在emits声明 -->

  <ChipVue
    class="rounded"
    style="border: 1px solid blue;"
    title="纸片"
    @click="say"
  />

</template>

渲染结果:

<button class="chip rounded" title="纸片" style="box-shadow: grey 0px 0px 8px; border: 1px solid blue;"> 普通纸片 </button>

二、如何禁止透传属性和事件

当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上,那怎么阻止呢?

1、在选项式 API 中,你可以在组件选项中设置inheritAttrs: false来阻止;

2、在组合式 API 的"<script setup>"中,你需要一个额外的"<script>"块来书写inheritAttrs: false选项声明来禁止;从 3.3 开始你也可以直接在"<script setup>"中使用 defineOptions

实例:

Chip.vue

<script setup>
  defineOptions({
    inheritAttrs: false  //阻止自动透传给唯一的根组件
  })
</script>

<template>
  <!-- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上
  如果根元素已有class或style属性,它会自动合并 -->
  <button class="chip" style="box-shadow: 0 0 8px grey;">
    普通纸片
  </button>
</template>

<style>
  .chip {
    border: none;
    background-color: rgb(231,231,231);
    padding: 8px 15px;
  }

  .rounded {
    border-radius: 100px;
  }

</style>

App.vue

<script setup>
  import ChipVue from './components/Chip.vue'

  function say() {
    alert('Hello')
  }

</script>

<!-- 视图区域(view) -->
<template>
  <!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
  <!-- 透传的事件(click)在子组件中并没有在emits声明 -->

  <ChipVue
    class="rounded"
    style="border: 1px solid blue;"
    title="纸片"
    @click="say"
  />

</template>

三、多根元素的“透传属性和事件”

多根节点的组件并没有自动“透传属性和事件”的行为,由于Vue不确定要将“透传属性和事件”透传到哪里,所以我们需要v-bind="$attrs"来显式绑定,否则将会抛出一个运行时警告。

实例:

Chip.vue

​
<script setup>

</script>

<template>
  <!-- 多根节点的组件并没有自动“透传属性和事件”的行为 -->
  <button class="chip">
    普通纸片
  </button>
  <hr>
  <button class="chip" v-bind="$attrs">
    普通纸片
  </button>
  <hr>
  <button class="chip" v-bind="$attrs">
    普通纸片
  </button>
</template>

<style>
  .chip {
    border: none;
    background-color: rgb(231,231,231);
    padding: 8px 15px;
  }

  .rounded {
    border-radius: 100px;
  }

</style>

​

App.vue

<script setup>
  import ChipVue from './components/Chip.vue'

  function say() {
    alert('Hello')
  }

</script>

<!-- 视图区域(view) -->
<template>
  <!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
  <!-- 透传的事件(click)在子组件中并没有在emits声明 -->

  <ChipVue
    class="rounded"
    style="border: 1px solid blue;"
    title="纸片"
    @click="say"
  />

</template>

四、访问“透传属性和事件”

1、在选项式 API 中,我们可通过this.$attrs来访问“透传属性和事件”

2、在组合式 API 中的"<script setup>"中引入useAttrs()来访问一个组件的“透传属性和事件”

实例:

Chip.vue

<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>
  <hr>
  
  <h6>{{ attrs }}</h6>

  <ul>
    <li>{{ attrs.title }}</li>
    <li>{{ attrs.class }}</li>
    <li>{{ attrs.style }}</li>
  </ul>

  <button @click="attrs.onClick()">执行透传的事件</button>
  <hr>

  <button @click="showAttrs">在JS中访问透传的属性和事件</button>

</template>

<style>
  .chip {
    border: none;
    background-color: rgb(231,231,231);
    padding: 8px 15px;
  }

  .rounded {
    border-radius: 100px;
  }

</style>

App.vue

<script setup>
  import ChipVue from './components/Chip.vue'

  function say() {
    alert('Hello')
  }

</script>

<!-- 视图区域(view) -->
<template>
  <!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
  <!-- 透传的事件(click)在子组件中并没有在emits声明 -->

  <ChipVue
    class="rounded"
    style="border: 1px solid blue;"
    title="纸片"
    @click="say"
  />

</template>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值