记录--Vue中的$attrs你真的会用吗?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
先来看一个业务需求:
项目经常会遇到产品经理要求你做某组件一样的功能,还要在它的基础上增加东西。如何只用少量代码高效的二次封装组件呢?
例如我要做一个element-ui的input组件进行封装,以下是封装要求:
- 对el-input组件增加某些定制功能
- 调整el-input的原有css样式
- 封装后不得更改原有el-input的所有功能
文章最后会给出element-ui的input组件二次封装的示例。
先来介绍一下attrs吧
在 Vue2 中,attr 是指组件接收的 HTML 特性(attribute),通过 props 的方式传递给子组件。而在 Vue3 中,attr 的概念被引入了 Composition API 中,并且被用于管理各种配置项。
下面介绍一些 attr 的使用技巧:
Vue2 中使用 attr
- 使用 v-bind指令绑定 HTML 属性
在 Vue2 中,如果想将父组件传递的 HTML 属性传递给子组件进行使用,可以在子组件中通过 props 接收参数,并使用 v-bind 指令将其绑定到子组件的 HTML 元素上。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <template> <div class = "demo-component" :style= "styleObject" >{{ message }}</div> </template> <script> export default { name: "DemoComponent" , props: { message: String, styleObject: Object, }, }; </script> |
在父组件中使用该组件时,可以通过 v-bind 指令将 HTML 特性传递给子组件:
1 2 3 | <template> <demo-component message= "Hello, world!" :style- object = "{ color: 'red' }" ></demo-component> </template> |
- 使用 $attrs 对象传递所有未被 props 所接收的特性
在 Vue2 中,可以通过 $attrs 对象获取父组件传递给子组件但未被 props 所接收的特性,从而实现组件复用和扩展的目的。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <template> <div class = "demo-component" :style= "styleObject" v-bind= "$attrs" >{{ message }}</div> </template> <script> export default { name: "DemoComponent" , props: { message: String, styleObject: Object, }, }; </script> |
在父组件使用该组件时,可以像平常传递普通的 HTML 特性一样,同时还可以传递一些自定义的特性:
1 2 3 4 5 6 7 | <template> <demo-component message= "Hello, world!" :style- object = "{ color: 'red' }" custom-attribute= "something" ></demo-component> </template> |
在子组件中,可以通过 this.$attrs 属性获取父组件传递给子组件但未被 props 所接收的特性:
1 | console.log( this .$attrs.customAttribute); // 输出:something |
Vue3 中使用 attr
在 Vue3 中,可以通过 setup 函数中的第二个参数 context 来访问该组件的配置选项,其中包括了所有未被 props 所接收的特性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <template> <div class = "demo-component" :style= "styleObject" v-bind= "$attrs" >{{ message }}</div> </template> <script> export default { name: "DemoComponent" , props: { message: String, styleObject: Object, }, setup(props, context) { console.log(context.attrs.customAttribute); // 输出:something }, }; </script> |
在 setup 函数中,通过 context.attrs 获取父组件传递给子组件但未被 props 所接收的特性。
除了 $attrs
,Vue3 中还引入了 $props
对象,它是一个由 props 组成的响应式对象,在组件内部通过解构赋值可以快速地访问 props 的属性值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <template> <div class = "demo-component" :style= "styleObject" >{{ message }}</div> </template> <script> export default { name: "DemoComponent" , props: { message: String, styleObject: Object, }, setup(props) { const { message, styleObject } = props; console.log(message, styleObject); // 输出:Hello, world! { color: 'red' } }, }; </script> |
在 setup 函数中,通过解构赋值可以快速地访问 props 的属性值。
利用 $attrs
和 $listeners
可以在二次封装 element-ui 组件时非常方便地传递组件属性和事件。
示例代码
下面以 el-input 组件为例,演示一下vue2中如何高效地二次封装 element-ui 组件,从而达到只用少量代码在原有组件上升级的效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <template> <el-input v-bind= "$attrs" v- on = "$listeners" : class = "{ 'is-invalid': isError }" > <template v- if = "isError" #append> <i class = "el-input__icon el-icon-circle-close" ></i> </template> </el-input> </template> <script> export default { name: "MyInput" , inheritAttrs: false , props: { isError: Boolean, // 是否显示错误提示 }, }; </script> <style scoped lang= "scss" > //这是写自己的样式内容 </style> |
解释一下上面代码的内容吧:
-
使用
v-bind="$attrs"
将父级组件所有的未被 props 所接收的特性绑定到 el-input 组件上。 -
使用
v-on="$listeners"
将父级组件传递给当前组件的所有事件监听器绑定到 el-input 组件上。 -
在模板中可以很方便地使用 isError 属性来扩展组件,并且不需要在父组件中再次定义。
需要注意的是,由于 element-ui 组件本身也包含了一些默认的属性和事件,因此需要在组件中设置 inheritAttrs: false
,以避免传递 element-ui 组件自带的属性和事件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构