[前端] 前端框架之封装Vue第三方组件三个技巧

1704 0
Honkers 2022-10-21 16:06:56 | 显示全部楼层 |阅读模式
目录

    引言一、使用第三方组件的属性二、使用第三方组件的自定义事件三、使用第三方组件的插槽四、使用第三方组件的方法


引言

在封装第三方组件中,经常会遇到一个问题,如何通过封装的组件去使用第三方组件的Attributes(属性)、Events(自定义事件)、Methods(方法)、Slots(插槽)。
当然这个问题并不是难以解决,用普通方法解决难免陷入繁琐重复的工作中,而且封装的组件代码可读性也不高。
本专栏将介绍三种技巧来使用第三方组件的Attributes(属性)、Events(自定义事件)、Slots(插槽),至于使用第三方组件的Methods(方法)的技巧还待优化。

一、使用第三方组件的属性



封装一个elementUI的el-input输入框组件称为myInput,若要在myInput组件上添加一个disabled属性来禁用输入框,要如何实现呢?一般同学会这么做
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="inputVal" :disabled="disabled"></el-input>
  5.   </div>
  6. </template>
  7. <script>
  8. export default {
  9.   props: {
  10.     value: {
  11.       type: String,
  12.       default: '',
  13.     },
  14.     disabled: {
  15.       type: Boolean,
  16.       default: false
  17.     }
  18.   },
  19.   computed: {
  20.     inputVal: {
  21.       get() {
  22.         return this.value;
  23.       },
  24.       set(val) {
  25.         this.$emit('input', val);
  26.       }
  27.     }
  28.   }
  29. }
  30. </script>
复制代码
过一段时间后又要在myInput组件上添加el-input组件的其它属性,el-input组件总共有27个多属性,那该怎么呢,难道一个个用prop传进去,这样不仅繁琐而且可读性差,可以用$attrs一步到位,先来看一下attrs的官方定义。
$attrs: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="input" v-bind="$attrs"></el-input>
  5.   </div>
  6. </template>
复制代码
这还不够,还得把inheritAttrs选项设置为false,为什么呢,来看一下inheritAttrs选项的官方定义就明白了。
默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。
通过设置 inheritAttrs 为 false,这些默认行为将会被去掉。而通过 $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。注意:这个选项不影响 class 和 style 绑定。
简单来说,把inheritAttrs设置为false,避免给myInput组件设置的属性被添加到myInput组件的根元素div上。
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="input" v-bind="$attrs"></el-input>
  5.   </div>
  6. </template>
  7. <script>
  8. export default {
  9.   inheritAttrs: false,
  10.   props: {
  11.     value: {
  12.       type: String,
  13.       default: '',
  14.     },
  15.   },
  16.   computed: {
  17.     inputVal: {
  18.       get() {
  19.         return this.value;
  20.       },
  21.       set(val) {
  22.         this.$emit('input', val);
  23.       }
  24.     }
  25.   }
  26. }
  27. </script>
复制代码
这样设置后,在myInput组件上就可以直接使用el-input组件的属性,不管后续el-input组件再增加了多少个属性。

二、使用第三方组件的自定义事件



若在myIpput组件上使用el-input组件上自定义的事件呢,可能你的第一反应是this.$emit。
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="input" v-bind="$attrs" @blur="blur"></el-input>
  5.   </div>
  6. </template>
  7. <script>
  8. export default {
  9.   inheritAttrs: false,
  10.   props: {
  11.     value: {
  12.       type: String,
  13.       default: '',
  14.     },
  15.   },
  16.   computed: {
  17.     inputVal: {
  18.       get() {
  19.         return this.value;
  20.       },
  21.       set(val) {
  22.         this.$emit('input', val);
  23.       }
  24.     }
  25.   },
  26.   methods: {
  27.     blur() {
  28.       this.$emit('blur')
  29.     }
  30.   }
  31. }
  32. </script>
复制代码
  1. <myInput v-model="value" @blur="handleBlur"></myInput>
复制代码
el-input组件有4个自定义事件,还不算多,假如遇到自定义事件更多的第三方组件,要怎么办,难道一个一个添加进去,这样会增加一堆非必要的methods,其实可以用$listeners一步到位,先来看一下$listeners的官方定义。
$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件。
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="input" v-bind="$attrs" v-on="$listeners"></el-input>
  5.   </div>
  6. </template>
复制代码
那么在myInput组件中给el-input组件添加上v-on="$listeners",就可以在myInput组件上使用el-input组件自定义的事件。

三、使用第三方组件的插槽



若在myIpput组件上使用el-input组件上定义的插槽呢?这个没有多少取巧的方法,第三方组件定义多少个插槽,在封装的时候都得用slot标签暴露出去。比如暴露el-input组件中的prefix插槽,代码如下所示:
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input v-model="input" v-bind="$attrs" @blur="blur">
  5.       <template #prepend>
  6.         <slot name="prepend"></slot>
  7.       </template>
  8.     </el-input>
  9.   </div>
  10. </template>
复制代码
四、使用第三方组件的方法



利用ref来实现,首先在myInput组件中的el-input组件上添加一个ref="elInput"属性,
  1. //myInput.vue
  2. <template>
  3.   <div>
  4.     <el-input ref="elInput></el-input>
  5.   </div>
  6. </template>
  7. <script>
  8. export default {
  9.   mounted(){
  10.      this.elInput = this.$refs.elInput;
  11.   }
  12. }
  13. </script>
复制代码
这里要注意父子组件的mounted的执行时机,因为一般el-input组件是全局引入的,相当同步引入组件,此时el-input组件的mounted会比myInput组件的mounted先执行,所以可以在myInput组件的mounted中把this.$refs.elInput赋值到myInput组件的this的一个属性上。
myInput组件如何使用el-input组件的方法分两种情况,跟myInput组件的引入有关系。
假如myInput组件是同步引入的
  1. <template>
  2.   <div>
  3.     <myInput ref="myInput"></myInput>
  4.   </div>
  5. </template>
  6. <script>
  7. import myInput from './myInput.vue';
  8. export default {
  9.   data() {
  10.     return {
  11.     }
  12.   },
  13.   components: {
  14.     myInput,
  15.   },
  16.   mounted() {
  17.     //调用el-input组件的focus方法
  18.     this.$refs.myInput.elInput.focus();
  19.   }
  20. }
  21. </script>
复制代码
假如myInput组件是异步引入的
  1. <template>
  2.   <div>
  3.     <myInput ref="myInput"></myInput>
  4.   </div>
  5. </template>
  6. <script>
  7. export default {
  8.   data() {
  9.     return {
  10.     }
  11.   },
  12.   components: {
  13.     myInput: () => import('./myInput.vue')
  14.   },
  15.   mounted() {
  16.     //调用el-input组件的focus方法
  17.     setTimeout(() => {
  18.        this.$refs.myInput.elInput.focus();
  19.     })
  20.   }
  21. }
  22. </script>
复制代码
以上就是前端框架封装Vue第三方组件三个技巧的详细内容,更多关于封装Vue第三方组件的资料请关注中国红客联盟其它相关文章!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4008
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行