el-popover实现下拉滚动刷新
效果图:
下拉组件实现: wb-select-scroll.vue
<!--<wb-select-scroll :parentValue.sync="dataList.wbCombinIVos[index].subid" urls="subjectEndScroll" :rowIndex="index" @selectBackFun="dealSelectBackFun"placeholders="请选择折扣科目" clearable></wb-select-scroll >5、新增使用那个组件,assemblyshop是分机机构,department是部门,employ是业务员,subject是科目,remark是摘要,billkind100是运输方式,project是项目,customer是客户,money是币种,paymethod是结算方式,trader是供应商,iotype是出入库类型,assetsType是固定资产类别,assetsAddType是固定资产增加方式,assetsReduceType是固定资产减少方式voucherRemark是凭证摘要,goodstype是货品类别,brand是品牌,新改动;下拉刷新,根据传过来的urls值,请求后端接口,要求,所有的接口都要按照分页的格式进行处理,可以参考 goodsList 接口进行开发urls="goodsList" 货品下拉列表urls="subjectEndScroll" 末级科目下拉列表urls="getTraderCustomerScroll" 客户下拉列表--><template><div ><el-popover placement="bottom" :width="width" trigger="click" popper-class="wb-padding" v-model="visible":disabled="disabled"><div ref="divRef"><div style="overflow: auto; height: 200px; border: 1px solid #ddd;" ref="scrollContainer" v-if="urls == 'goodsList'"><!-- <el-radio-group v-model="goodstype" style="margin-top: 5px;"><el-radio :label="3">A类</el-radio><el-radio :label="6">B类</el-radio><el-radio :label="9">C类</el-radio></el-radio-group> --><ul class="el-scrollbar__view el-select-dropdown__list" style="list-style: none; padding: 0; margin: 0;"><!-- 表头 --><div><li class="el-select-dropdown__item" style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #ddd; padding: 8px 0; background-color: #f8f4f4;font-weight: bold"><span style="padding:5px;display: inline-block; width: 200px;text-align:center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;">编码</span><span style="padding:5px; width: 250px;text-align:center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;">名称</span><span style="padding:5px; width: 100px;text-align:center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">规格</span></li></div> <!-- 数据行 --><div v-for="(it, index) in listArr" :key="index" @click="upData(it)"><li class="el-select-dropdown__item" style="padding:5px;display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #ddd; padding: 8px 0;"><span style="padding:5px;display: inline-block; width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;" :title="it.code">{{ it.code }}</span><span style="padding:5px;width: 250px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;" :title="it.name">{{ it.name }}</span><span style="padding:5px; width: 100px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" :title="it.specs">{{ it.specs }}</span></li></div><!-- 无数据时显示 --><div v-if="listArr == null || listArr.length <= 0"style="display: flex; justify-content: center; align-items: center; text-align: center; width: 100%; height: 200px; border: 1px solid #ddd;"><span style="padding:5px;">无数据</span></div></ul></div><div style="overflow: auto; height: 200px;" ref="scrollContainer" v-else><ul class="el-scrollbar__view el-select-dropdown__list" style="list-style: none; padding: 0; margin: 0;"><!-- 表头 --><div><li class="el-select-dropdown__item" style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #ddd; padding: 8px 0; background-color: #f8f4f4;font-weight: bold"><span style="padding:5px;display: inline-block; width: 200px;text-align:center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;">编码</span><span style="padding:5px; width: 250px;text-align:center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;">名称</span></li></div> <!-- 数据行 --><div v-for="(it, index) in listArr" :key="index" @click="upData(it)"><li class="el-select-dropdown__item" style="display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #ddd; padding: 8px 0;"><span style="padding:5px;display: inline-block; width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;" :title="it.code">{{ it.code }}</span><span style="padding:5px;width: 250px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ddd; padding-right: 5px;" :title="it.name">{{ it.name }}</span></li></div><div v-if="listArr == null || listArr.length <= 0"style="display: flex; justify-content: center; align-items: center; text-align: center; width: 100%; height: 200px;"><span style="padding:5px;">无数据</span></div></ul></div><div :style="'background-color: #fff;width:' + width + ' px;'"><div v-if="assembly" style="display: flex; line-height: 30px;cursor: pointer;"><div class="addBorder" style="width: 50%;" @click="adds">新增</div><div class="delBorder" style="width: 50%;" @click="empty">重置</div></div><div v-else style="display: flex; line-height: 30px;cursor: pointer;"><div class="delBorder" style="width: 100%;" @click="empty">重置</div></div></div></div><el-input type="text" ref="myInput" v-model="name" @change="changes" @input="remoteName"slot="reference" size="mini" style="width: 100%;" :placeholder="placeholders" :disabled="disabled"><i v-if="disabled == false" slot="suffix":class="showIcon ? 'el-input__icon el-icon-arrow-up' : 'el-input__icon el-icon-arrow-down'"@click="handleClick"></i><i v-if="disabled == true" class="el-input__icon el-icon-arrow-up"></i></el-input></el-popover><!-- 组件化新增 --><component :is="currentComponent" ref="assemblyAll" @on-added="handleAdded"></component></div>
</template><script>export default {components: {"areas": () => import('./assembly/area.vue'),},props: {parentValue: "",placeholders: "",list: [],widths: "",urls: "",defaultId: "",assembly: "",disabled: {default: false},voucherTemSubject: "",params:{page: 1,pageSize: 20},rowIndex: {type: Number,default: -999},},watch: {visible(newVal) {this.showIcon = newVal; // 如果visible为true,箭头向上;false时箭头向下if (newVal) {//设置宽度this.focusSelect();this.$nextTick(() => {const scrollContainer = this.$refs.scrollContainer;if (scrollContainer) {scrollContainer.addEventListener('scroll', this.handleScroll);}this.paramsData.page = 1; // 初始化页码this.listArr = []; // 清空数据this.hasMore = true; // 允许加载更多// this.fetchOptions(); // 加载第一页数据// console.log('watch监听打开下拉后查询-------newVal--',newVal);this.selectByKeyWord();});} else {const scrollContainer = this.$refs.scrollContainer;if (scrollContainer) {scrollContainer.removeEventListener('scroll', this.handleScroll);}}},list(newVal) {//this.listArr = newVal;},parentValue: {handler(newvalue) {this.$nextTick(() => {if(this.parentValue){//默认值// console.log('watch监听parentValue后查询---------',this.parentValue);this.selectByKeyWord(1);}else {this.name = "";}});}},},data() {return {name: '',goodstype: null,width: "200",dataList: { "mshopid": "" },visible: false,parentids: this.defaultId,id: "",index: 1,listCp: [],currentComponent: "",listArr: [],inpIndex: true,showIcon: false,parentValueInfo: this.parentValue,paramsData:{page: 1, // 当前页码pageSize: 20, },// 每页数据量hasMore: true, // 是否还有更多数据loading: false,had_id_one: [],// list: [{'id':1,"name":"dade"},// {'id':4,"name":"dade4"}]};},created() {this.listArr = this.list},mounted() {// console.log('mounted---this.parentValue===',this.parentValue);// 存在加载下拉框,降低ioif(this.parentValue){//默认值// console.log('挂载完成后查询---------',this.parentValue);this.selectByKeyWord(1);}//动态引入组件if (this.assembly) {//引入组件this.currentComponent = this.assembly;}document.addEventListener('click', this.selectBlur, true)},beforeDestroy() {document.removeEventListener('click', this.selectBlur, true)// 移除滚动事件监听,防止内存泄漏const scrollContainer = this.$refs.scrollContainer;if (scrollContainer) {scrollContainer.removeEventListener('scroll', this.handleScroll);}},methods: {handleScroll(event){// console.log('------滚动了---------');const { scrollTop, scrollHeight, clientHeight } = event.target;//console.log('scrollTop + clientHeight=======',scrollTop + clientHeight)// console.log('scrollHeight=======',scrollHeight)// 判断是否滚动到底部if (scrollTop + clientHeight >= scrollHeight-1 && this.hasMore ) {this.paramsData.page++; // 增加页码// this.fetchOptions(); // 请求下一页数据// console.log('到底了,查询下一页------');this.select();}},// 输入框失去焦点selectBlur(e) {if (this.visible === true&& this.$refs.divRef&& this.$refs.myInput&& this.$refs.myInput.$el&& !this.$refs.divRef.contains(e.target)&& !this.$refs.myInput.$el.contains(e.target)) {this.visible = false}},async handleAdded(data) {this.parentids = data.id// console.log('新增--handleAdded---查询----');await this.select()this.$emit('update:parentValue', data.id);// 处理新增数据的回调方法this.$emit('add-callback', { ...data })},handleClick() {// if (this.showIcon === false) {// this.focusSelect()// }},// 输入框获得焦点focusSelect() {const inputElement = this.$refs.myInput.$el;if (this.widths == undefined) {this.width = inputElement.offsetWidth;} else {this.width = this.widths;}},//失去焦点,或者按回车,返回changes() {if (this.urls == 'remark') {this.inpIndex = false;this.$emit('update:parentValue', this.name);}},// 输入框数据改变remoteName(e) {this.paramsData.keyWord = e;this.selectByKeyWord();},//点击选中,返回值,数据双向绑定upData(it) {this.name = it.name;this.$emit('update:parentValue', it.id);this.$emit('selectBackFun', it,this.rowIndex);//选中调用父类方法this.visible = false;},// 新增adds() {this.$refs.assemblyAll.assembly();this.visible = false;},// 重置empty() {this.name = "";this.$emit('update:parentValue', "");this.$emit('accountFn', {})this.visible = false;},// 查询下拉框async select() {if (this.urls) {await this.$myhttp.post("/main/dropDowm/" + this.urls, this.paramsData).then((res) => {// console.log('select查询--res.data.code----',res.data.code);if(res.data.code == 2000){let datalist = res.data.data;if(datalist != null && datalist.length > 0){this.listArr = [...this.listArr,...datalist]this.listCp = [...this.listCp,...datalist]}// console.log('select查询结果this.listArr---',this.listArr);}})}},retParamsData(){this.paramsData.page = 1;this.paramsData.pageSize = 20;},// 查询下拉框async selectByKeyWord(val) {if (this.urls) {if(this.parentValue && '' !== this.parentValue && val == 1){this.paramsData.parentValue = this.parentValue;}else {this.paramsData.parentValue = null;}this.retParamsData();//还原查询分页数据await this.$myhttp.post("/main/dropDowm/" + this.urls, this.paramsData).then((res) => {if(res.data.code == 2000){let datalist = res.data.data;let count = res.data.count;if(val == 1){this.listArr = [...datalist];this.listCp = [...datalist];this.had_id_one = [...datalist];if(this.had_id_one && this.had_id_one.length == 1){this.name = this.had_id_one[0].name;}}else {// 过滤出 this.had_id_one 中那些 id 不在 datalist 中的对象let filteredDatalist = datalist.filter(item => !this.had_id_one.some(dataItem => dataItem.id === item.id));// 合并过滤后的结果this.listArr = [...filteredDatalist,...this.had_id_one];this.listCp = [...datalist];}}})}else {this.listArr = [];}},}
};
</script><style>
.el-select-dropdown__wrap {max-height: 200px !important;
}.wb-padding {padding: 0px;min-width: 300px;
}.addBorder {text-align: center;border-top: 1px solid rgb(221 221 221);
}.delBorder {text-align: center;border-top: 1px solid rgb(221 221 221);border-left: 1px solid rgb(221 221 221);
}
</style>
<style scoped>
.scroll-container {height: 300px; /* 设置一个固定高度来模拟滚动 */overflow-y: auto; /* 允许垂直滚动 */
}
</style>
在别的页面使用:
1、引入:
components: {"wb-select-scroll": () => import('@/views/comm/wb-select-scroll.vue'),},
2、使用:
<el-descriptions size="small" :column="1" border :labelStyle="{ width: '80px', color: '#000000' }":contentStyle="{ width: 'calc(100% - 80px)' }"><el-descriptions-item label="货品名称"><wb-select-scroll :parentValue.sync="goods.goodsid" urls="goodsList" @selectBackFun="dealSelectBackFun"placeholders="请选择货品" clearable></wb-select-scroll ></el-descriptions-item></el-descriptions>
重要说明:
parentValue.sync为绑定的变量,必填
:parentValue.sync="goods.goodsid"
urls为请求到后端接口的url,根据自己实际项目调整组合
urls="goodsList"
@selectBackFun点击下拉内容返回的回调函数,根据实际业务处理
@selectBackFun="dealSelectBackFun"