avalon v5.1发布,性能大幅提高

2024-05-13 21:38

本文主要是介绍avalon v5.1发布,性能大幅提高,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

早在avalon在IE与firefox有较为严重的性能问题,chrome等则由于它们太逆天因此看不出。主要原因是动态插入节点时,each由于一些帮方法考虑不周,结果不得不逐个插入,虽然使用了nextTick进行缓冲,但延迟明显。然后avalon v5把大体的架构完成了,然后重点改良这些方法了。在v5.1中所有延迟都没有了,即便在IE6下也很接近之前在chrome的运行效果。算是一次非常出色的改进。


1, addItemView方法不再逐个复制,逐个插入了。



//原来
 function addItemView(index, item, data) {
        var scopes = data.scopeList;
        var collection = data.collection;
        var parent = data.element;
        var doc = parent.ownerDocument;
        var textNodes = [];
        var scope = createItemModel(index, item, collection, data.args);
        scopes = [scope].concat(scopes)
        for (var node = data.view.firstChild; node; node = node.nextSibling) {
            var clone = node.cloneNode(true);
            if (collection.insertBefore) { //必须插入DOM树,否则下为注释节点添加自定义属性会失败
                parent.insertBefore(clone, collection.insertBefore);
            } else {
                parent.appendChild(clone);
            }
            if (clone.nodeType === 1) {
                scanTag(clone, scopes.concat(), doc); //扫描元素节点
            } else if (clone.nodeType === 3) {
                textNodes.push(clone); //插值表达式所在的文本节点会被移除,创建循环中断(node.nextSibling===null)
            } else if (clone.nodeType === 8) {
                clone.nodeValue = node.nodeValue + "" + index;
                if (!clone.addScope) {
                    clone.$scope = scope;
                    clone.addScope = "addItemView";
                }
                clone.$view = data.view.cloneNode(false);
            }
        }
        avalon.nextTick(function() {
            for (var i = 0; node = textNodes[i++]; ) {
                scanText(node, scopes.concat(), doc); //扫描文本节点
            }
        })
    }
改为


function addItemView(index, item, data) {
    var scopes = data.scopes;
    var list = data.list;
    var parent = data.element;
    var doc = parent.ownerDocument;
    var scope = createItemModel(index, item, list, data.args);
    scopes = [scope].concat(scopes);
    var view = data.view.cloneNode(true);//★★★★
    var textNodes = [];
    var elements = [];
    for (var node = view.firstChild; node; node = node.nextSibling) {
        if (node.nodeType === 1) {
            elements.push(node);
        } else if (node.nodeType === 3) {
            textNodes.push(node);
        } else if (node.nodeType === 8) {
            node.id = node.nodeValue + index; //设置路标
            node.$scope = scope;
            node.$view = view.cloneNode(false);//★★★★
        }
    }
    // parent.insertBefore(el, null) === parent.appendChild(el)
    parent.insertBefore(view, list.place || null);
 
    for (var i = 0; node = elements[i++];) {
        scanTag(node, scopes.concat(), doc); //扫描文本节点
    }
    avalon.nextTick(function() {
        if (!parent.inprocess) {
            parent.inprocess = 1; //作用类似于display:none
            var hidden = parent.hidden; //http://html5accessibility.com/
            parent.hidden = true;//★★★★ 防止reflow
        }
        for (var i = 0; node = textNodes[i++];) {
            scanText(node, scopes.concat(), doc); //扫描文本节点
        }
        if (parent.inprocess) {
            parent.hidden = hidden;
            parent.inprocess = 0;
        }
    })
}
2,新的路标系统:avalon使用一个注释节点来确认每个子模板的起点, 像emberjs则是使用两个script节点, knockout是使用两个 。


//原来
//路标是指每个模板最开头的那个注释节点
    //<!--xxx1--><tag><tag><text><!--xxx2--><tag><tag><text><!--xxx3--><tag><tag><text>
    // 假若 index == 2, 返回<!--xxx2-->
 
    function findIndex(elem, listName, index) {
        for (var node = elem.firstChild; node; node = node.nextSibling) {
            if (node.nodeType === 8 && (node.nodeValue === listName + index)) {
                return node;
            }
        }
    }
 
    //重置所有路标
 
    function resetIndex(elem, name) {
        var index = 0;
        for (var node = elem.firstChild; node; node = node.nextSibling) {
            if (node.nodeType === 8) {
                if (node.nodeValue.indexOf(name) === 0) {
                    if (node.nodeValue !== name + index) {
                        node.nodeValue = name + index;
                        var scope = node.$scope || {};
                        scope.$index = index;
                    }
                    index++;
                }
            }
        }
    }
现在的逻辑简化成这样:


function findIndex(elem, index) { //寻找路标
    for (var node = elem.firstChild; node; node = node.nextSibling) {
        if (node.id === node.nodeValue + index) {//★★★★
            return node;
        }
    }
}
 
function resetIndex(elem, name) { //重置路标
    var index = 0;
    for (var node = elem.firstChild; node; node = node.nextSibling) {
        if (node.nodeType === 8 && node.nodeValue === name) {//★★★★
            if (node.id !== name + index) {
                node.id = name + index;//★★★★
                node.$scope.$index = index;
            }
            index++;
        }
    }
}
3,移除模板的两个函数合并成一个,因此整体代码量都下降了。


//原来
    function removeItemView(node, listName) {
        var nodes = [node];
        var view = node.$view;
        for (var check = node.nextSibling; check; check = check.nextSibling) {
            //遇到下个路标时就断开
            if (check.nodeType === 8 && check.nodeValue.indexOf(listName) === 0) {
                break
            }
            nodes.push(check);
        }
        for (var i = 0; node = nodes[i++]; ) {
            view.appendChild(node);
        }
        return [view, check]; //返回被移除的文档碎片及下一个路标
    }
    //移除each中的多个子视图,返回它们对应的文档碎片集合
 
    function removeItemViews(node, listName, number) {
        var views = [];
        do {
            var array = removeItemView(node, listName);
            if (array[1]) {
                views.push(array[0]);
                node = array[1];
            } else {
                break
            }
        } while (views.length !== number);
        return views;
    }
现在是


function emptyNode(parent) {//它直接用于clear与update方法
    while (parent.firstChild) {
        parent.removeChild(parent.firstChild);
    }
}
function removeItemView(node, id) { 
    var nodes = [node];
    var view = node.$view;
    for (var check = node.nextSibling; check; check = check.nextSibling) {
        if (check.nodeType === 8 && check.id === id) {
            break
        }
        nodes.push(check);
    }
    for (var i = 0; node = nodes[i++];) {
        view.appendChild(node);
    }
    emptyNode(view);//★★★★
    view = null;//★★★★
}
可以到它的主页查看效果!如果有什么好的改进,记得pull request啊!

这篇关于avalon v5.1发布,性能大幅提高的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/986901

相关文章

修复已被利用的高危漏洞! macOS Sequoia 15.6.1发布

《修复已被利用的高危漏洞!macOSSequoia15.6.1发布》苹果公司于今日发布了macOSSequoia15.6.1更新,这是去年9月推出的macOSSequoia操作... MACOS Sequoia 15.6.1 正式发布!此次更新修复了一个已被黑客利用的严重安全漏洞,并解决了部分中文用户反馈的

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

Java慢查询排查与性能调优完整实战指南

《Java慢查询排查与性能调优完整实战指南》Java调优是一个广泛的话题,它涵盖了代码优化、内存管理、并发处理等多个方面,:本文主要介绍Java慢查询排查与性能调优的相关资料,文中通过代码介绍的非... 目录1. 事故全景:从告警到定位1.1 事故时间线1.2 关键指标异常1.3 排查工具链2. 深度剖析:

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon