基于vue+element ui实现下拉表格选择组件
基于vue+element ui实现下拉表格选择组件
·
单选
多选
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里的组件修改
更多推荐
已为社区贡献4条内容
所有评论(0)