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

作者:红尘炼心 时间:2023-07-02 16:37:03 

引言

在封装第三方组件中,经常会遇到一个问题,如何通过封装的组件去使用第三方组件的Attributes(属性)、Events(自定义事件)、Methods(方法)、Slots(插槽)。

当然这个问题并不是难以解决,用普通方法解决难免陷入繁琐重复的工作中,而且封装的组件代码可读性也不高。

本专栏将介绍三种技巧来使用第三方组件的Attributes(属性)、Events(自定义事件)、Slots(插槽),至于使用第三方组件的Methods(方法)的技巧还待优化。

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

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

封装一个elementUI的el-input输入框组件称为myInput,若要在myInput组件上添加一个disabled属性来禁用输入框,要如何实现呢?一般同学会这么做

//myInput.vue
<template>
 <div>
   <el-input v-model="inputVal" :disabled="disabled"></el-input>
 </div>
</template>
<script>
export default {
 props: {
   value: {
     type: String,
     default: '',
   },
   disabled: {
     type: Boolean,
     default: false
   }
 },
 computed: {
   inputVal: {
     get() {
       return this.value;
     },
     set(val) {
       this.$emit('input', val);
     }
   }
 }
}
</script>

过一段时间后又要在myInput组件上添加el-input组件的其它属性,el-input组件总共有27个多属性,那该怎么呢,难道一个个用prop传进去,这样不仅繁琐而且可读性差,可以用$attrs一步到位,先来看一下attrs的官方定义。

$attrs: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件

//myInput.vue
<template>
 <div>
   <el-input v-model="input" v-bind="$attrs"></el-input>
 </div>
</template>

这还不够,还得把inheritAttrs选项设置为false,为什么呢,来看一下inheritAttrs选项的官方定义就明白了。

默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会&ldquo;回退&rdquo;且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。

通过设置 inheritAttrsfalse,这些默认行为将会被去掉。而通过 $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。注意:这个选项不影响 class 和 style 绑定。

简单来说,把inheritAttrs设置为false,避免给myInput组件设置的属性被添加到myInput组件的根元素div上。

//myInput.vue
<template>
 <div>
   <el-input v-model="input" v-bind="$attrs"></el-input>
 </div>
</template>
<script>
export default {
 inheritAttrs: false,
 props: {
   value: {
     type: String,
     default: '',
   },
 },
 computed: {
   inputVal: {
     get() {
       return this.value;
     },
     set(val) {
       this.$emit('input', val);
     }
   }
 }
}
</script>

这样设置后,在myInput组件上就可以直接使用el-input组件的属性,不管后续el-input组件再增加了多少个属性。

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

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

若在myIpput组件上使用el-input组件上自定义的事件呢,可能你的第一反应是this.$emit

//myInput.vue
<template>
 <div>
   <el-input v-model="input" v-bind="$attrs" @blur="blur"></el-input>
 </div>
</template>
<script>
export default {
 inheritAttrs: false,
 props: {
   value: {
     type: String,
     default: '',
   },
 },
 computed: {
   inputVal: {
     get() {
       return this.value;
     },
     set(val) {
       this.$emit('input', val);
     }
   }
 },
 methods: {
   blur() {
     this.$emit('blur')
   }
 }
}
</script>
<myInput v-model="value" @blur="handleBlur"></myInput>

el-input组件有4个自定义事件,还不算多,假如遇到自定义事件更多的第三方组件,要怎么办,难道一个一个添加进去,这样会增加一堆非必要的methods,其实可以用$listeners一步到位,先来看一下$listeners的官方定义。

$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件 * 。它可以通过 v-on="$listeners" 传入内部组件。

//myInput.vue
<template>
 <div>
   <el-input v-model="input" v-bind="$attrs" v-on="$listeners"></el-input>
 </div>
</template>

那么在myInput组件中给el-input组件添加上v-on="$listeners",就可以在myInput组件上使用el-input组件自定义的事件。

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

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

若在myIpput组件上使用el-input组件上定义的插槽呢?这个没有多少取巧的方法,第三方组件定义多少个插槽,在封装的时候都得用slot标签暴露出去。比如暴露el-input组件中的prefix插槽,代码如下所示:

//myInput.vue
<template>
 <div>
   <el-input v-model="input" v-bind="$attrs" @blur="blur">
     <template #prepend>
       <slot name="prepend"></slot>
     </template>
   </el-input>
 </div>
</template>

四、使用第三方组件的方法

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

利用ref来实现,首先在myInput组件中的el-input组件上添加一个ref="elInput"属性,

//myInput.vue
<template>
 <div>
   <el-input ref="elInput></el-input>
 </div>
</template>
<script>
export default {
 mounted(){
    this.elInput = this.$refs.elInput;
 }
}
</script>

这里要注意父子组件的mounted的执行时机,因为一般el-input组件是全局引入的,相当同步引入组件,此时el-input组件的mounted会比myInput组件的mounted先执行,所以可以在myInput组件的mounted中把this.$refs.elInput赋值到myInput组件的this的一个属性上。

myInput组件如何使用el-input组件的方法分两种情况,跟myInput组件的引入有关系。

假如myInput组件是同步引入的

<template>
 <div>
   <myInput ref="myInput"></myInput>
 </div>
</template>
<script>
import myInput from './myInput.vue';
export default {
 data() {
   return {
   }
 },
 components: {
   myInput,
 },
 mounted() {
   //调用el-input组件的focus方法
   this.$refs.myInput.elInput.focus();
 }
}
</script>

假如myInput组件是异步引入的

<template>
 <div>
   <myInput ref="myInput"></myInput>
 </div>
</template>
<script>
export default {
 data() {
   return {
   }
 },
 components: {
   myInput: () => import('./myInput.vue')
 },
 mounted() {
   //调用el-input组件的focus方法
   setTimeout(() => {
      this.$refs.myInput.elInput.focus();
   })
 }
}
</script>

来源:https://juejin.cn/post/6943534547501858824#heading-4

标签:Vue,第三方,组件封装,前端框架
0
投稿

猜你喜欢

  • 原生js实现瀑布流效果

    2023-09-04 07:11:02
  • Python爬取数据保存为Json格式的代码示例

    2022-10-13 17:11:36
  • sql server 2008 忘记sa密码的解决方法

    2024-01-26 22:48:16
  • 从算法入手讲解SQL Server的典型示例

    2008-12-18 14:51:00
  • python 对excel交互工具的使用详情

    2021-11-25 19:10:06
  • 介绍Python中的一些高级编程技巧

    2022-09-22 19:23:15
  • Python编程中的反模式实例分析

    2021-02-01 09:54:26
  • Mac上Python使用ffmpeg完美解决方案(避坑必看!)

    2023-10-07 23:03:10
  • Python中用sleep()方法操作时间的教程

    2023-11-27 10:45:28
  • python压缩和解压缩模块之zlib的用法

    2023-09-19 08:32:07
  • PyTorch中的参数类torch.nn.Parameter()详解

    2021-09-07 19:06:30
  • golang bad file descriptor问题的解决方法

    2024-05-09 09:31:42
  • 推荐系统MostPopular算法的Python实现方式

    2022-04-21 14:44:24
  • Vue+Java+Base64实现条码解析的示例

    2024-05-02 17:08:27
  • 使用Python对Dicom文件进行读取与写入的实现

    2022-05-30 12:18:27
  • 如何利用Python实现简单C++程序范围分析

    2022-07-19 00:32:48
  • python框架Django实战商城项目之工程搭建过程图文详解

    2022-12-16 16:25:57
  • SQL Server 2016正式版安装配置过程图文详解

    2024-01-26 05:27:15
  • sqlserver中delete、update中使用表别名和oracle的区别

    2024-01-19 15:21:49
  • 浅谈python中set使用

    2023-05-31 10:57:41
  • asp之家 网络编程 m.aspxhome.com