vue3动态ref与大数据量Select
·
缘起,有个大数据量的Select需要改造,同时需要添加编辑数据,说不清楚了,直接来吧!涉及大数据量Select改造,动态ref
Select组件- 动态
ref
Select组件
<template>
<a-select
v-model:value="seletedValue"
style="width: 281px; margin-left: 8px;"
:options="options"
:fieldNames="{label: 'tagName', value: 'tagId', options: options}"
@popupScroll="popupScroll"
>
</a-select>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { getTags } from '@/server/request'
const seletedValue = ref('')
let oriData = ref([])
// 默认渲染行数
let index = 10
const options = ref([])
const exitOptions = ref<string[]>([])
onMounted(async () => {
await changeTagsOptions()
options.value = []
options.value = oriData.value.slice(0, index).filter((o: { tagId: string; }) => o.tagId !== seletedValue.value)
})
const popupScroll = (e:any) => {
const { scrollHeight, scrollTop, clientHeight } = e.target;
if (scrollHeight - scrollTop === clientHeight) {
const tmp = oriData.value.slice(index, index+10)
tmp.forEach((t: { tagId: string; }) => {
if (!exitOptions.value.includes(t.tagId)) {
options.value.push(t)
}
})
index += 10
}
}
const changeTagsOptions = async () => {
const params = {
paging: {
current: 1,
pageSize: 100000,
},
dialect: {
displayUserCount: false
}
}
const res = await getTags(params)
if (res.errorCode === 0) {
oriData.value = res.data.result
}
}
const returnCurrentData = () => {
return seletedValue.value
}
const loadPage = async (val: string) => {
seletedValue.value = val
await changeTagsOptions()
options.value = []
options.value = oriData.value.slice(0, index).filter((o: { tagId: string; }) => o.tagId !== seletedValue.value)
const find = oriData.value.find((d: { tagId: string; }) => d.tagId === val)
if (find) {
options.value.unshift(find)
exitOptions.value.push(val)
}
options.value.forEach((t: { tagId: string; }) => {
exitOptions.value.push(t.tagId)
})
}
defineExpose({
returnCurrentData,
loadPage
})
</script>
组件:
通过loadPage接收调用方传递的数据,通过returnCurrentData返回编辑好的数据。
组件通过接口获取数据,但默认只加载前10条,并将需要回显的数据放在数据的最上层。
滚动下拉选项时,到底部会继续加载后续数据,每次加载10条
动态ref
效果如下:
下面是从项目中摘的代码:
<template>
<div style="border: 1px solid #d9d9d9;padding: 4px;margin-top:48px">
<template v-for="(cond, condIndex) in participationConditions">
<a-row>
<a-col :span="2" class="item-label" style="line-height:32px">
{{ $t('departmentConditions') }}:</a-col>
<a-col :span="22">
<a-input :value="computeValue(condIndex, 'tags')" style="width:99%; margin: 4px 8px;" disabled />
</a-col>
</a-row>
<div style="text-align: right;">
<a-button style="margin: 0 4px" size="small" type="primary" ghost @click="editConditions(condIndex)">{{ $t('btnEdit') }}</a-button>
<a-button style="margin: 0 4px" danger ghost size="small" @click="removeConditions(condIndex)">{{ $t('btnDelete') }}</a-button>
</div>
<a-divider style="margin:12px 0" />
</template>
<a-row>
<a-col :span="2" class="item-label">
<span class="required-icon">*</span>
{{ $t('departmentConditions') }}:</a-col>
<a-col :span="22">
<bigSelect v-for="(item, sDepartIndex) in selectedTags" :val="item" :ref="setItemRef"></bigSelect>
<plus-circle-two-tone :style="{fontSize: '18px',margin: '0 20px 0 10px'}" @click="addItem('department')" />
</a-col>
</a-row>
<div style="text-align: right;">
<a-button class="add-btn" type="primary" size="small" ghost :disabled="selectedTags.length === 0" @click="addConditions()">{{ $t('btnConfirm') }}</a-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { PlusCircleTwoTone } from '@ant-design/icons-vue';
import { ref, onBeforeUpdate, nextTick, onMounted } from 'vue'
import bigSelect from './components/big-select.vue'
import { Obj } from '@/type'
import { message } from 'ant-design-vue';
import { useI18n } from 'vue-i18n'
import { getTags } from '@/server/request'
const { t } = useI18n()
const itemRefs = ref([])
const setItemRef = (el: any) => {
if (el) {
itemRefs.value.push(el)
}
}
onBeforeUpdate(() => {
itemRefs.value = []
})
onMounted(() => {
changeTagsOptions()
})
const tagLists = ref<Obj[]>([])
const changeTagsOptions = async () => {
const params = {
paging: {
current: 1,
pageSize: 100000,
},
dialect: {
displayUserCount: false
}
}
const res = await getTags(params)
if (res.errorCode === 0) {
tagLists.value = res.data.result
}
}
const selectedTags = ref<string[]>([''])
const addItem = (type: string) => {
if (type === 'department') {
selectedTags.value.push('')
}
}
const participationConditions = ref<Obj[]>([])
const addConditions = () => {
let tmpTag = []
for (let i=0; i<itemRefs.value.length; i++) {
tmpTag.push(itemRefs.value[i].returnCurrentData())
}
selectedTags.value = Array.from(new Set(tmpTag))
let tmp = {
tags: [] as Obj[],
assets: [] as Obj[]
}
let validateFlag = true
selectedTags.value.forEach((sd:string, index: number) => {
const find = tagLists.value.find((t) => t.tagId === sd)
if (find) {
tmp.tags.push({
value: find['tagId'],
label: find['tagName'],
})
} else {
validateFlag = false
}
})
if (!validateFlag) {
message.warning(t('configurationConfirm'))
return
}
if (editIndex === -1) {
participationConditions.value.push(tmp)
} else {
participationConditions.value[editIndex] = tmp
}
selectedTags.value = ['']
editIndex = -1
for (let i=0; i<itemRefs.value.length; i++) {
itemRefs.value[i].loadPage('')
}
}
let editIndex = -1
const editConditions = (condIndex: number) => {
const tmp = participationConditions.value[condIndex].tags.map((p: { value: string; }) => p.value)
selectedTags.value = tmp
nextTick(() => {
for (let i=0; i<itemRefs.value.length; i++) {
itemRefs.value[i].loadPage(selectedTags.value[i])
}
})
editIndex = condIndex
}
const removeConditions = (condIndex: number) => {
participationConditions.value.splice(condIndex, 1)
}
const computeValue = (condIndex: number, type: string) => {
if (type === 'tags') {
return participationConditions.value[condIndex][type].map((p: { label: string; }) => p.label).join(' and ')
}
}
</script>
<style scoped lang="scss">
.required-icon {
color:red;
font-size: 14px;
}
.item-label {
text-align: right;
// line-height: 40px;
}
.add-btn {
margin: 4px;
}
</style>
逻辑不用关心,关注下itemRefs相关内容。
写不下去了,就这样吧!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)