当前位置:   article > 正文

element-ui - 解决el-select数据量过大卡顿问题_elementui select数据过多

elementui select数据过多

解决el-select数据量过大卡顿问题


前言

当我们的下拉列表数据量过大时,初始化可能会有卡顿现象,我们可以通过滚动显示更多数据来解决这个问题。


一、el-select封装

// 控件名称  LargeDataSearchSelect
<tempalte>
  <div></div>
</tempalte>

<script>
export default {
  name: 'large-data-search-select',
  directives: {
    'el-select-loadmore': {
      bind(el, binding) {
        // 获取element-ui定义好的scroll盒子
        const SELECTWRAP_DOM = el.querySelector(
            '.el-select-dropdown .el-select-dropdown__wrap'
        )
        SELECTWRAP_DOM.addEventListener('scroll', function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
          if (condition) binding.value()
        })
      }
    }
  },
  props: {
    selectProps: {
      type: Object,
      default: () => {
        return {
          options: [],
          rangeNumber: 100
        }
      },
      require: true
    },
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      selectValue: '',
      rangeNumber: this.selectProps.rangeNumber || 100,
      options: [],
      originalData: []
    }
  },
  watch: {
    value: {
      handler(newVal) {
        this.selectValue = newVal
      },
      deep: true,
      immediate: true
    },

    selectProps() {

      this.init()
    }
  },

  created() {

    this.delayFilter = _.debounce((query)=>{
      this.filter(query)
    },500)
  },

  mounted() {

    this.$nextTick(() => {

      this.init()
    })
  },
  methods: {

    init() {

      this.originalData = this.selectProps.options
      this.initRenderOpions()
    },

    loadMore(n) {
      if (n < 8) this.rangeNumber = 10
      return () => (this.rangeNumber += 5) // 每次滚动到底部可以新增条数  可自定义
    },

    filter(query) {
      if (query) {
        let newOption = this.originalData.filter((item) =>
            item[this.selectProps.label || 'label'].includes(query)
        )

        if(newOption.length) {
          return this.options = newOption
        }
      }

      this.initRenderOpions()
    },

    selectChange() {

      this.$emit('updateChange', this.selectValue)
      this.initRenderOpions()
    },

    initRenderOpions() {
      let options = this.originalData.slice(0, this.rangeNumber)
      let index = -1

      if (_.size(this.selectValue)) {
        index = _.findIndex(options, (item)=>{
          return item.game_id === this.selectValue
        })

        if(index === -1) {
          let currentItem = _.find(this.originalData, (game)=>{
            return game.game_id === this.selectValue
          })

          if(currentItem) {
            options.unshift(currentItem)
          }
        }
      }

      this.options = options
    }
  },

  render() {
    return (
        <el-select
    {...this.$attrs}
    v-model={this.selectValue}
    placeholder={this.selectProps.placeholder || '请选择'}
    popper-append-to-body={false}
    clearable
    filterable
    filter-method={this.delayFilter}
    onChange={this.selectChange}
    v-el-select-loadmore:rangeNumber={this.loadMore(this.rangeNumber)}
        >
        {this.options.map((item, index) => {
            return (
                <el-option
                  key={item[this.selectProps.value || 'value']}
                  label={item[this.selectProps.label || 'label']}
                  value={item[this.selectProps.value || 'value']}
                 ></el-option>
          )
          })}
        </el-select>
  )
  }
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166

二、使用

<template>
<!-- 原本的 el-select -->
<!--  <el-select class="extern-header-gamelist fl" size="small" v-model="gameId" filterable placeholder="请按游戏筛选查看"-->
<!--             @change="onChangeGameIdHandler">-->
<!--    <el-option v-for="(item, index) in gameList" :label="item.game_name" :value="item.game_id" :key="index"-->
<!--               style="width:217px;"></el-option>-->
<!--  </el-select>-->

  <!-- 使用自己封装的el-select -->
  <LargeDataSearchSelect class="extern-header-gamelist fl" size="small"
                  v-model="gameId"
                  :selectProps.sync="selectProps"
                  @updateChange="onChangeGameIdHandler"
  />
</template>

<script>
import util from '@/common/util'
import LargeDataSearchSelect from "@/components/large-data-search-select";
export default {
  name: "app",
  components: {
    LargeDataSearchSelect
  },
  data(){
    return {
      gameList: [],
      gameId: util.getGameId(),
    }
  },
  computed: {
    selectProps() {
      return {
        placeholder: '请按游戏筛选查看',
        options: _.clone(this.gameList),
        rangeNumber: 100,
        label: "game_name",
        value: "game_id"
      }
    },
  },
  created() {

    this.fetchGameList()
  },
  methods: {
    async fetchGameList() {
      let result;

      result = await IBOX.waxios({
        url: `${IBOX.config.baseURL}api/get_gs_games`,
        method: 'Get'
      })

      if(result && result.ret === 0 && _.isArray(result.data)) {

        this.gameList = _.map(result.data, (game) => {
          return {
            game_id: '' + game.game_id,
            game_name: `[${game.game_id}]${game.game_name}`
          }
        })
        IBOX.gameList = this.gameList;
        this.selectProps.options = _.clone(this.gameList);
        this.$store.commit('updateGameList', this.gameList)
      }else{

        this.$alert(staticData.requestFailMessage).then(()=>{

          this.fetchGameList()
        })
      }
    },

    onChangeGameIdHandler(gameId) {
      if(util.getGameId() !== gameId) {
        util.setGameId(gameId);
        this.$emit('change-game');
      }
    },
  }
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

总结

原文转载来自: 解决el-select数据量过大卡顿问题-记录贴

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/114801
推荐阅读
相关标签
  

闽ICP备14008679号