Vue组件二次封装的一些实用技巧总结

目录
  • 前言
  • 透传 Attribute
  • 透传 slot
    • 普通slot
    • 动态插槽名
    • 作用域插槽
  • 封装组件存在的问题
    • 组件实例属性和方法的调用
  • 总结

前言

在开发Vue项目我们一般使用第三方UI组件库进行开发,如element-plus, @arco-design/web-Vue, naive-ui等, 但是这些组件提供的接口并不一定满足我们的需求,这时我们可以通过对组件库组件的二次封装,来满足我们特殊的需求。

对于封装组件有一个大原则就是我们应该尽量保持原有组件的接口,除了我们需要封装的功能外,我们不应该改变原有组件的接口,即保持原有组件提供的接口如props,events,slots等不变。

为了实现这一原则我们就需要将新组件的接口与旧组件的接口一一对应, 当然我们可以通过在新组件中一一声明对应的接口来实现(或者只实现我们目前需要用到的接口)但这种办法虽然简单但看起来却极其很繁琐, 有没有一种方法可以实现props,events,slots的自动透传呢?

透传 Attribute

我们可以使用一个没有参数的 v-bind来实现props,events的透传, 它会将一个对象的所有属性都作为 attribute 应用到目标元素或组件上, 这在官方文档中有着详细介绍。

<BaseButton v-bind="$attrs"/>

其中$attrs包含组件可以透传属性的对象, 透传属性包括props,events, class,style,id等。(不包含接收组件显式声明的 props、emits以及slots )

如下,是一个封装el-input的默认可清空的的组件,由于我们已经在defineProps声明过clearable, 所以此时我们需要显性传递clearable属性

<template>
  <div class="my-input">
    {{ label }}
    <el-input v-bind="$attrs" :clearable="clearable"></el-input>
  </div>
</template>

<script setup>
defineProps({
  label: String,
  clearable: {
    type: Boolean,
    default: true,
  },
});
</script>

如果我们不希望透传某些属性比如class, 我们可以通过useAttrs来实现

<template>
  <div class="my-input">
    {{ label }}
    <el-input v-bind="filteredAttrs" :clearable="clearable"></el-input>
  </div>
</template>

<script setup>
import { computed, useAttrs } from 'Vue';

defineProps({
  label: String,
  clearable: {
    type: Boolean,
    default: true,
  },
});

const attrs = useAttrs();
const filteredAttrs = computed(() => {
  return { ...attrs, class: undefined };
});
</script>

上述封装的组件还有个缺点, 就是我们将无法使用el-input本身提供的slot,下面我们就来实现一个可以透传 slot的组件

透传 slot

slot可以通过下面这种方式透传的

<!-- 在组件中创建新的对应名称的插槽 -->
<template #slotName>
<!-- 在插槽内部使用对应名称的插槽 -->
    <slot name="slotName" />
</template>

普通slot

如果透传的slot比较少,我们可以通过在封装组件内部定义并使用插槽<template v-slot:slotName><slot name="slotName" /></template>来透传插槽

<template #slotName>
    <slot name="slotName" />
</template>

动态插槽名

如果需要透传的slot不固定或者较多,我们可以通过动态插槽名称透传

<template #[slotName] v-for="(slot, slotName) in $slots" >
    <slot :name="slotName" />
</template>

如下是一个透传的slot的el-input组件

<template>
  <div class="my-input">
    {{ label }}
    <el-input v-bind="$attrs" :clearable="clearable">
      <template #[slotName] v-for="(slot, slotName) in $slots">
          <slot :name="slotName" />
      </template>
    </el-input>
  </div>
</template>

<script setup>
defineProps({
  label: String,
  clearable: {
    type: Boolean,
    default: true,
  },
});
</script>

作用域插槽

如果需要封装组件使用了作用域插槽,我们可以通过<template v-slot:slotName="slotProps"><slot name="slotName" v-bind="slotProps"/></template>来透传作用域插槽插槽。

<template #[slotName]="slotProps" v-for="(slot, slotName) in $slots" >
    <slot :name="slotName" v-bind="slotProps"/>
</template>

封装组件存在的问题

组件实例属性和方法的调用

封装后的组件我们无法按照之前的情况调用组件实例中的属性和方法,比如BaseButton有focus方法,在封装之前我们可以通过下面这种方式调用

// 调用BaseButton的组件父组件
// <BaseButton ref="button">
const button = ref();
button.value.focus()

对于封装后的组件,由于此时button指向我们的MyButton,并不指向BaseButton的实例,所以我们需要在包装的组件中声明并暴露BaseButton事例

//我们封装的组件
// MyButton.Vue
// <BaseButton ref="button">
const button = ref();

注意如果我们使用 <script setup>,是没办法访问实例中的属性的,详情参考vuejs.org/api/sfc-scr…

此时可以通过defineExpose显式公开ref属性

// 我们封装的组件
// MyButton.Vue
// <BaseButton ref="button">
const button = ref();
defineExpose({
  button
});

然后在父组件中我就可以通过实例链式调用封装的组件了

// <MyButton ref="button">
const button = ref();
button.value.button.focus()

总结

到此这篇关于Vue组件二次封装的一些实用技巧的文章就介绍到这了,更多相关Vue组件二次封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue axios基于常见业务场景的二次封装的实现

    axios axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 在前端框架中的应用也是特别广泛,不管是vue还是react,都有很多项目用axios作为网络请求库. 我在最近的几个项目中都有使用axios,并基于axios根据常见的业务场景封装了一个通用的request服务. npm: $ npm install axios bower: $ bower install axios Using cdn: <script src="https:/

  • 详解vue axios二次封装

    这段时间告诉项目需要,用到了vue. 刚开始搭框架的时候用的是vue-resource后面看到官方推荐axios就换过来了 顺便封装了一下 定义公共参数与引入组件: import axios from 'axios' import qs from 'qs' axios.interceptors.request.use(config => { //显示loading return config }, error => { return Promise.reject(error) }) axios

  • vue中axios的二次封装实例讲解

    我们做项目时,虽然axios也可以直接拿来用,但是对接口比较零散,不太好进行维护,也会产生大量的重复代码,所以我在这对axios进行了统一接口处理 第一步,先在src中的公共文件夹中如utils里新建request.js文件 import axios from 'axios' import router from '@/router/routers' import { Notification, MessageBox } from 'element-ui' import store from '

  • vue axios 二次封装的示例代码

    这段时间告诉项目需要,用到了vue. 刚开始搭框架的时候用的是vue-resource后面看到官方推荐axios就换过来了 顺便封装了一下 //引入axios import axios from 'axios' let cancel ,promiseArr = {} const CancelToken = axios.CancelToken; //请求拦截器 axios.interceptors.request.use(config => { //发起请求时,取消掉当前正在进行的相同请求 if

  • Vue二次封装axios为插件使用详解

    照例先贴上 axios的 gitHub 地址 不管用什么方式获取数据,对于一个项目来说,代码一定要利于维护其次是一定要写的优美,因此加上一层封装是必要的 vuejs2.0 已经不再维护 vue-resource,vuejs2.0 已经使用了 axios,这也是为什么我会转到 axios 的主要原因,废话不多说: 基本的封装要求: 统一 url 配置 统一 api 请求 request (请求)拦截器,例如:带上token等,设置请求头 response (响应)拦截器,例如:统一错误处理,页面重

  • Vue组件二次封装的一些实用技巧总结

    目录 前言 透传 Attribute 透传 slot 普通slot 动态插槽名 作用域插槽 封装组件存在的问题 组件实例属性和方法的调用 总结 前言 在开发Vue项目我们一般使用第三方UI组件库进行开发,如element-plus, @arco-design/web-Vue, naive-ui等, 但是这些组件提供的接口并不一定满足我们的需求,这时我们可以通过对组件库组件的二次封装,来满足我们特殊的需求. 对于封装组件有一个大原则就是我们应该尽量保持原有组件的接口,除了我们需要封装的功能外,我们

  • Element使用el-table组件二次封装

    目录 前言 一.安装引入 二.封装功能 三.样式覆盖 四.使用组件 前言 在vue开发中使用element-ui的el-table时一般都需要进行封装以便于复用,提高开发效率,减少重复代码,这篇博客对el-table进行简单的二次封装: 一.安装引入 Element官方文档 npm安装element-ui: npm i element-ui -S 可以看文档按需引入,这里为了方便直接全局引入了: import Vue from 'vue' import App from './App.vue'

  • vue axios二次封装的详细解析

    axios的二次封装 视频讲解 npm i axios //下载axios 首先创建两个文件夹在src目录下:api和config 先在config文件夹下建立一个index.js:具体代码如下: export default{ baseUrl:{ dev: "http://localhost:8082/mhy", //开发环境 pro: "http://xxx.xx.xx.xx:8082/mhy", //上线环境 } } 当然我这里是因为我主要写后端springb

  • elementui实现预览图片组件二次封装

    起因 在elementui组件库中,el-image组件有个预览图片功能,比较简洁,但是和图片绑定在一起,我们只想要一个单纯的预览组件,传递一个图片,通过事件方式,显示大图 分析 通过查看elementui的代码,发现在image(el-image组件)目录中里面有一个image-viewer组件, el-image组件的预览功能也是通过这一个组件实现的,只是官方没有把这个组件单独暴露出来 这里就比较简单了,我们可以使用手动导入组件的方式,引入image-viewer组件 image-viewe

  • vue elementui二次封装el-table带插槽问题

    目录 elementui二次封装el-table带插槽 element-ui table组件的二次封装(插槽的形式) 1.外层table组件封装 2.内层table组件代码 elementui二次封装el-table带插槽 子组件table封装 html部分 <template>   <div     v-loading="loading">     <el-table       ref="tableData"       :stri

  • vue2.0 自定义组件的方法(vue组件的封装)

    一.前言 之前的博客聊过 vue2.0和react的技术选型:聊过vue的axios封装和vuex使用.今天简单聊聊 vue 组件的封装. vue 的ui框架现在是很多的,但是鉴于移动设备的复杂性,兼容性问题突出.像 Mint-UI 等说实话很不错了,但是坑也是不少,而且很多功能也是仅凭这些实现不了,这需要我们去封装自己的可复用组件 二.封装组件的步骤 1. 建立组件的模板,先把架子搭起来,写写样式,考虑你的组件的基本逻辑. os:思考1小时,码码10分钟,程序猿的准则. 2. 准备组件的好数据

  • vue-cli对element-ui组件进行二次封装的实战记录

    目录 为什么要element对进行二次封装? 如何对element对进行二次封装? 总结 为什么要element对进行二次封装? 1.element-ui组件的部分样式不满足当前项目的需求. element-ui组件的样式是固定的,比如我们常用的那些组件,table,button,icon,tab等等.当我们需要的样式和element组件有偏差的时候,我们可以通过针对element组件进行二次封装,然后通过Vue.component()方法,定义到全局,来解决我们当前的项目需求. 2.eleme

随机推荐