web前端之web前端

发布时间:2024年01月05日


web前端之原生实现分时函数、分时间段渲染页面,而不是等到所有操作都执行结束才渲染页面、提高用户体验

前言

当前需要向页面插入十万个div元素,如果使用普通的渲染方式,会造成延迟。这时候就需要通过分时函数来实现渲染了。


html

<div class="w_680 d_f jc_sb">
    <div class="d_f fd_c ai_c">
        <button onclick="handleInsert()">插入1万个元素(原始写法)</button>

        <div id="idOld"></div>
    </div>

    <div class="d_f fd_c ai_c">
        <button onclick="handleOptimize()">插入1万个元素(优化后的写法)</button>

        <div id="idOptimize"></div>
    </div>
</div>

原始写法

function handleInsert() {
    let idOld = document.querySelector('#idOld'),
        datas = Array.from({ length: 100000 }, (_, i) => i + 1);

    for (const item of datas) {
        const div = document.createElement('div');

        div.textContent = item;
        idOld.appendChild(div);
    }
}

优化方式一(参数归一化)

function handleOptimize() {
    let datas = Array.from({ length: 100000 }, (_, i) => i + 1),
        idOptimize = document.querySelector('#idOptimize'),
        taskHandler = (item, i) => {
            const div = document.createElement('div');
            
            div.textContent = item;
            idOptimize.appendChild(div);
        };

    performChunk(datas, taskHandler);
    // performChunk(100000, taskHandler);
}

function performChunk(datas, taskHandler) {
	// 参数归一化
    if (typeof datas === 'number') datas = Array.from({ length: datas }, (_, i) => i + 1);
    if (datas.length === 0) return false;

    let i = 0;

    function _run() {
        if (i >= datas.length) return false;

        requestIdleCallback((idle) => {
            while (idle.timeRemaining() > 0 && i < datas.length) {
                taskHandler(datas[i], i);

                i++;
            }

            _run();
        });
    }

    _run();
}

优化方式二(当浏览器不支持requestIdleCallback方法的时候)

function handleOptimize() {
    let datas = Array.from({ length: 100000 }, (_, i) => i + 1),
        idOptimize = document.querySelector('#idOptimize'),
        taskHandler = (item, i) => {
            const div = document.createElement('div');
            
            div.textContent = item;
            idOptimize.appendChild(div);
        },
        scheduler = (task) => {
            setTimeout(() => {
                const start = Date.now();
                task(() => Date.now() - start < 50);
            }, 100);
        };

    performChunk(datas, taskHandler, scheduler);
}

function performChunk(datas, taskHandler, scheduler) {
    if (typeof datas === 'number') datas = Array.from({ length: datas }, (_, i) => i + 1);
    if (datas.length === 0) return false;

    let i = 0;

    function _run() {
        if (i >= datas.length) return false;

        scheduler((isGoOn) => {
            while (isGoOn() > 0 && i < datas.length) {
                taskHandler(datas[i], i);

                i++;
            }

            _run();
        });
    }

    _run();
}

优化方式三(判断环境)

function handleOptimize() {
    let datas = Array.from({ length: 100000 }, (_, i) => i + 1),
        idOptimize = document.querySelector('#idOptimize'),
        taskHandler = (item, i) => {
            const div = document.createElement('div');
            
            div.textContent = item;
            idOptimize.appendChild(div);
        }

    browserPerformChunk(datas, taskHandler);
}

function browserPerformChunk(datas, taskHandler) {
    const scheduler = (task) => {
        requestIdleCallback((idle) => {
            task(() => idle.timeRemaining() > 0);
        })
    };

    performChunk(datas, taskHandler, scheduler);
}

function performChunk(datas, taskHandler, scheduler) {
    if (typeof datas === 'number') datas = Array.from({ length: datas }, (_, i) => i + 1);
    if (datas.length === 0) return false;

    let i = 0;

    function _run() {
        if (i >= datas.length) return false;

        scheduler((isGoOn) => {
            while (isGoOn() > 0 && i < datas.length) {
                taskHandler(datas[i], i);

                i++;
            }

            _run();
        });
    }

    _run();
}

解析

待定…


web前端之原生实现树形目录结构、一维数组生成多维数组、无限级菜单目录

html

<div id="menuBox"></div>

JavaScript

mainInit();

// 数据处理
// 扁平数组结构转换成JSON树形结构
function mainInit() {
    // 源数据
    let data = [
        { id: 5, parentId: 2, name: "目录1-1-1", },
        { id: 1, parentId: 0, name: "目录1", },
        { id: 13, parentId: 9, name: "目录2-2-3", },
        { id: 3, parentId: 1, name: "目录1-2", },
        { id: 2, parentId: 1, name: "目录1-1", },
        { id: 12, parentId: 9, name: "目录2-2-2", },
        { id: 4, parentId: 1, name: "目录1-3", },
        { id: 7, parentId: 0, name: "目录2", },
        { id: 9, parentId: 7, name: "目录2-2", },
        { id: 6, parentId: 2, name: "目录1-1-2", },
        { id: 11, parentId: 9, name: "目录2-2-1", },
        { id: 8, parentId: 7, name: "目录2-1", },
        { id: 10, parentId: 7, name: "目录2-3", },
    ];

    // 构造一个新对象
    // 对象的属性名是id值
    // 对象的属性值是数组对应项的值
    let map = {};
    data.forEach(item => {
        map[item.id] = item;
    });
    const result = [];
    data.forEach(item => {
        const parent = map[item.parentId];
        if (parent) {
            // 如果有children则push数据到children中
            // 如果没有就新建一个空的children数组
            // 然后再push数据
            parent.children = parent.children || [];
            parent.children.push(item);
        } else {
            // 在本例中
            // else只会进入两次
            // 也是最外层目录
            result.push(item);
        }
    });

    const root = document.getElementById('menuBox');

    createMenu(result, root);
}

// 生成标签元素
function createMenu(data, root) {
    if (!data.length) throw new Error('出错啦');

    data.forEach(item => {
        const detailsEle = document.createElement('details');
        const summaryEle = document.createElement('summary');
        const span = document.createElement('span');
        span.innerHTML = item.name;
        summaryEle.appendChild(span);
        detailsEle.appendChild(summaryEle);
        root.appendChild(detailsEle);

        if (item.children?.length) createMenu(item.children, detailsEle);
    });
}

CSS

null
文章来源:https://blog.csdn.net/weixin_51157081/article/details/124829791
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。