Vue3 Composition API优雅封装第三方组件实例

 更新时间:2022年07月11日 16:04:27   作者:HexOr  
这篇文章主要为大家介绍了Vue3 Composition API优雅封装第三方组件实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言✨

对于第三方组件,如何在保持第三方组件原有功能(属性props、事件events、插槽slots、方法methods)的基础上,优雅地进行功能的扩展了?

Element Plusel-input为例:

很有可能你以前是这样玩的,封装一个MyInput组件,把要使用的属性props、事件events和插槽slots、方法methods根据自己的需要再写一遍:

// MyInput.vue
<template>
  <div class="my-input">
    <el-input v-model="inputVal" :clearable="clearable" @clear="clear">
    <template #prefix>
      <slot name="prefix"></slot>
    </template>
      <template #suffix>
      <slot name="suffix"></slot>
    </template>
    </el-input>
  </div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  clearable: {
    type: Boolean,
    default: false
  }
})
const emits = defineEmits(['update:modelValue', 'clear'])
const inputVal = computed({
  get: () => props.modelValue,
  set: (val) => {
    emits('update:modelValue', val)
  }
})
const clear = () => {
  emits('clear')
}
</script>

可过一段时间后,需求变更,又要在MyInput组件上添加el-input组件的其它功能,可el-input组件总共有20个多属性,5个事件,4个插槽,那该怎么办呢,难道一个个传进去,这样不仅繁琐而且可读性差。

在Vue2中,我们可以这样处理,点击此处查看 封装Vue第三方组件

此文诣在帮助大家做一个知识的迁移,探究如何使用Vue3 CompositionAPI优雅地封装第三方组件~

一、对于第三方组件的属性props、事件events

在Vue2中

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

而在Vue3中

  • $attrs:包含了父作用域中不作为组件 props 或自定义事件的 attribute 绑定和事件(包括 class 和 style和自定义事件),同时可以通过 v-bind="$attrs" 传入内部组件。
  • $listeners 对象在 Vue 3 中已被移除。事件监听器现在是 $attrs 的一部分。
  • 在 <script setup>中辅助函数useAttrs可以获取到$attrs。
//MyInput.vue 
<template>
  <div class="my-input">
    <el-input v-bind="attrs"></el-input>
  </div>
</template>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>

当然,这样还不够。光这样写,我们绑定的属性(包括 class 和 style)同时会在根元素(上面的例子是class="my-input"的Dom节点)上起作用。要阻止这个默认行为,我们需要设置inheritAttrs为false。

下面我们来看看Vue3文档对inheritAttrs的解释

默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。

于是,我们对于第三方组件的属性props、事件events处理,可以写成如下代码:

// MyInput.vue 
<template>
  <div class="my-input">
    <el-input v-bind="attrs"></el-input>
  </div>
</template>
<script>
export default {
  name: 'MyInput',
  inheritAttrs: false
}
</script>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>

二、对于第三方组件的插槽slots

Vue3中

  • $slots:我们可以通过其拿到父组件传入的插槽
  • Vue3中移除了$scopedSlots,所有插槽都通过 $slots 作为函数暴露
  • 在 <script setup>中辅助函数useSlots可以获取到$slots。

基于以上几点,如果我们对于第三方组件的封装没有增加额外的插槽,且第三方组件的插槽处于同一个dom节点之中,我们也有一种取巧的封装方式😎, 通过遍历$slots拿到插槽的name,动态添加子组件的插槽:

//MyInput.vue 
<template>
  <div class="my-input">
    <el-input v-bind="attrs">
      <template v-for="k in Object.keys(slots)" #[k] :key="k">
        <slot :name="k"></slot>
      </template>
    </el-input>
  </div>
</template>
<script>
export default {
  name: 'MyInput',
  inheritAttrs: false
}
</script>
<script setup>
import { useAttrs, useSlots } from 'vue'
const attrs = useAttrs()
const slots = useSlots()
</script>

如果不满足以上条件的话,咱还得老老实实在子组件中手动添加需要的第三方组件的插槽~

三、对于第三方组件的方法methods

对于第三方组件的方法,我们通过ref来实现。首先在MyInput组件中的el-input组件上添加一个ref="elInputRef"属性,然后通过defineExpose把elInputRef暴露出去给父组件调用。

子组件:MyInput.vue

// MyInput.vue 
<template>
  <div class="my-input">
    <el-input v-bind="attrs" ref="elInputRef">
      <template v-for="k in Object.keys(slots)" #[k] :key="k">
        <slot :name="k"></slot>
      </template>
    </el-input>
  </div>
</template>
<script>
export default {
  name: 'MyInput',
  inheritAttrs: false
}
</script>
<script setup>
import { useAttrs, useSlots } from 'vue'
const attrs = useAttrs()
const slots = useSlots()
const elInputRef = ref(null)
defineExpose({
  elInputRef  // <script setup>的组件里的属性默认是关闭的,需通过defineExpose暴露出去才能被调用
})
</script>

父页面:Index.vue的调用代码如下:

// Index.vue 
<template>
  <my-input v-model='input' ref="myInput">
    <template #prefix>姓名</template>
  </my-input>
</template>
<script setup>
import MyInput from './components/MyInput.vue'
import { ref, onMounted } from 'vue'
const input = ref('')
const myInput = ref(null) // 组件实例
onMounted(()=> {
  myInput.value.elInputRef.focus() // 初始化时调用elInputRef实例的focus方法
})
</script>

以上就是Vue3 Composition API优雅封装第三方组件实例的详细内容,更多关于Vue3 Composition API封装第三方组件的资料请关注脚本之家其它相关文章!

相关文章

  • UniApp中实现类似锚点定位滚动效果

    UniApp中实现类似锚点定位滚动效果

    一个uniapp小程序的项目,我们需要实现一个非常实用的功能——类似于锚点定位的交互效果,即在首页中有多个tab(分类标签),每个tab对应着不同的模块,当用户点击某个分类的tab时,需要流畅地滚动到对应的内容位置,提供更好的用户体验,
    2023-10-10
  • vue 组件的封装之基于axios的ajax请求方法

    vue 组件的封装之基于axios的ajax请求方法

    今天小编就为大家分享一篇vue 组件的封装之基于axios的ajax请求方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Vue项目刷新后h5样式失效的原因及解决方案

    Vue项目刷新后h5样式失效的原因及解决方案

    今天遇到一个bug,有一个Element的message组件,用它做的一个进度条,它是写在一个页面上,并且是用js控制dom元素的,web端一切正常,但是,H5页面刷新的时候它样式加载不出来了,所以本文主要介绍了Vue项目刷新后h5样式失效的原因及解决方案,需要的朋友可以参考下
    2024-10-10
  • 解决vue-cli-service不是内部或外部命令也不是可运行的程序或批处理文件的报错问题

    解决vue-cli-service不是内部或外部命令也不是可运行的程序或批处理文件的报错问题

    这篇文章主要介绍了解决vue-cli-service不是内部或外部命令也不是可运行的程序或批处理文件的报错问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • 浅谈Vue灰度发布新功能的使用

    浅谈Vue灰度发布新功能的使用

    本文主要介绍了浅谈Vue灰度发布新功能的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 一篇文章教会你部署vue项目到docker

    一篇文章教会你部署vue项目到docker

    在前端开发中,部署项目是我们经常发生的事情,下面这篇文章主要给大家介绍了关于部署vue项目到docker的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04
  • vue上传文件formData上传的解决全流程

    vue上传文件formData上传的解决全流程

    这篇文章主要介绍了vue上传文件formData上传的解决全流程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • ElementUI时间选择器限制选择范围disabledData的使用

    ElementUI时间选择器限制选择范围disabledData的使用

    本文主要介绍了ElementUI时间选择器限制选择范围disabledData的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 详解Vue的键盘事件

    详解Vue的键盘事件

    这篇文章主要为大家介绍了Vue的键盘事件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • vue中在vuex的actions中请求数据实例

    vue中在vuex的actions中请求数据实例

    今天小编就为大家分享一篇vue中在vuex的actions中请求数据实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11

最新评论