js项目优化
邵预鸿 Lv5

长列表优化

针对大数据时,长列表的优化

  • 滚动加载(不谈,见网上)

  • 虚拟列表

    思路:在列表头部和底部分别添加一个div,始终只展示当前屏幕的li dom,屏幕之上下由div的高度支撑

    ​ 切割开始点= Math.floor(容器.scrollTop / li的高度) ,为什么Math.floor? 滚动时可能存在顶部某个li一半的情况,需要预留位置

    ​ 切割结束点= Math.ceil( 容器.scrollTop + 一个屏幕的高度 / li的高度) ,为什么Math.ceil? 同理,滚动时可能存在底部某个li一半的情况,需要预 留位置

    算出切割开始点、切割结束点,对完整数组切割,屏幕只保留(切割开始点,切割结束点) 的数组,屏幕之上由top_empty的高度代替,屏幕之下的由bottom_empty的高度代替

    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
    <div class="app_wrap"  v-infinite-scroll="load"  :infinite-scroll-distance="200">
    <div class="top_empty" :style="{height:topEmptyHeight+'px'}"></div>
    <ul class="list">
    <li v-for="(item) in list" :key="item">
    <div class="bar">{{item}}</div>
    </li>
    </ul>
    <div class="bottom_empty" :style="{height:bottomEmptyHeight+'px'}"></div>
    </div>


    <style scoped lang="scss">
    .app_wrap{
    width: 1000px;
    height: 100vh;
    overflow: auto;
    margin: 0 auto;
    .top_empty,.bottom_empty{
    height: 0;
    background-color: #ddd;
    }

    .list{
    li{
    height: 60px;
    padding-bottom: 15px;
    box-sizing: border-box;
    .bar{
    background-color: #ccc;
    color: #333;
    padding: 15px;
    box-sizing: border-box;
    }
    }
    }
    }
    </style>

    js部分

    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
    <script setup lang="ts">
    import { onMounted,defineEmits, ref,Ref } from 'vue';

    const topEmptyHeight = ref(0);
    const bottomEmptyHeight = ref(0);
    const listLength = ref(100);
    const list = ref([...new Array(listLength.value).keys()]);
    let copyList = list.value.concat();

    const load = ()=>{
    listLength.value +=50;
    list.value = [...new Array(listLength.value).keys()];
    copyList = list.value.concat();
    scrollFunc(); //数组滚动加载后,由于上面的代码展示的是所有,需要手动调用一次,把数据重新切割计算一次
    }
    const scrollFunc = ()=>{
    const scrollTop = (document.querySelector('.app_wrap') as HTMLElement).scrollTop;
    const endTop = scrollTop +(document.querySelector('.app_wrap') as HTMLElement).clientHeight;
    const splitStart = Math.floor(scrollTop / 60); //开始切割点
    const splitEnd = Math.ceil(endTop / 60); //切割结束点
    list.value = copyList.slice(splitStart,splitEnd); //分割数据
    topEmptyHeight.value = 60*splitStart; //头部空div的高度占位
    bottomEmptyHeight.value = 60*(copyList.length - splitEnd); //底部空div的高度占位

    }
    onMounted(()=>{
    scrollFunc();
    (document.querySelector('.app_wrap') as HTMLElement).addEventListener("scroll",scrollFunc)

    });
    </script>

页面最大高度

一个页面最大高度是22369600px,overflow:auto的内容最大高度也是22369600px,超出这个高度将会置为最大值,超出的部分无法展示

e.returnValue

e.returnValue = false; 输入时是否显示在输入框中,false不展示,此次按键无效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/** 处理输入非数字的输入  **/ 
const keyDownIsNumber = (e:any)=>{
const reg = /^\d+$/;
if(reg.test(e.key) || e.keyCode ===8 || e.keyCode ===46){
e.returnValue = true;
}else{
console.log('不是数字');
e.returnValue = false;
}
}
/** 处理中文输入,使用replace替换 **/
const inputChange = (e:any)=>{
const reg = /^\d+$/;
if(!reg.test(e.data)){
console.log('no number');
input.value.innerText = input.value.innerText.replace(/[^\d]/g,'')
}
}

html结构

1
<div class="text-box" @paste="pasteMsg" @keypress="keyDownIsNumber" ref="input"  @input="inputChange" contenteditable="true"></div>

div[contenteditable= true]时,不允许粘贴格式,只粘贴文字

  • 方法好像有点古老了,2022/4/14测试,能用.说不定某天,就用不了了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    document.querySelector('div[contenteditable="true"]').addEventListener("paste", function(e) {
    e.stopPropagation();
    e.preventDefault();
    var text = '', event = (e.originalEvent || e);
    if (event.clipboardData && event.clipboardData.getData) {
    text = event.clipboardData.getData('text/plain');
    } else if (window.clipboardData && window.clipboardData.getData) {
    text = window.clipboardData.getData('Text');
    }
    if (document.queryCommandSupported('insertText')) {
    document.execCommand('insertText', false, text);
    } else {
    document.execCommand('paste', false, text);
    }
    });

    参考文档:https://blog.csdn.net/qq_32013641/article/details/100575309

  • 本文标题:js项目优化
  • 本文作者:邵预鸿
  • 创建时间:2022-04-13 10:02:11
  • 本文链接:/images/logo.jpg2022/04/13/js项目优化/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!