Blazor/Hybird 触屏下单程序调优笔记

2024-05-10 09:52

本文主要是介绍Blazor/Hybird 触屏下单程序调优笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

环境 Blazor Net8.0 + FreeSql + Bootstrap Blazor 组件

以下都是自己瞎琢磨的和官网资料搬运,肯定有不少错漏和不合理的地方,非常希望各位大佬评论区给我建议和意见.

1. 组件化需要提升渲染性能的组件,例如触摸屏显示每个商品下单数量的商品列表

避免不必要地呈现组件子树, 执行一些初始化渲染后设置按需渲染, 外部控制按需渲染参数


//按需渲染
[Parameter]
public bool RenderQuantity { get; set; } = true;protected override bool ShouldRender() =>  RenderQuantity; protected override void OnAfterRender(bool firstRender)
{if (firstRender){//执行一些初始化渲染后设置按需渲染你的初始化渲染();StateHasChanged();RenderQuantity = false;}
}protected override async Task OnParametersSetAsync()
{if (RenderQuantity){_ = Task.Run(async () =>{await Task.Delay(500);RenderQuantity = false;});}
}

调用的页面,添加 RenderQuantity 控制渲染数量变化时机. 避免 StateHasChanged() 执行后渲染子组件.

<OrdersMenuList OrderID="@OrderID" RenderQuantity="@RenderQuantity"Refresh="@RefreshOrdersMenuList"
/>private bool RenderQuantity { get; set; }

2. API和UI分离: 例如更新订单数量,操作内存数据渲染到UI,不要等待后台查询订单详单列表后在刷新UI. 异步执行后台服务更新订单数量.

UI 更新数量

Task UpdateQuantity(string userCode, int thisQuantity= 1)
{//更新订单数量,操作内存数据,不查询数据库,提高性能. API和UI分离var itemOrdersMenu = OrdersMenu.Where(a => a.UserCode == userCode).FirstOrDefault();if (itemOrdersMenu != null){itemOrdersMenu.Quantity = thisQuantity;RenderQuantity = true;} _ = Task.Run(async () =>{//更新订单数量,返回合计var newOrderdetailsDto = DataService.UpdateQuantity(userCode,thisQuantity);if (newOrderdetailsDto.ForceQuantity!=null){//处理脏数据问题,更新订单数量为强制数量item.Quantity = newOrderdetailsDto.ForceQuantity.Value;if (itemOrdersMenu != null){itemOrdersMenu.Quantity = newOrderdetailsDto.ForceQuantity;RenderQuantity = true; }await InvokeAsync(StateHasChanged);}});return Task.CompletedTask;
}

Tips: 对于长时间不操作的订单界面,例如收银台桌面程序(Blazor/Blazor Hybird), 可以设置一个 UI 更新数量定时器, 例如间隔5分钟重新刷新整页.

3. 脏数据: 因为是多终结点程序(PC浏览器/手机浏览器/PDA/桌面版),不可避免存在脏数据问题. 需要变更单行订单数量刷新UI后, 获取后台单行订单数量,比对,有异常则重新执行 RenderQuantity 或 StateHasChanged 更新单行订单数量.

4. 服务端不要直接更新订单数量,改为原子操作, 采用 a.Quantity = a.Quantity + thisQuantity 方式

服务端 DataService.UpdateQuantity 方法:

fsql.Update<ResOrderDetails>().Set(a => new ResOrderDetails(){Quantity = a.Quantity + thisQuantity}).Where(a => a.OrderID == orderID && a.UserCode == userCode).ExecuteAffrows();

5. Button 尽可能使用 OnClickWithoutRender 方法: 点击按钮时触发此事件并且不刷新当前组件,用于提高性能时使用.

6. 使用 CascadingValue 组件具有可选的 IsFixed 参数

  • 如果 IsFixed 为 false(默认值),则级联值的每个接收方都会将订阅设置为接收更改通知。 由于订阅跟踪,每个 [CascadingParameter] 的开销大体上都要比常规 [Parameter] 昂贵。

  • 如果 IsFixed 为 true(例如,),则接收方会接收初始值,但不会将订阅设置为接收更新。 每个 [CascadingParameter] 都是轻型的,并不比常规 [Parameter] 昂贵。

如果有大量其他组件接收级联值,则将 IsFixed 设置为 true 可提高性能。 只要有可能,就应将级联值的 IsFixed 设置为 true。 当提供的值不会随时间而改变时,可以将 IsFixed 设置为 true。

在组件将 this 作为级联值传递时,也可以将 IsFixed 设置为 true:

<CascadingValue Value="this" IsFixed="true"><SomeOtherComponents>
</CascadingValue>

7. 不要过快触发事件

某些浏览器事件极频繁地触发。 例如,onmousemove 和 onscroll 每秒可以触发数十或数百次。 在大多数情况下,不需要经常执行 UI 更新。 如果事件触发速度过快,可能会损害 UI 响应能力或消耗过多的 CPU 时间。

请考虑使用 JS 互操作来注册不太频繁触发的回调,而不是使用快速触发的本机事件。 例如,以下组件显示鼠标的位置,但每 500 毫秒最多只能更新一次:

@implements IDisposable
@inject IJSRuntime JS<h1>@message</h1><div @ref="mouseMoveElement" style="border:1px dashed red;height:200px;">Move mouse here
</div>@code {private ElementReference mouseMoveElement;private DotNetObjectReference<MyComponent>? selfReference;private string message = "Move the mouse in the box";[JSInvokable]public void HandleMouseMove(int x, int y){message = $"Mouse move at {x}, {y}";StateHasChanged();}protected override async Task OnAfterRenderAsync(bool firstRender){if (firstRender){selfReference = DotNetObjectReference.Create(this);var minInterval = 500;await JS.InvokeVoidAsync("onThrottledMouseMove", mouseMoveElement, selfReference, minInterval);}}public void Dispose() => selfReference?.Dispose();
}

相应的 JavaScript 代码会注册用于鼠标移动的 DOM 事件侦听器。 在此示例中,事件侦听器使用 Lodash 的 throttle 函数来限制调用速率:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
<script>function onThrottledMouseMove(elem, component, interval) {elem.addEventListener('mousemove', _.throttle(e => {component.invokeMethodAsync('HandleMouseMove', e.offsetX, e.offsetY);}, interval));}
</script>

8. 使用缓存

private ConcurrentDictionary<TabItem, bool> LazyTabCache { get; } = new();private RenderFragment RenderTabItemContent(TabItem item) => builder =>
{if (item.IsActive){var content = _errorContent ?? item.ChildContent;builder.AddContent(0, content);_errorContent = null;if (IsLazyLoadTabItem){LazyTabCache.AddOrUpdate(item, _ => true, (_, _) => true);}}else if (!IsLazyLoadTabItem || item.AlwaysLoad || LazyTabCache.TryGetValue(item, out var init) && init){builder.AddContent(0, item.ChildContent);}
};
private RenderFragment? _errorContent;
private static readonly ConcurrentDictionary<Type, UrlValueConstraint> _cachedInstances = new();if (!_cachedInstances.TryGetValue(targetType, out result))
{result = Create(targetType);if (result is null){return false;}_cachedInstances.TryAdd(targetType, result);
}

学习资料

Blazor 性能最佳做法

按需渲染,手动管理 UI 刷新

这篇关于Blazor/Hybird 触屏下单程序调优笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个