输入框滚动加载与搜索如何进行封装?

技术 vue2 项目 框架是 antdv 1.7.8
我项目中有很多表单,表单中有很多Select 选择器 选择器的内容是项目中的某一个列表,有很多这种下拉,在不同的界面。
我的问题是,单独的每一个下拉框都可以进行 远程搜索与滚动加载,但是接口是不同的,所以如何进行封住一下写一个,所有的下拉框都能用。
代码demo如此

<template>

<div>

<div>

<a-select style="width: 500px;" v-model="queryParam.industry_id" show-search :filter-option="false"

:default-active-first-option="false" @search="handleSearch" @popupScroll="handlePopupScroll">

<a-select-option v-for="(item, index) in industryList" :key="index" :value="item.industry_id">

{{item.industry_name }}

</a-select-option>

</a-select>

</div>

<div>

<a-select style="width: 500px;" show-search :filter-option="false" :default-active-first-option="false"

@search="handleSearchEnt" v-model="queryParam.ent_id" @popupScroll="handlePopupScrollEnt">

<a-select-option v-for="(item, index) in industryEntList" :key="index" :value="item.ent_id">

{{ item.ent_name}}

</a-select-option>

</a-select>

</div>

</div>

</template>

<script>

import {

orgSelectAPI,

orgEntSelectAPI,

} from "@/api/enterprise.js";

import _ from "lodash";

export default {

data() {

return {

queryParam: {},

industryList: [], // 产业下拉数据

industryCount: 10, // 产业默认10个

industrySize: 0, // 总条数数据改变时候必须低于这个值

industrySearch: "", // 远程搜索值

industryEntList: [],

entCount: 10,

entSize: 0,

industryEntSearch: "",

};

},

created() {

this.getIndustryList();

this.getIndustryEntList();

},

methods: {

// 产业下拉加载

handlePopupScroll: _.debounce(function (e) {

const { target } = e;

const { scrollTop, scrollHeight, offsetHeight } = target;

if (

this.industryCount <= this.industrySize &&

scrollTop + 2 + offsetHeight >= scrollHeight

) {

this.industryCount = Math.min(

this.industryCount + 10,

this.industrySize

);

this.getIndustryList(this.industrySearch);

}

}, 500),

// 远程搜索

handleSearch: _.debounce(function (e) {

this.industrySearch = e;

this.getIndustryList(this.industrySearch);

}, 500),

// 获取产业数据

async getIndustryList(e) {

let res = await orgSelectAPI({

page: 1,

rows: e ? 0 : this.industryCount,

name: e,

});

this.industry_id = "";

this.industryList = [];

this.industrySize = res.data.total;

this.industryList = res.data.rows;

},

handleSearchEnt: _.debounce(function (e) {

this.industryEntSearch = e;

this.getIndustryEntList("", e);

}, 500),

handlePopupScrollEnt: _.debounce(function (e) {

const { target } = e;

const { scrollTop, scrollHeight, offsetHeight } = target;

if (

this.entCount <= this.entSize &&

scrollTop + 2 + offsetHeight >= scrollHeight

) {

this.entCount = Math.min(this.entCount + 10, this.entSize);

this.getIndustryEntList(this.industry_id, this.industryEntSearch);

}

}, 500),

// 获取企业数据

async getIndustryEntList(e, name) {

let res = await orgEntSelectAPI({

page: 1,

rows: this.entCount,

industry_id: e,

name,

});

this.industryEntList = []

this.industryEntList = res.data.rows;

this.entSize = res.data.total;

},

},

};

</script>

像这种数据我有很多,这种下拉出现一个我就得定义一个 count与 size 还有搜索与滚动的函数,写起来很麻烦,但是接口又不相同,我该如何进行封装一下,让这个东西写一次,后边的都能用

求大佬给个封装思路,接口与数据如何搞

经过大佬提示之后封装如下

<template>

<a-select :placeholder='showPlaceHolder' v-model="selectedValue" style="width: 100%;" show-search :filter-option="false"

:default-active-first-option="false" @search="handleSearch" @popupScroll="handlePopupScroll">

<a-select-option v-for="(item, index) in showList" :key="index" :value="item[valueKey]">

{{ item[labelKey] }}

</a-select-option>

</a-select>

</template>

<script>

import _ from "lodash";

export default {

props: {

showPlaceHolder: '',

apiFunction: {

type: Function,

required: true,

},

queryParams: {

type: Object,

default: () => ({}),

},

valueKey: {

type: String,

default: 'id',

},

labelKey: {

type: String,

default: 'name',

},

initialCount: {

type: Number,

default: 10,

},

},

data() {

return {

selectedValue: undefined,

showList: [],

pageCount: this.initialCount, // 每页多少条

page: 1, // 当前第几页

allPage: 0, // 总共有多少页

pageTotal: 0, // 总共有多少条

itemSearch: "", // 搜索框搜索输入值

countNum: 0, // 计数器

};

},

watch: {

selectedValue(newV) {

this.$emit('getValue', newV)

this.itemSearch = undefined

this.getList();

},

queryParams: {

deep: true,

handler(newV, oldV) {

// 表单重置

if (oldV[this.valueKey] && !newV[this.valueKey]) {

this.selectedValue = null

}

}

}

},

created() {

if (this.queryParams && this.queryParams[this.valueKey]) {

// 有值就表示回显数据,回显只查当前条

this.selectedValue = this.queryParams[this.valueKey]

this.byIdGetList(this.queryParams)

} else {

this.getList();

}

},

/**

* 引用

* import popupScrollSelect from "@/views/common/components/popupScrollSelect.vue";

* <popupScrollSelect :showPlaceHolder="$t('pleaseSelect') + $t('facility_cn')" :query-params="{ facility_id: formRight.facility_id }" :api-function="emissionConfigFacilityAPI" value-key="facility_id" label-key="facility_cn" @getValue="e => formRight.facility_id = e"> </popupScrollSelect>

* 现在需要修改成分页请求数据,第一次请求 第1页,10条 第二次请求 2页,10条,将 第二页与第一页的数据拼接起来

* 设计思路,每页十条得到总页数,向上取整,页码每次加一,直到加到最大值,每次得到数据之后,push到原始展示数组中。

*

*/

methods: {

async getList(searchValue = "", page) {

const response = await this.apiFunction({

page: page ? page : 1,

rows: searchValue ? 0 : this.pageCount,

name: searchValue,

});

if (searchValue) {

this.showList = response.data.rows;

} else {

// 无法判断上次数据是搜索之后的 showList 还是下拉之后的数据,需要去重才能赋值

const mergedArray = [...this.showList.concat(response.data.rows)];

this.showList = _.uniqWith(mergedArray, _.isEqual)

}

// 总页数,总条数只需要计算一次

if (this.countNum == 0) {

this.pageTotal = response.data.total;

this.allPage = Math.ceil(this.pageTotal / this.pageCount) // 最多有多少页

this.countNum++

}

},

handleSearch: _.debounce(function (value) {

this.itemSearch = value;

this.getList(this.itemSearch);

}, 500),

handlePopupScroll: _.debounce(function (e) {

const { target } = e;

const { scrollTop, scrollHeight, offsetHeight } = target;

if (

this.page <= this.allPage &&

scrollTop + 2 + offsetHeight >= scrollHeight

) {

// this.pageCount = Math.min(this.pageCount + 10, this.pageTotal);

this.page = Math.min(this.page + 1, this.allPage);

this.getList(this.itemSearch, this.page);

}

}, 500),

async byIdGetList(queryParams) {

const response = await this.apiFunction(queryParams);

if (!this.showList.some(item => JSON.stringify(item) == JSON.stringify(response.data.rows[0]))) {

this.showList = [...this.showList, ...response.data.rows]

}

},

},

};

</script>


回答:

封装:

<template>

<a-select :placeholder="placeholder" v-model="selectedValue" style="width: 100%;" show-search :filter-option="false"

:default-active-first-option="false" @search="handleSearch" @popupScroll="handlePopupScroll">

<a-select-option v-for="(item, index) in list" :key="index" :value="item[valueKey]">

{{ item[labelKey] }}

</a-select-option>

</a-select>

</template>

<script>

import _ from "lodash";

export default {

props: {

placeholder: String,

apiFunction: {

type: Function,

required: true,

},

queryParams: Object,

valueKey: {

type: String,

default: 'id',

},

labelKey: {

type: String,

default: 'name',

},

initialCount: {

type: Number,

default: 10,

},

},

data() {

return {

selectedValue: null,

list: [],

count: this.initialCount,

page: 1,

total: 0,

};

},

watch: {

selectedValue(value) {

this.$emit('input', value);

},

queryParams: {

deep: true,

handler() {

this.getList();

},

},

},

created() {

this.getList();

},

methods: {

async getList(searchValue = "", page = 1) {

try {

const response = await this.apiFunction({

page,

rows: searchValue ? 0 : this.count,

name: searchValue,

});

this.list = searchValue ? response.data.rows : [...this.list, ...response.data.rows];

this.total = response.data.total;

} catch (error) {

console.error(error);

}

},

handleSearch: _.debounce(function (value) {

this.getList(value);

}, 500),

handlePopupScroll: _.debounce(function (e) {

const { target } = e;

const { scrollTop, scrollHeight, offsetHeight } = target;

if (this.page * this.count < this.total && scrollTop + offsetHeight >= scrollHeight) {

this.page += 1;

this.getList("", this.page);

}

}, 500),

},

};

</script>


回答:

官方示例:
https://3x.ant.design/components/select-cn/

以上是 输入框滚动加载与搜索如何进行封装? 的全部内容, 来源链接: utcz.com/p/934942.html

回到顶部