element-ui中el-select无限滚动

element-ui中el-select无限滚动,第1张

1. 在main.js同级创建directive.js文件

directive.js:

import Vue from 'vue'

Vue.directive('loadMore', {
  bind(el, binding) {
    // 如果有method由调用方实现,没有则在这里实现加载和远程搜索的功能
    if (binding.modifiers.method) { // 方法一
      // 节流
      let timer
      // 滚动监听
      el.querySelector('.el-select-dropdown .el-select-dropdown__wrap').addEventListener('scroll', function() {
        const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 100
        if (!timer && condition) {
          // 滚动加载(调用自定义的加载方法)
          binding.value()
          timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null
          }, 500)
        }
      })
    } else { // 方法二
      // 传入的对象
      let value = binding.value
      // 节流
      let timer
      // 无搜索内容变量
      let pageNo = 1
      let pages = 1
      // 远程搜索内容变量
      let searchPageNo = 1
      let searchPages = 1
      // 每次加载的条数
      let pageSize = isNaN(value.pageSize) ? 10 : parseInt(value.pageSize)
      // 远程搜索变量
      let searchField = value.searchField
      // 搜索固定内容
      let searchData = value.searchData
      // 接口地址
      let url = value.url
      // 下拉数组,这个options在本方法中必须永远指向value.options,否则整个功能都将失效
      let options = value.options
      // 无搜索拷贝数组,此处是为了在加载的基础上加一些默认的下拉项
      let optionsCopy = JSON.parse(JSON.stringify(value.options))
      // 远程搜索拷贝数组
      let optionsSearch = []
      // 远程搜索内容
      let searchValue = ''
      // 加载逻辑
      const loadOptions = (searchField, search, searchData) => {
        let params = {
          pageSize: pageSize
        }
        if (searchData) {
          Object.assign(params, searchData)
        }
        // 这里不能改变options的指向,否则会使整个功能失效(不能用options = [])
        options.length = 0
        // 判断是否为远程搜索,true-是
        if (searchField && search) {
          // 当到最大页数时不再查询
          if (searchPages >= searchPageNo) {
            params.pageNo = searchPageNo++
            params[searchField] = search
            api[url](params).then(res => {
              if (res) {
                searchPages = Math.ceil(res.data.total / pageSize)
                optionsSearch = optionsSearch.concat(res.data.data)
                dataProcessing(optionsSearch)
              }
            })
          }
        } else {
          // 当到最大页数时不再查询
          if (pages >= pageNo) {
            params.pageNo = pageNo++
            api[url](params).then(res => {
              if (res) {
                pages = Math.ceil(res.data.total / pageSize)
                optionsCopy = optionsCopy.concat(res.data.data)
                dataProcessing(optionsCopy)
              }
            })
          }
        }
      }
      // 返回数据处理
      let dataProcessing = (optionsCopy) => {
        // 这里不能改变options的指向,否则会使整个功能失效
        optionsCopy.forEach(item => {
          let check = options.find(t => {
            return t[value.modelField] === item[value.modelField]
          })
          if (!check) {
            options.push(item)
          }
        })
      }
      // 首次加载
      loadOptions(undefined, undefined, searchData)
      // 判断是否需要回显
      if (value.model && value.modelField) {
        // 回显方法
        let echo = (model, modelField, searchData) => {
          let params = {}
          params[modelField] = model
          if (searchData) {
            Object.assign(params, searchData)
          }
          api[url](params).then(res => {
            if (res) {
              optionsCopy = optionsCopy.concat(res.data.data)
              dataProcessing(optionsCopy)
            }
          })
        }
        if (optionsCopy.length > 0) {
          let check = optionsCopy.find((item) => {
            return item[value.modelField] === value.model
          })
          if (!check) {
            echo(value.model, value.modelField, searchData)
          }
        } else {
          echo(value.model, value.modelField, searchData)
        }
      }
      // 滚动监听(无限滚动)
      el.querySelector('.el-select-dropdown .el-select-dropdown__wrap').addEventListener('scroll', function() {
        const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 100
        if (!timer && condition) {
          // 滚动加载
          loadOptions(searchField, searchValue, searchData)
          timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null
          }, 200)
        }
      })
      // 输入监听(远程搜索)
      if (searchField) {
        const elInput = el.getElementsByTagName('input')[0]
        // 输入搜索
        elInput.addEventListener('input', function() {
          if (this.value) {
            searchPageNo = 1
            searchPages = 1
            optionsSearch = []
            searchValue = this.value
            loadOptions(searchField, searchValue, searchData)
          } else {
            searchValue = ''
            dataProcessing(optionsCopy)
          }
        })
        // 失去焦点时清除输入内容
        elInput.addEventListener('blur', function() {
          searchValue = ''
          dataProcessing(optionsCopy)
        })
      }
    }
  }
})

2. 在main中注册

import directives from './directives'
Vue.use(directives)

3.使用方法 (我是有很多地方使用到,所以封装成组件)

3.1 方法一 

data() {
  return {
    loading: false,
// 本来是想直接使用collectorId的,但是使用后报错,不允许我直接使用父传过来的,只好重新取一个
    collectorIdValue: '',
    options: [],
    params: {
      pageSize: 15,
      pageNum: 1,
      pageTotal: 0,
    },
  }
},
created() {
  this.remoteMethod()
},
props: {
  // 父传子的绑定数据
  collectorId: {
    default: null,
    type: [Number, String]
  },
},
watch: {
  // 监听绑定数据是否存在,存在则传递给父组件对应的数据
  'collectorIdValue': {
    handler(newVal) {
      if (newVal) {
        this.$parent.model.collectorId = newVal;
      } else {
        this.$parent.model.collectorId = ''
      }
    },
    immediate: true
  }
},
methods: {
  //  初始加载数据 
  remoteMethod(query) {
    this.loading = true;
    this.collectorIdValue = query || ''
    this.params.pageNum = 1
    const params = {
      pageSize: this.params.pageSize,
      pageNum: this.params.pageNum,
      collectorId: this.collectorIdValue
    }
    // 调用接口
    listCollector(params).then(response => {
      this.options = response.rows.map(el => {
        el.value = el.collectorId
        el.label = el.collectorId + '-(' + el.meterCount + ')只' + `${el.description? '-' + el.description : ''}`
        return el
      })
      this.params.pageTotal = response.total;
      this.loading = false;
    });
  },
  // 滚动到底部,加载数据
  loadMore(){
    if (this.options.length >= this.params.pageTotal) return
    this.params.pageNum++
    this.loading = true;
    const params = {
      pageSize: this.params.pageSize,
      pageNum: this.params.pageNum,
      collectorId: this.collectorIdValue
    }
    listCollector(params).then(response => {
      this.$nextTick(() => {
        this.options = this.options.concat(response.rows.map(el => {
          el.value = el.collectorId
          el.label = el.collectorId + '--(' + el.meterCount + ')只'
          return el
        }))
      })
      this.params.pageTotal = response.total;
      this.loading = false;
    });
  }
}

效果图:

3.2 方法二

           filterable
           :filter-method="()=>{}"
           v-load-more="{
             url:'url',
             options: options,
             model: id,
             modelField: 'id',
             searchField: 'name'}"
           >
      v-for="item in options"
    :key="item.id"
    :label="item.name"
    :value="item.id">
 

 
data() {
  return {
    options:[],
    id: ''
  }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/940239.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存