首页 > 其他分享 >基于vue+element ui实现下拉表格选择组件

基于vue+element ui实现下拉表格选择组件

时间:2024-03-25 16:45:05浏览次数:28  
标签:vue default defaultValue value defaultProps item ui element row


一:前言

本文属于转载;

image



二:正文


1:示例展示

单选

image

多选


image


index.vue

<template>
  <el-select
    ref="select"
    v-model="defaultValue"
    :title="isNeedTitle ? getTitle() : null"
    :clearable="false"
    :multiple="multiple"
    :filterable="false"
    :placeholder="placeholder"
    :disabled="disabled"
    :value-key="defaultProps.value"
    :filter-method="filterMethod"
    @remove-tag="removeTag"
    @visible-change="visibleChange"
    @clear="clear"
  >
    <template #empty>
      <div
        class="sc-table-select__table"
        :style="{ width: tableWidth + 'px' }"
        v-loading="loading"
      >
        <div class="sc-table-select__header">
          <slot name="header" :form="formData" :submit="formSubmit"></slot>
        </div>
        <el-table
          ref="table"
          style="font-size: 16px"
          :data="tableData"
          :height="245"
          :highlight-current-row="!multiple"
          @row-click="rowClick"
          @select="select"
          @select-all="selectAll"
          reserve-selection
        >
          <el-table-column
            v-if="multiple"
            type="selection"
            width="45"
          ></el-table-column>
          <el-table-column v-else type="index" width="45">
            <template #default="scope"
              ><span>{{
                scope.$index + (currentPage - 1) * pageSize + 1
              }}</span></template
            >
          </el-table-column>
          <slot></slot>
        </el-table>
        <div class="sc-table-select__page">
          <el-pagination
            small
            background
            layout="prev, pager, next"
            :total="total"
            :page-size="pageSize"
            :current-page.sync="currentPage"
            @current-change="currentChange"
          ></el-pagination>
        </div>
      </div>
    </template>
  </el-select>
</template>

<script>
import config from './tableSelect'

export default {
  props: {
    value: { type: [String, Number, Array, Object], default: '' },
    // Not Request,all Table Data
    tabularData: { type: Array, default: () => [] },
    // 是否是需要请求
    isNeedRequest: { type: Boolean, default: false },
    // 数据value是否以逗号隔开
    isDataJoin: { type: Boolean, default: true },
    // 请求url
    requestUrl: { type: Function, default: Function },
    params: { type: Object, default: () => {} },
    placeholder: { type: String, default: '请选择' },
    multiple: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    tableWidth: { type: Number, default: 400 },
    mode: { type: String, default: 'popover' },
    // 合并默认配置
    props: { type: Object, default: () => {} },
    // 合并默认配置
    isNeedTitle: { type: Boolean, default: false },
    // 是否需要数据过滤
    isNeedDataFilter: { type: Boolean, default: false },
    filterParam: { type: Object, default: () => {} }
  },
  data() {
    return {
      loading: false,
      keyword: null,
      defaultValue: [],
      tableData: [],
      pageSize: config.pageSize,
      total: 0,
      currentPage: 1,
      defaultProps: {
        label: config.props.label,
        value: config.props.value,
        page: config.request.page,
        pageSize: config.request.pageSize,
        keyword: config.request.keyword
      },
      formData: {},
      // Not Request,Need Table Data
      tabularMap: {}
    }
  },
  watch: {
    value: {
      handler() {
        this.$nextTick(() => {
          if (!this.isDataJoin) {
            if (this.multiple) {
              this.defaultValue = this.value || []
            } else {
              this.defaultValue = this.value
            }
          } else {
            // 多选
            if (this.multiple) {
              this.defaultValue = Array.isArray(this.value) ? this.value : this.value ? this.value.split(',') : []
              this.defaultValue = (this.defaultValue || []).map(item => {
                return { [this.defaultProps.value]: item }
              })
            } else {
              this.defaultValue = this.value ? { [this.defaultProps.value]: this.value } : ''
            }
          }
          this.findLabel()
        })
      },
      deep: true,
      immediate: true
    },
    tabularData: {
      handler(val) {
        if (this.isNeedRequest) return
        this.$nextTick(() => {
          val.forEach(item => {
            this.tabularMap[item[this.defaultProps.value]] = item[this.defaultProps.label]
          })
          this.findLabel()
        })
      },
      deep: true,
      immediate: true
    }
  },
  created() {
    // bug,在这不能使用nextTick
    this.defaultProps = Object.assign(this.defaultProps, this.props)
  },
  methods: {
    // 表格显示隐藏回调
    visibleChange(visible) {
      if (visible) {
        this.currentPage = 1
        this.keyword = null
        this.formData = {}
        this.getData()
      } else {
        this.findLabel()
      }
    },
    // 获取表格数据
    async getData() {
      if (this.isNeedRequest) {
        this.initTable()
      } else {
        this.initTabularData()
      }
    },
    initTabularData() {
      // this.tableData = deepClone(this.tabularData)
      this.total = this.tabularData.length
      this.tableData = this.tabularData.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize)
      if (Object.keys(this.formData).length > 0) {
        const input = this.formData[this.defaultProps.label]
        if (input) {
          const arr = this.tabularData.filter((item) => {
            return String(item[this.defaultProps.label]).toLowerCase().match(input)
          })
          this.total = arr.length
          this.tableData = arr.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize)
        }
      }
      // 表格默认赋值
      this.$nextTick(() => {
        if (this.multiple) {
          this.defaultValue.forEach(row => {
            const arr = this.tableData.filter(item => item[this.defaultProps.value] === row[this.defaultProps.value])
            if (arr.length > 0) {
              this.$refs.table.toggleRowSelection(arr[0], true)
            }
          })
        } else {
          const arr = this.tableData.filter(item => item[this.defaultProps.value] === this.defaultValue[this.defaultProps.value])
          this.$refs.table.setCurrentRow(arr[0])
        }
        this.$refs.table.$el.querySelector('.el-table__body-wrapper').scrollTop = 0
      })
    },
    async initTable() {
      this.loading = true
      var reqData = {
        [this.defaultProps.page]: this.currentPage,
        [this.defaultProps.pageSize]: this.pageSize,
        [this.defaultProps.keyword]: this.keyword
      }
      Object.assign(reqData, this.params, this.formData)
      var res = await this.requestUrl(reqData)
      var parseData = config.parseData(res)
      this.tableData = parseData.list
      this.total = parseData.total
      this.loading = false
      // 表格默认赋值
      this.$nextTick(() => {
        if (this.multiple) {
          this.defaultValue.forEach((row) => {
            const arr = this.tableData.filter(item => item[this.defaultProps.value] === row[this.defaultProps.value])
            if (arr.length > 0) {
              this.$refs.table.toggleRowSelection(arr[0], true)
            }
          })
        } else {
          const arr = this.tableData.filter(item => item[this.defaultProps.value] === this.defaultValue[this.defaultProps.value])
          this.$refs.table.setCurrentRow(arr[0])
        }
        this.$refs.table.$el.querySelector('.el-table__body-wrapper').scrollTop = 0
      })
    },
    // 插糟表单提交
    formSubmit() {
      this.currentPage = 1
      this.keyword = null
      this.getData()
    },
    // 分页刷新表格
    currentChange(val) {
      this.currentPage = val
      this.getData()
    },
    // 赋值
    findLabel() {
      this.$nextTick(() => {
        if (this.multiple) {
          this.$refs.select.selected.forEach((item) => {
            if (this.isNeedRequest) {
              item.currentLabel = item.value[this.defaultProps.label]
            } else {
              item.currentLabel = this.tabularMap[item.value[this.defaultProps.value]]
            }
          })
        } else {
          if (this.isNeedRequest) {
            this.$refs.select.selectedLabel = this.defaultValue[this.defaultProps.label] || ''
          } else {
            this.$refs.select.selectedLabel = this.tabularMap[this.defaultValue[this.defaultProps.value]] || ''
          }
        }
      })
    },
    // 表格勾选事件
    select(rows, row) {
      var isSelect = rows.length && rows.indexOf(row) !== -1 // tip:row属于rows里的数据,同一地址,所以可判断
      if (isSelect) {
        // console.log(row, 'row')
        this.defaultValue.push(row)
        if (this.isNeedDataFilter) {
          var flag = false
          if (+row[this.filterParam.key] == this.filterParam.value) {
            flag = true
          }
        }
        this.dataFilter(flag)
      } else {
        this.defaultValue.splice(this.defaultValue.findIndex(item => item[this.defaultProps.value] === row[this.defaultProps.value]), 1)
      }
      if (this.isDataJoin) {
        this.defaultValue = this.defaultValue.map(item => item[this.defaultProps.value]).join(',')
      }
      this.findLabel()
      this.$emit('input', this.defaultValue)
      this.$emit('change', this.defaultValue)
    },
    // 表格全选事件
    selectAll(rows) {
      var isAllSelect = rows.length > 0
      if (isAllSelect) {
        var flag = false
        rows.forEach(row => {
          var isHas = this.defaultValue.find(item => item[this.defaultProps.value] === row[this.defaultProps.value])
          if (!isHas) {
            this.defaultValue.push(row)
            if (this.isNeedDataFilter) {
              if (+row[this.filterParam.key] == this.filterParam.value) {
                flag = true
              }
            }
          }
        })
        this.dataFilter(flag)
      } else {
        this.tableData.forEach(row => {
          const index = this.defaultValue.findIndex(item => item[this.defaultProps.value] === row[this.defaultProps.value])
          if (index !== -1) {
            this.defaultValue.splice(index, 1)
          }
        })
      }
      if (this.isDataJoin) {
        this.defaultValue = this.defaultValue.map(item => item[this.defaultProps.value]).join(',')
      }
      this.findLabel()
      this.$emit('input', this.defaultValue)
      this.$emit('change', this.defaultValue)
    },
    async rowClick(row) {
      if (this.multiple) {
        // 处理多选点击行
        this.$refs.table.toggleRowSelection(row)
        const isSelect = this.defaultValue.filter(item => item.bizid === row.bizid).length !== 0
        let oldDefaultValue = [...this.defaultValue] || []
        if (isSelect) oldDefaultValue = this.defaultValue.filter(item => item.bizid !== row.bizid)
        if (!isSelect) oldDefaultValue.push(row)
        this.select(oldDefaultValue || [], row)
      } else {
        this.defaultValue = ''
        this.$emit('input', this.defaultValue)
        this.$emit('change', this.defaultValue)
        await this.$nextTick()
        this.defaultValue = row
        if (this.isDataJoin) {
          this.defaultValue = row[this.defaultProps.value]
        }
        this.$refs.select.blur()
        this.findLabel()
        this.$emit('input', this.defaultValue)
        this.$emit('change', this.defaultValue)
      }
    },
    // tags删除后回调
    removeTag(tag) {
      var row = this.findRowByKey(tag[this.defaultProps.value])
      this.$refs.table.toggleRowSelection(row, false)
      if (this.isDataJoin) {
        this.defaultValue = this.defaultValue.map(item => item[this.defaultProps.value]).join(',')
      }
      this.$emit('input', this.defaultValue)
      this.$emit('change', this.defaultValue)
    },
    // 清空后的回调
    clear() {
      this.$emit('input', this.defaultValue)
      this.$emit('change', this.defaultValue)
    },
    // 关键值查询表格数据行
    findRowByKey(value) {
      return this.tableData.find(item => item[this.defaultProps.value] === value)
    },
    filterMethod(keyword) {
      if (!keyword) {
        this.keyword = null
        return false
      }
      this.keyword = keyword
      this.getData()
    },
    // 触发select隐藏
    blur() {
      this.$refs.select.blur()
    },
    // 触发select显示
    focus() {
      this.$refs.select.focus()
    },
    async getTitle() {
      try {
        await this.$nextTick()
        const title = []
        if (!this.isNeedRequest) {
          const map = {}
          for (const item of this.tabularData) {
            map[item[this.defaultProps.value]] = item[this.defaultProps.label]
          }
          if (this.multiple) {
            for (const v of this.defaultValue || []) {
              title.push(map[v[[this.defaultProps.value]]])
            }
          } else {
            return map[this.defaultValue[this.defaultProps.value]] || ''
          }
        }
        return title.length > 0 ? title.join(',') : ''
      } catch (error) {
        return ''
      }
    },
    dataFilter(flag) {
      if (!this.isNeedRequest && this.multiple && this.isNeedDataFilter) {
        this.defaultValue = this.defaultValue.filter(v => {
          const tepArr = this.tabularData.filter(i => {
            if (flag) {
              return i[this.filterParam.key] != this.filterParam.value
            } else {
              return i[this.filterParam.key] == this.filterParam.value
            }
          })
          const tepVal = tepArr.find(t => t[this.defaultProps.value] === v[this.defaultProps.value])
          if (tepVal) {
            this.$refs.table.toggleRowSelection(tepVal, false)
            return false
          }
          return true
        })
      }
    }
  }
}
</script>

<style scoped>
.sc-table-select__table {
  padding: 12px;
}
.sc-table-select__page {
  padding-top: 12px;
}
</style>




tableSelect.js

// 表格选择器配置
export default {
  pageSize: 20,						// 表格每一页条数
  parseData: function(res) {
    return {
      data: res.data,
      list: res.data.data.list,		// 分析行数据字段结构
      total: res.data.data.total,		// 分析总数字段结构
      msg: res.data.message,			// 分析描述字段结构
      code: res.data.code				// 分析状态字段结构
    }
  },
  request: {
    page: 'page',					// 规定当前分页字段
    pageSize: 'pageSize',			// 规定一页条数字段
    keyword: 'keyword'				// 规定搜索字段
  },
  props: {
    label: 'label',					// 映射label显示字段
    value: 'value'					// 映射value值字段
  }
}

使用


<template>
<!-- 单选用法 -->
<YyTableSelect
  v-model="xxx"
  :props="props"
  :tabularData="table"
  :table-width="600"
  @change="change()">
  <el-table-column prop="parameterName" label="参数名称"></el-table-column>
  <el-table-column prop="parameterScore" label="分值" width="180"></el-table-column>
</YyTableSelect>
<!-- 多选用法 -->
  <YyTableSelect
    v-model="value"
    :apiObj="apiObj"
    :table-width="700"
    multiple
    :props="props"
    @change="change"
  >
    <template #header="{ form, submit }">
      <el-form :inline="true" :model="form">
        <el-form-item>
          <el-select
            v-model="form.sex"
            placeholder="性别"
            clearable
            :teleported="false"
          >
            <el-option label="男" value="1"></el-option>
            <el-option label="女" value="2"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-date-picker
            v-model="form.date"
            value-format="YYYY-MM-DD"
            type="date"
            placeholder="时间"
            :teleported="false"
          ></el-date-picker>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submit">查询</el-button>
        </el-form-item>
      </el-form>
    </template>
    <el-table-column prop="id" label="ID" width="180"></el-table-column>
  </YyTableSelect>
</template>

<script>
import YyTableSelect from '@/views/components/YyTableSelect'
export default {
  components: {
    YyTableSelect
  },
  data() {
    return {
      params: {
        name: ''
      },
      value: [
        {
          id: '1',
          user: 'xx'
        },
        {
          id: '2',
          user: 'xx'
        }
      ],
      props: {
        label: 'label',
        value: 'value',
        keyword: 'keyword'
      }
    }
  },
  computed: {},
  mounted() {},
  methods: {
    // 值变化
    change(val) {
      console.log(val)
    }
  }
}
</script>

<style scoped></style>


根据https://lolicode.gitee.io/scui-doc/demo/#/dashboard里的组件修改






标签:vue,default,defaultValue,value,defaultProps,item,ui,element,row
From: https://www.cnblogs.com/ios9/p/18094751

相关文章

  • 基于 Python + Unitest + HwTestReport/BeautifulReport的UI自动化测试框架
    一、框架目录结构概览 二、框架执行流程简介 三、框架目录结构简介 四、测试报告示例 HwTestReport BeautifulReport         ......
  • 09-Vue-概述
    Vue官网:Vue.js(vuejs.org)Avue文档:Date日期|Avue(avuejs.com) 前置工作1)在使用Vue时,我们推荐在你的浏览器上 安装—Vue.js(vuejs.org),它允许你在一个更友好的界面中审查和调试Vue应用。2) 直接下载开发版本的vue.js,并用 <script> 标签引入,Vue 会被注册......
  • 基于ssm+vue.js的在线购书商城系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......
  • 基于ssm+vue.js的乐购游戏商城系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......
  • 基于ssm+vue.js的购物网站附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......
  • [AHK2 ui] 轻松设置主题
    开始在写ui工具的时候,常常会设置控件的背景或字体颜色;通常的做法是在options参数中使用backgroundRedcblack而如果想使用变量就会出现麻烦的字符串拼接,像这样:this.AddText('background'bgc'c'fc)在控件很多的时候便会像这样(我曾经写的ui):为了解决这种复杂性,有了下面的......
  • Java项目:小程序公交信息在线查询系统(java+SSM+Vue+ElementUI+mysql)
    源码获取:俺的博客首页"资源"里下载! 项目介绍基于SSM+Vue的小程序公交信息在线查询系统小程序角色:管理员、用户两种角色,分为小程序端和后台管理两部分;用户:用户通过小程序登录页面可以填写用户名和密码等信息进行登录操作,登录成功后,进入首页可以查看首页、线路信息、站......
  • Java项目:小程序公交信息在线查询系统(java+SSM+Vue+ElementUI+mysql)
    源码获取:俺的博客首页"资源"里下载! 项目介绍基于SSM+Vue的小程序公交信息在线查询系统小程序角色:管理员、用户两种角色,分为小程序端和后台管理两部分;用户:用户通过小程序登录页面可以填写用户名和密码等信息进行登录操作,登录成功后,进入首页可以查看首页、线路信息、站......
  • Java项目:汽车租赁管理系统(java+SpringBoot+Vue+ElementUI+Mybaits+mysql)
    源码获取:俺的博客首页"资源"里下载! 项目介绍基于SpringbootVue汽车租赁管理系统角色:管理员、用户、普通管理员三种角色,分为前后台;用户:用户通过用户登录页面可以填写用户名和密码等信息进行登录操作,登录成功后,进入首页可以查看首页、汽车信息、汽车资讯、汽车论坛、公......
  • EasyUi之Tabs(选项卡)
    原文链接:https://blog.csdn.net/qianbihua00/article/details/115392143什么是Tabs选项卡是最流行的导航模式之一(与菜单栏和垂直导航一样)。选项卡最大的优点是用户很熟悉,而且经常是持久的内容,所以即使用户在网站或应用程序中跳出刚浏览过的内容,他们也不会迷失。官方示例 ......