对Element select 进行分页处理

文章目录

  • 前言
  • 一、单选select分页
  • 二、多选select分页
  • 总结


前言

由于项目中有时一个select的候选项会一次性返回很多数据,比如我的就有上万条。一次性都渲染会造成页面直接卡死。本篇笔记就记录一下如何使用 elmentUI Select 选择器 和Pagination 分页组件进行性能优化处理。 你也可以对次进行改编成模板...

ps: 单选select分页是根据前辈的案例进行了改编和优化处理

一、单选select分页

简单说明:
1. 单选分页,支持搜索记忆功能,在搜索中途关闭选项卡时,会显示上次已选的正确选项。当input中有正确的值时会自动跳转到对应的分页
2. 如果你对此封装成了自己的组件,在子向传父组件传递候选项数据时,需要同时对options和options1进行赋值且他们的值是一致的

代码如下(示例):

<!DOCTYPE html>
<html>

<head>element selelct分页搜索(不支持多选)</head>
<!-- 引入样式 -->
<link rel="stylesheet" href="./css/element.css">
<!-- 引入组件库 -->
<script src="./js/vue.min.js"></script>
<script src="./js/element.js"></script>

<style>
    #main {
     
        width: 100%;
        height: 100%;
        text-align: center;
    }

    .el-input__inner {
     
        background: #5183ff !important;
        color: white;
        border: none;
        min-height: 32px !important;
        padding: 10px 22px 10px 10px;
        text-align: center;
    }

    .el-select .el-input .el-select__caret {
     
        display: none;
    }

    .el-select-dropdown__list {
     
        padding: 0;
    }

    .el-select-dropdown__list .el-page {
     
        position: sticky;
        bottom: 0;
        background: #fff;
    }
</style>

<body>
    <div id='main'>
        <el-select class="" v-model="value1" placeholder="请选择吃点" :clearable="false" size="mini" refs="mySelect"
            :reserve-keyword="true" filterable popper-class="sele" :filter-method="filter" @change="changed"
            @remove-tag="removeTab" @focus="focus" @blur="funb" @visible-change="hidden">
            <!--multiple="true"-->
            <el-option v-for="item in optionfen" :key="item.value" :label="item.label" remote :value="item.value"
                placeholder="请输入">
            </el-option>

            <div class="el-page">
                <el-pagination small @current-change="handleCurrentChange" :current-page="currentpage"
                    :page-size="pageSize" layout="prev, pager,next,total" :total="options.length">
                </el-pagination>
            </div>
        </el-select>

        <el-button type="primary" size="small" icon="el-icon-search" @click='getInputVal'>搜索</el-button>
    </div>
    <script>
        new Vue({
     
            el: '#main',
            data() {
     
                return {
     
                    options: [{
     value: '选项options1',label: '黄金糕'
                    }, {
     value: '选项options2',label: '双皮奶'
                    }, {
     value: '选项options3',label: '蚵仔煎'
                    }, {
     value: '选项options4',label: '龙须面'
                    }, {
     value: '选项options5',label: '北京烤鸭'
                    }, {
     value: 'options1',label: '氮气'
                    }, {
     value: 'options2',label: '氧气'
                    }, {
     value: 'options3',label: '臭气'
                    }, {
     value: 'options4',label: '氢气'
                    }, {
     value: 'options5',label: '氦气'
                    }, {
     value: 'options6',label: '分期'
                    }, {
     value: 'options7',label: '前期'
                    }],  //总数据
                    options1: [{
     value: '选项options1',label: '黄金糕'
                    }, {
     value: '选项options2',label: '双皮奶'
                    }, {
     value: '选项options3',label: '蚵仔煎'
                    }, {
     value: '选项options4',label: '龙须面'
                    }, {
     value: '选项options5',label: '北京烤鸭'
                    }, {
     value: 'options1',label: '氮气'
                    }, {
     value: 'options2',label: '氧气'
                    }, {
     value: 'options3',label: '臭气'
                    }, {
     value: 'options4',label: '氢气'
                    }, {
     value: 'options5',label: '氦气'
                    }, {
     value: 'options6',label: '分期'
                    }, {
     value: 'options7',label: '前期'
                    }],  //搜索的数据
                    optionfen: [],  //当前页码的数据
                    value1: "",  //输入框的值
                    currentpage: 1,   //当前页码
                    pageSize: 10,   //每页展示的条数
                    val: "", //存储输入框中正确地值(数据列表中的值)
                    selectDataAll:""
                };
            },
            computed: {
     },
            mounted() {
      },
            methods: {
     
                getInputVal() {
     
                    console.log(this.value1);
                    console.log(this.val);
                    console.log(this.selectDataAll);
                },
                removeTab() {
     
                    console.log('触发删除tab');
                },
                //分页的实现,currentpage 为页码,每页展示的数据为10(可自行更改pageSize)条,分别是在总数据options中
                //下标从(currentpage -1)*10开始的十条数据
                handleCurrentChange(val) {
     
                    // console.log('执行分页,第 '+val);
                    this.optionfen = [];
                    this.currentpage = val;
                    let start = (val - 1) * this.pageSize;
                    let end = Number(start) + Number(this.pageSize);
                    //此处需要判断如果计算的结束下标大于总数据的长度,则需要修改结束下标
                    if (end > this.options.length) {
     
                        end = this.options.length;
                    }
                    for (let i = start; i < end; i++) {
     
                        //将取到的数据展示在页面
                        this.optionfen.push(this.options[i]);
                    }
                },
                //已选择数据
                changed() {
     
                    this.selectDataAll = [];
                    for (let i = 0, len = this.optionfen.length; i < len; i++) {
     
                        const option = this.optionfen[i];
                        if (this.value1 == option.value) {
     
                            this.selectDataAll.push(option);
                            this.val = option;
                            break;
                        }
                    }

                    // console.log(this.val);
                    // console.log(selectDataAll);
                    // this.$emit(`${this.funName}`, selectDataAll); //推送
                },
                // 获得焦点
                //获得焦点的时候跳转到当前value所在的页码
                focus() {
     
                    // console.log("获得焦点:" + this.val);
                    let flag = false;
                    for (let i in this.options1) {
     
                        if (this.options1[i].value == this.value1) {
     
                            flag = true;
                            if (i < 10) {
     
                                this.currentpage = 1;
                                this.handleCurrentChange(1);
                            } else {
     
                                let num = 0;
                                num = ((i + 10) / 10).toString().charAt(0);
                                if (i > 100) {
     
                                    num = ((i + 10) / 10).toString().charAt(0);
                                    let num1 = ((i + 10) / 10).toString().charAt(1);
                                    num = `${
     num}${
     num1}`;
                                } else if (i > 1000) {
     
                                    num = ((i + 10) / 10).toString().charAt(0);
                                    let num1 = ((i + 10) / 10).toString().charAt(1);
                                    let num2 = ((i + 10) / 10).toString().charAt(2);
                                    num = `${
     num}${
     num1}${
     num2}`;
                                }
                                this.currentpage = Number(num) + 1;
                                this.handleCurrentChange(Number(num) + 1);
                            }
                            break;
                        }
                    }
                    //如果没有就默认展示第一页
                    if (!flag) {
     
                        this.currentpage = 1;
                        this.handleCurrentChange(1);
                    }
                },
                // 失去焦点
                //前面每次操作都将输入框内的value值存储一份到val中,就是为了防止用户搜索的时候中途关闭选择框,这个时候输入框显示的就是
                //用户输入一半的value值,加上这层逻辑就可以在用户输入的数据在总数据中不存在的时候(也就是无效数据),关闭选择框
                //之后让输入框依旧显示上一次的正确value值
                funb() {
     
                    this.value1 = this.val.value;
                    let elment = document.querySelector(".el-input__inner");
                    elment.style.color = 'red'
                },
                // 隐藏select列表
                hidden(bool) {
     
                    if (!bool) {
     
                        //关闭select下拉框的时候重置页码及数据,并移除事件监听
                        this.optionfen = [];
                        this.options = this.options1;
                        let start = 0;
                        let end = Number(start) + Number(this.pageSize);
                        if (end > this.options1.length) {
     
                            end = this.options1.length;
                        }
                        for (let i = start; i < end; i++) {
     
                            this.optionfen.push(this.options1[i]);
                        }
                        // 移除mousedown事件监听
                        removeEventListener("mousedown", function () {
      }, false);
                    } else {
     
                        // 打开select列表
                        // 增加mousedown事件监听  当点击分页时移除输入框的默认事件 ,让他不会失去焦点(blur),如果不加,就会
                        //出现当用户点击分页之后,输入框会失去焦点,这个时候如果用户需要输入数据进行搜索就需要删除输入框的值再输入,体验不好。
                        //(elementUI下拉框的默认样式,当可搜索时点击输入框可直接输入,不需要删除上次数据)
                        document.addEventListener(
                            "mousedown",
                            function (e) {
                                     
                                if (
                                    e.target.tagName === "LI" ||
                                    (e.target.tagName == "I" && e.target.localName == "i")
                                ) {
     
                                    e.preventDefault();
                                }
                            },
                            false
                        );
                        this.focus();
                    }
                },
                //搜索方法,将符合的数据存入options中,并分页展示
                filter(val) {
     
                    // console.log('过滤');
                    this.optionfen = [];
                    this.value1 = val.value;
                    let arr = [];
                    let value = val.toLowerCase();
                    for (let i = 0, len = this.options1.length; i < len; i++) {
     
                        if (this.options1[i].label.toLowerCase().indexOf(value) >= 0) {
     
                            arr.push(this.options1[i]);
                        }
                    }
                    this.options = arr;
                    this.handleCurrentChange(1);
                },
            },
        });
    </script>
</body>

</html>

二、多选select分页

简单说明:
1. 多选分页同样支持搜索记忆功能,但只会跳转到input中第一个数据所对的分页
2. 如果你使用了并仔细观察会返现el-page我使用的定位是粘性定位,如果你要修改el-select的样式,可能会造成样式的错位!
3.

代码如下(示例):

<!DOCTYPE html>
<html>

<head>element selelct分页搜索(多选)</head>
<!-- 引入样式 -->
<link rel="stylesheet" href="./css/element.css">
<!-- 引入组件库 -->
<script src="./js/vue.min.js"></script>
<script src="./js/element.js"></script>
<script src="./js/lodash.min.js"></script>

<style>
    #main {
     
        width: 100%;
        height: 100%;
        text-align: center;
    }

    .el-input__inner {
     
        background: #5183ff !important;
        color: white;
        border: none;
        min-height: 32px !important;
        padding: 10px 22px 10px 10px;
        text-align: center;
    }

    .el-select .el-input .el-select__caret {
     
        display: none;
    }

    .el-select-dropdown__list {
     
        padding: 0;
    }

    .el-select-dropdown__list .el-page {
     
        position: sticky;
        bottom: 0;
        background: #fff;
    }
</style>

<body>
    <div id='main'>
        <el-select class="" v-model="value1" placeholder="请选择吃点" :clearable="false" size="mini" refs="mySelect"
            :reserve-keyword="true" filterable popper-class="sele" :filter-method="filter" @change="changed"
            @remove-tag="removeTab" @focus="focus" @blur="funb" @visible-change="hidden" multiple="true">
            <!--multiple="true"-->
            <el-option v-for="item in optionfen" :key="item.value" :label="item.label" remote :value="item.value"
                placeholder="请输入">
            </el-option>

            <div class="el-page">
                <el-pagination small @current-change="handleCurrentChange" :current-page="currentpage"
                    :page-size="pageSize" layout="prev, pager,next,total" :total="options.length">
                </el-pagination>
            </div>
        </el-select>

        <el-button type="primary" size="small" icon="el-icon-search" @click='getInputVal'>搜索</el-button>
        <ul style="position: absolute; width: 250px; margin: 0 auto; top: 50px;">
            <li v-for="item in dataAll">
                {
     {
     item.label}} :  {
     {
     item.value}}
            </li>
        </ul>
    </div>
    <script>
        new Vue({
     
            el: '#main',
            data() {
     
                return {
     
                    options: [{
     value: '选项options1',label: '黄金糕'
                    }, {
     value: '选项options2',label: '双皮奶'
                    }, {
     value: '选项options3',label: '蚵仔煎'
                    }, {
     value: '选项options4',label: '龙须面'
                    }, {
     value: '选项options5',label: '北京烤鸭'
                    }, {
     value: 'options1',label: '氮气'
                    }, {
     value: 'options2',label: '氧气'
                    }, {
     value: 'options3',label: '臭气'
                    }, {
     value: 'options4',label: '氢气'
                    }, {
     value: 'options5',label: '氦气'
                    }, {
     value: 'options6',label: '分期'
                    }, {
     value: 'options7',label: '前期'
                    }],  //总数据
                    options1: [{
     value: '选项options1',label: '黄金糕'
                    }, {
     value: '选项options2',label: '双皮奶'
                    }, {
     value: '选项options3',label: '蚵仔煎'
                    }, {
     value: '选项options4',label: '龙须面'
                    }, {
     value: '选项options5',label: '北京烤鸭'
                    }, {
     value: 'options1',label: '氮气'
                    }, {
     value: 'options2',label: '氧气'
                    }, {
     value: 'options3',label: '臭气'
                    }, {
     value: 'options4',label: '氢气'
                    }, {
     value: 'options5',label: '氦气'
                    }, {
     value: 'options6',label: '分期'
                    }, {
     value: 'options7',label: '前期'
                    }],  //搜索的数据
                    optionfen: [],  //当前页码的数据
                    value1: [],  //输入框的值
                    currentpage: 1,   //当前页码
                    pageSize: 6,   //每页展示的条数
                    selectDataAll: {
     }, 
                    dataAll: [],
                    isTimer: '' //防抖时间
                };
            },
            computed: {
     },
            mounted() {
      },
            methods: {
     
                isDebounce(fn, delay) {
     
                    var _self = this; // 取debounce执行作用域的this
                    var args = arguments;
                    if (_self.isTimer) {
     
                        clearTimeout(_self.isTimer);
                    }
                    _self.isTimer = setTimeout(function () {
     
                        fn.apply(_self.isDebounce, args); // 用apply指向调用debounce的对象,相当于_this.fn(args);
                    }, delay);
                },
                getInputVal() {
     
                    console.log(this.value1);
                    console.log(this.dataAll);
                },
                removeTab(res) {
     
                    // console.log('触发删除tab: '+e);
                    let _self = this;
                    _.each(_self.selectDataAll, function (value) {
     
                        _.remove(value, function (item) {
     
                            return item.value == res;
                        })
                    })
                },
                //分页的实现,currentpage 为页码,每页展示的数据为10(可自行更改pageSize)条,分别是在总数据options中
                //下标从(currentpage -1)*10开始的十条数据
                handleCurrentChange(val) {
     
                    // console.log('执行分页,第 '+val);
                    this.optionfen = [];
                    this.currentpage = val;
                    let start = (val - 1) * this.pageSize;
                    let end = Number(start) + Number(this.pageSize);
                    //此处需要判断如果计算的结束下标大于总数据的长度,则需要修改结束下标
                    if (end > this.options.length) {
     
                        end = this.options.length;
                    }
                    for (let i = start; i < end; i++) {
     
                        //将取到的数据展示在页面
                        this.optionfen.push(this.options[i]);
                    }
                },
                //已选择数据
                changed(e) {
     
                    let _self = this;
                    let func = function () {
     
                        let data = [];
                        //匹配当前分页与输入框中value对应的数据
                        for (let j = 0; j < _self.value1.length; j++) {
     
                            const selectVal = _self.value1[j];
                            for (let i = 0, len = _self.optionfen.length; i < len; i++) {
     
                                const option = _self.optionfen[i];
                                if (option.value === selectVal) {
     
                                    let bool = true;
                                    //防止添加重复数据
                                    for (var k = 0; k < _self.selectDataAll.length; k++) {
     
                                        if (_self.selectDataAll[k].value === selectVal) {
     
                                            bool = false;
                                            break;
                                        }
                                    }
                                    if (bool) {
     
                                        data.push(option);
                                    }
                                }
                            }

                        }
                        _self.selectDataAll["page" + _self.currentpage] = data;


                        //对数据进行重组
                        _self.dataAll = [];
                        Object.values(_self.selectDataAll).map(item => {
     
                            for (let n = 0; n < item.length; n++) {
     
                                _self.dataAll.push(item[n])
                            }
                        })
                        console.log(_self.dataAll);
                    }
                    _self.isDebounce(func, 150);

                    // this.$emit(`${this.funName}`, selectDataAll); //推送
                },
                // 获得焦点
                //获得焦点的时候跳转到当前第一个value所在的页码
                focus() {
     
                    let _self = this;
                    let flag = false;
                    let func = function () {
     
                        let firstInputVal = Array.isArray(_self.value1) ? _self.value1[0] : _self.value1;
                        for (let i in _self.options1) {
     
                            if (_self.options1[i].value == firstInputVal) {
     
                                flag = true;
                                if (i < 10) {
     
                                    _self.currentpage = 1;
                                    _self.handleCurrentChange(1);
                                } else {
     
                                    let num = 0;
                                    num = ((i + 10) / 10).toString().charAt(0);
                                    if (i > 100) {
     
                                        num = ((i + 10) / 10).toString().charAt(0);
                                        let num1 = ((i + 10) / 10).toString().charAt(1);
                                        num = `${
     num}${
     num1}`;
                                    } else if (i > 1000) {
     
                                        num = ((i + 10) / 10).toString().charAt(0);
                                        let num1 = ((i + 10) / 10).toString().charAt(1);
                                        let num2 = ((i + 10) / 10).toString().charAt(2);
                                        num = `${
     num}${
     num1}${
     num2}`;
                                    }
                                    _self.currentpage = Number(num) + 1;
                                    _self.handleCurrentChange(Number(num) + 1);
                                }
                                break;
                            }
                        }
                        console.log("获得焦点:" + _self.value1);
                    }

                    _self.isDebounce(func, 150);


                    //如果没有就默认展示第一页
                    if (!flag) {
     
                        _self.currentpage = 1;
                        _self.handleCurrentChange(1);
                    }
                },
                // 失去焦点
                funb() {
     
                    console.log('失去焦点');
                    let elment = document.querySelector(".el-input__inner");
                    elment.style.color = 'red'
                },
                // 隐藏select列表
                hidden(bool) {
     
                    if (!bool) {
     
                        //关闭select下拉框的时候重置页码及数据,并移除事件监听
                        this.optionfen = [];
                        this.options = this.options1;
                        let start = 0;
                        let end = Number(start) + Number(this.pageSize);
                        if (end > this.options1.length) {
     
                            end = this.options1.length;
                        }
                        for (let i = start; i < end; i++) {
     
                            this.optionfen.push(this.options1[i]);
                        }
                        // 移除mousedown事件监听
                        removeEventListener("mousedown", function () {
      }, false);
                    } else {
     
                        // 打开select列表
                        // 增加mousedown事件监听  当点击分页时移除输入框的默认事件 ,让他不会失去焦点(blur),如果不加,就会
                        //出现当用户点击分页之后,输入框会失去焦点,这个时候如果用户需要输入数据进行搜索就需要删除输入框的值再输入,体验不好。
                        //(elementUI下拉框的默认样式,当可搜索时点击输入框可直接输入,不需要删除上次数据)
                        document.addEventListener(
                            "mousedown",
                            function (e) {
     
                                if (
                                    e.target.tagName === "LI" ||
                                    (e.target.tagName == "I" && e.target.localName == "i")
                                ) {
     
                                    e.preventDefault();
                                }
                            },
                            false
                        );
                        this.focus();
                    }
                },
                //搜索方法,将符合的数据存入options中,并分页展示
                filter(val) {
     
                    // console.log('过滤');
                    this.optionfen = [];
                    let arr = [];
                    let value = val.toLowerCase();
                    for (let i = 0, len = this.options1.length; i < len; i++) {
     
                        if (this.options1[i].label.toLowerCase().indexOf(value) >= 0) {
     
                            arr.push(this.options1[i]);
                        }
                    }
                    this.options = arr;
                    this.handleCurrentChange(1);
                },
            },
        });
    </script>
</body>

</html>

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

你可能感兴趣的:(elmentUI,select,elementui)