写点什么

Vue3 - $attrs 的几种用法(1 个或多个根元素、Options API 和 Composition API)

作者:德育处主任
  • 2022 年 6 月 27 日
  • 本文字数:2938 字

    阅读完需:约 10 分钟

Vue3 - $attrs 的几种用法(1个或多个根元素、Options API 和 Composition API)

本文简介

点赞 + 关注 + 收藏 = 学会了


使用 Vue 开发时,肯定会接触到 组件 的概念,无可避免的也会接触到 组件通讯 的概念。


组件通讯的方式有很多种,我在 《Vue3 过10种组件通讯方式》 一文中粗略罗列了 Vue3 常用的组件通讯方法。


Vue 2 中除了 $attrs 外,还有 $listenersVue 3$listeners 合并到 $attrs 里了。


而本文的重点是讲解在 Vue 3 中如何使用 $attrs


本文使用的 Vue 版本是 3.2.25


本文关键字:


  • $attrs:在 template 中使用(单一根元素和多个根元素的情况)

  • useAttrs:在 js 中使用(1 种 Options API 和 2 种 Composition API 的用法)


attrs 的作用

在讲解 attrs 之前,你首先要知道组件常用的通讯方式:propsemits ,这两个是 Vue 组件通讯的基础,本文不会讲解。


简单来说, attrs 主要接收没在 props 里定义,但父组件又传过来的属性。


举个例子


<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue --><template> <div> {{ msg }} - {{ $attrs }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



可以看到,在子组件中,msg 使用了 props 接收,所以 {{ msg }} 可以直接输出 props 里接收的内容。


而没在 props 里接收的内容,全部都放到了 $attrs 里,并且存在一个对象里面。


接下来将展开讲解不同情况下 attrs 的使用方法。


attrs 在 template 中的用法

在前面简单的例子里其实已经大概知道 attrstemplate 的用法。但 Vue3template 不再要求只有一个根元素了。所以 attrstemplate 中分 2 种情况使用。


只有 1 个根元素的情况下

只有 1 个根元素的情况下,子组件中,没被 props 接收的属性,都会绑定在根元素上。


<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue --><template> <div> {{ msg }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



可以看到,没被 props 接收的属性都被绑定到根元素上了。


style 里传入的样式也被执行,文字变成红色了。


如果此时我们想在页面输出 name 的值,可以在子组件中这样操作


<!-- 这里省略 父组件代码 ...... -->


<!-- 子组件 ChildCom.vue --><template> <div> {{ $attrs.name }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



使用 $attrs.xxx ,这里的 xxx 是对应的属性名。


有 2 个根元素的情况下

当子组件有 2 个根元素时,没被 props 接收的属性不会绑定到子组件的元素上。


<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue --><template> <div> {{ msg }} </div> <div> {{ msg }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



此时连父组件传入是 style 样式都不生效了。


如果我们此时希望第二个元素绑定所有没被 props 接收的属性,可以使用 v-bind="$attrs" 的方法实现


<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue --><template> <div> {{ msg }} </div> <div v-bind="$attrs"> {{ msg }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



注意第二个元素,使用了 v-bind="$attrs" 绑定了所有没被 props 接收的属性。


如果只希望绑定部分属性,可以单独写


<!-- 这里省略 父组件代码 ...... -->


<!-- 子组件 ChildCom.vue --><template> <div> {{ msg }} </div> <div :style="$attrs.style"> {{ msg }} </div></template>
<script setup>defineProps({ msg: { type: String }})</script>
复制代码



attrs 在 js 中的用法

除了在 template 中可以访问到 $attrs ,在 JS 中也可以访问到。


vue 3 其实是兼容大部分 Vue 2 语法的,也就是 Options API 。而 attrsOptions APiComposition Api 中的使用方法会稍微有一丢丢区别。而 Composition API 又分为 Vue 3.2 前的语法和 3.2 后的语法。


接下来将分开讨论这 3 种情况。


Options API

<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue 暂不关注 template 部分 --><script>export default { props: { msg: { type: String } }, mounted() { console.log(this.$attrs) }}</script>
复制代码



此时控制台会输出没被 props 接收的属性。


Composition API 3.0 的语法

<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue 暂不关注 template 部分 --><script>export default { props: { msg: { type: String } }, setup(props, context) { console.log('props: ', props) console.log('attrs: ', context.attrs) }}</script>
复制代码



Vue 3.2 前的写法,需要在 setup 方法里接收 2 个参数,而 attrs 就在 context 参数里。


Composition API 3.2 的语法

Vue 3.2 后的语法,可以在 <script> 标签上添加 setup 属性。所以在代码里就不需要再调用 setup 方法了。


在这种情况下,props 成了默认的全局方法,而 attrs 则需要另外引入。


<!-- 父组件 ParentCom.vue --><template>  <ChildCom    msg="雷猴"    data="123"    name="鲨鱼辣椒"    style="color: red;"  /></template>
<script setup>import ChildCom from './ChildCom.vue'</script>


<!-- 子组件 ChildCom.vue 暂不关注 template 部分 --><script setup>import { useAttrs } from 'vue'
const props = defineProps({ msg: { type: String }})
const attrs = useAttrs()
console.log('props: ', props)console.log('attrs: ', attrs)</script>
复制代码



需要引入 vue 中的 useAttrs ,在调用 useAttrs 后会返回当前未被 props 接收的属性。


重点是以下两句。


import { useAttrs } from 'vue'const attrs = useAttrs()
复制代码


之后在 js 代码里就可以使用 attrs.xxx 获取对应的属性值了。

发布于: 刚刚阅读数: 3
用户头像

反派 2019.03.19 加入

用键盘绣花

评论

发布
暂无评论
Vue3 - $attrs 的几种用法(1个或多个根元素、Options API 和 Composition API)_Vue_德育处主任_InfoQ写作社区