当前位置: 首页 > news >正文

【组件封装-优化】vue+element plus:二次封装select组件,实现下拉列表有分页、自定义是否可搜索的一系列功能

第一章 前言

1.1 实现效果

1.2 需求及准备

  • 开发前言:由于公司针对下拉框都是直接使用组件,并且下拉数据都不是特别多。而小编的需求是接口直接返回了2000多条数据,一个原因是数据特别庞大,请求接口需要花费特别长时间;另一个是2000调数据我们也不好一次性都展示在下拉框,体验感不是很好;于是通过小编的研究与优化,与后端约定将数据改成提供分页接口,并且小编也利用element-plus组件提供了两个方法:一个是直接使用无限滚动组件,触底掉接口(Infinite Scroll);另一个是再二次封装一个分页的下拉框,经过最终讨论,确定方案用后者(原因:扩展性更高,且后续其他项目可通用
  • 核心需求:因下拉框中的数据过多,所以需要使用分页的方式来实现。
  • 工具:element-plus

设计 | Element Plus

 Infinite Scroll 无限滚动 | Element Plus

  • v-bind="$attrs" 理解

【vue】v-bind=“$attrs“理解与使用-CSDN博客

  • 插槽

【vue】slot插槽:灵活内容分发的艺术-CSDN博客 

第二章 源代码

2.1 组件开发

  • 实现思路
  1. 基于element-plus开发,必须需要两个组件el-selec和组件el-pagination
  2. 需要能继承到上面两个组件的所有属性,减少任务量
  3. 支持是否可搜索(可用props控制显隐或者插槽等);是否可分页(由于小编的需求是支持分页,所以小编的思路是默认就有,大家可根据需求添加配置项或者做成插槽);
  4. 分页与下拉框数据联动;
  5. 要学会利用v-model对某些必要数据双向绑定方便我们对数据的处理
  6. 除了以上必要功能,还有就是样式了,也要稍微处理
  • 注意:小编在封装时会已经使用一些element组件的配置项,如果父组件在使用时用了同名的属性,则会覆盖;大家需要留意一下
  • 组件原代码如下
<!-- 组件名:ui-select -->

<script setup>
// 接收一些必要的配置项
const props = defineProps({
  
  val: {
    type: String,
    default: ''
  },
  // 选择框宽度
  width: {
    type: String,
    default: ''
  },
  // options弹窗宽度
  optionsWidth: {
    type: String,
    default: ''
  },
  // 配置项
  options: {
    type: Array,
    default: () => [
      {
        id: 1,
        label: 'Option1',
        value: 'Option1'
      }
    ]
  },
  // 分页数据
  pageData: {
    type: Object,
    default: () => {
      return {
        pageNo: 1,
        pageSize: 10,
        total: 20
      }
    }
  }
})

const emit = defineEmits(['update:val', 'update:pageData', 'pageChange'])
const selectVal = ref('')
const page = ref({})
onMounted(() => {
  const { val, pageData } = props
  // element组件是支持select的双向绑定的,所以小编单独用了一个新的变量处理
  selectVal.value = val
  // 分页数据
  page.value = pageData
})
const selectChange = (item) => {
  // select选中值的更新
  emit('update:val', item)
}
const pageChange = () => {
  // 分页变化更新分页数据
  emit('update:pageData', page.value)
。// 同时emit一个方法,让父组件可以利用这个方法执行某些操作
  emit('pageChange')
}
</script>

<template>
  <div>
    <!-- v-bind="$attrs"小编前面有提到,就是完整的拿到父组件传的参数,从而不需要props再接一层 -->
    <!-- select 和 pagination都设置v-bind="$attrs",继承两个组件的配置项 -->
    <!-- 注意:小编在封装的时候已经使用了一些element组件的配置项,如果父组件在使用时用了同名的属性,则会覆盖 -->
    <el-select
      v-model="selectVal"
      v-bind="$attrs"
      :style="{
        width: width || '100%'
      }"
      @change="selectChange"
      class="custom_select"
    >
      <!-- 最小宽度是分页撑的宽度 -->
      <div
        :style="{
          width: optionsWidth || '100%'
        }"
        class="options_content"
      >
        <!-- 这里使用到了插槽,主要是扩展我们二次封装的select组件是否可搜索或者再前面需要加什么内容…… -->
        <slot name="header" class="header"></slot>
        <!-- element的select的options配置项 -->
        <div class="options_main">
          <el-option
            v-for="item in options"
            :key="item.id"
            :label="item.label"
            :value="item.value"
          />
        </div>
        <!-- 分页组件 -->
        <!-- 注意这里也有v-bind="$attrs"使用 -->
        <el-pagination
          v-model:current-page="page.pageNo"
          :page-size="page.pageSize"
          layout="prev, pager, next"
          :total="page.total"
          @current-change="pageChange"
          v-bind="$attrs"
          class="pagination_page"
        />
      </div>
    </el-select>
  </div>
</template>

// 下面就是我们针对二次封装组件的一些其他样式
<style lang="scss" scoped>
.pagination_page {
  width: 100%;
  padding: 10px 20px 10px 20px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.options_main {
  // element select组件的弹窗是在根下的,不好直接设置弹窗的高,只能限制内容了
  height: 140px;
  margin: 0 20px;
  overflow: auto;
}
::-webkit-scrollbar {
  width: 5px;
}
</style>

2.2 组件使用

<!--
说明:
    1、placeholder、clearable是el-select组件的属性,
    由于我们使用了$attrs,所以再uiselect直接使用也是可以生效的;
    同理background是el-pagination的也是可以的
     2、小编使用了header插槽为分页组件提供了可搜索的功能
     3、要留意这些字段的含义
-->
<!--
解释一下字段:
aiForm.description: 下拉框绑定的值
scopePage: 分页数据对象
    {
      pageNo: 1,
      pageSize: 10,
      total: 100
    }
decOptions: 下拉数据
scopeSearchForm.description: 搜索关键字
-->
<UiSelect
  v-model:val="aiForm.description"
  v-model:pageData="scopePage"
  placeholder="行业表诉"
  class="ai_search-border margin_right_bottom"
  width="150px"
  :options="decOptions"
  background
  @pageChange="getDescriptions"
  clearable
>
  <template #header>
    <div class="scope_header">
      <el-input
        v-model="scopeSearchForm.description"
        class="ai_search-border margin_right_bottom"
        style="border-color: #dcdfe6"
        placeholder="请输入关键字"
        clearable
      >
        <template #append>
          <el-icon style="cursor: pointer" @click="getDescriptions"><Search /></el-icon>
        </template>
      </el-input>
    </div>
  </template>
</UiSelect>

相关文章:

  • Apache Airflow开源程序是一个以编程方式编写、计划和监控工作流程的平台
  • 苹果内购支付 Java 接口
  • 蓝桥杯:日期统计
  • 基于STM32、HAL库的CH224K 快充协议芯片简介及驱动程序设计
  • AI平台如何实现推理?数算岛是一个开源的AI平台(主要用于管理和调度分布式AI训练和推理任务。)
  • 【Java设计模式】第7章 建造者模式讲解
  • class与构造函数
  • Podman配置
  • AI在未来会不会代替人工???
  • Redis中AOF的实现方式和AOF重写
  • 运动规划实战案例 | 基于可视图的路径规划算法(附ROS C++/Python仿真)
  • 动态列表的数据渲染、新增、编辑等功能开发及数据处理
  • MySQL安装与基础配置(Windows版以及linux版)
  • RISCV GCC 4 后端优化
  • 国产数据库 YanshanDB 和 达梦数据库 的选型
  • PHP MySQL 创建数据库
  • 4S店汽车维修保养管理系统 (源码+lw+部署文档+讲解),源码可白嫖!
  • Spring MVC 操作会话属性详解(@SessionAttributes 与 @SessionAttribute)
  • 第二十五章:Python-pyecharts 库实现 3D 地图绘制
  • css单位
  • 政府网站建设是/关于友谊的连接
  • 著名b2b网站有哪些/免费域名邮箱
  • 专家一对一免费咨询/seo搜索引擎优化书籍
  • 我要网站建设/seo整站优化吧
  • 设计素材网站能挣钱吗/谷歌外贸
  • 优秀设计师个人网站/免费建站免费推广的网站