当前位置: 首页 > news >正文

前端 性能优化 (图片与样式篇)

文章目录

  • 前端能够做哪些图片优化?
    • 1、减小图片体积
    • 2、图片缓存
      • 服务工作线程 (Service Workers)缓存
      • IndexDB缓存图片
      • LocalStorage缓存
    • 3、图片懒加载
      • 使用 loading="lazy" 属性
    • 4、不同分辨率下使用不同的图片
    • 5、使用webp格式的图片
    • 6、配置图片CDN
    • 7、减少图片和动图的使用
  • css样式如何优化?
    • 1、关键css优先,非关键css等页面加载完成再加载或引入
    • 2、使用 CSS 预处理器和后处理器
    • 3、利用 CSS 变量
    • 4、减少和优化选择器的复杂性
    • 5、删除无用的 CSS
    • 6、利用缓存
    • 7、编写代码时尽量减少重排和重绘

前端能够做哪些图片优化?

1、减小图片体积

压缩图片可以减小文件大小,提升页面加载速度。可以使用工具如 TinyPNG 或 ImageOptim 来优化图片。

2、图片缓存

浏览器缓存是最基础的前端缓存方式。通过设置HTTP响应头,指定缓存策略,可以控制浏览器对图片资源的缓存行为。

Cache-Control: 设置图片的缓存时长。例如,Cache-Control: max-age=31536000表示缓存一年。
Expires: 指定缓存过期日期,配合Cache-Control使用。
ETag 和 Last-Modified: 标记资源的版本号或最后修改时间,当浏览器再次请求该资源时,通过对比判断是否需要重新下载。

这些头信息可以在服务器端配置,常用于CDN或静态资源服务器。

服务工作线程 (Service Workers)缓存

Service Workers是一种更高级的缓存方式,通过注册Service Worker脚本,可以拦截图片请求并从缓存中返回内容。可以在应用初始化时加载图片资源并存储在Service Worker的缓存中,后续请求可以直接读取缓存内容。

// 安装阶段(Install Event),当 Service Worker 安装时触发
self.addEventListener('install', event => {// 使用 event.waitUntil 确保安装过程完成后才继续执行后续的步骤event.waitUntil(// 打开一个名为 'image-cache' 的缓存存储caches.open('image-cache').then(cache => {// 将图片资源添加到缓存中return cache.addAll(['/images/photo1.jpg', // 图片1'/images/photo2.jpg', // 图片2// 更多图片资源可以添加在这里...]);}));
});// 激活阶段,拦截网络请求并返回缓存数据(Fetch Event)
self.addEventListener('fetch', event => {// 判断请求是否是图片资源if (event.request.destination === 'image') {// event.respondWith 接受一个 Promise,返回响应数据event.respondWith(// 尝试从缓存中匹配请求caches.match(event.request).then(response => {// 如果缓存中存在图片,直接返回缓存的响应return response || // 如果缓存中没有对应的图片,则执行网络请求fetch(event.request).then(fetchResponse => {// 一旦网络请求返回图片数据,就将其缓存return caches.open('image-cache').then(cache => {// 将网络获取的图片存入缓存cache.put(event.request, fetchResponse.clone());// 返回从网络获取的图片响应return fetchResponse;});});}));}
});

IndexDB缓存图片

IndexedDB一个适合存储较大数据(如图片二进制数据)的浏览器数据库。要存储图片,我们通常将图片文件转换为 Blob(二进制大对象),并存入 IndexedDB。这样,在后续需要加载缓存图片时,可以从 IndexedDB 中检索 Blob,然后将其转化为 URL 以加载到页面中。

初始化 IndexedDB 数据库和对象存储

// 初始化 IndexedDB
function openDatabase() {return new Promise((resolve, reject) => {const request = indexedDB.open('imageCacheDB', 1);// 创建或更新数据库时触发request.onupgradeneeded = function(event) {const db = event.target.result;if (!db.objectStoreNames.contains('images')) {db.createObjectStore('images'); // 创建名为 "images" 的对象存储}};request.onsuccess = function(event) {resolve(event.target.result); // 成功打开数据库};request.onerror = function(event) {reject(event.target.error); // 打开数据库失败};});
}

将图片存储到 IndexedDB 中

// 将图片 Blob 存入 IndexedDB
function cacheImage(url, blob) {openDatabase().then(db => {const transaction = db.transaction('images', 'readwrite');const store = transaction.objectStore('images');store.put(blob, url); // 使用图片 URL 作为键transaction.oncomplete = () => {console.log('Image cached in IndexedDB');};}).catch(error => {console.error('Failed to cache image:', error);});
}// 获取图片并缓存
function fetchAndCacheImage(url) {fetch(url).then(response => response.blob()).then(blob => {cacheImage(url, blob); // 缓存图片}).catch(error => {console.error('Failed to fetch image:', error);});
}

从 IndexedDB 中读取图片并显示
当需要显示图片时,可以从 IndexedDB 读取 Blob 数据并生成一个 URL 给 标签使用

// 从 IndexedDB 中获取图片 Blob
function getCachedImage(url) {return new Promise((resolve, reject) => {openDatabase().then(db => {const transaction = db.transaction('images', 'readonly');const store = transaction.objectStore('images');const request = store.get(url);request.onsuccess = function(event) {if (event.target.result) {resolve(event.target.result); // 返回图片 Blob} else {reject('Image not found in cache');}};request.onerror = function() {reject('Failed to retrieve image from IndexedDB');};});});
}// 使用缓存图片显示到页面
function displayImageFromCache(url, imgElementId) {getCachedImage(url).then(blob => {const imgURL = URL.createObjectURL(blob);document.getElementById(imgElementId).src = imgURL;}).catch(error => {console.error('Error displaying cached image:', error);});
}// 示例调用
const imageUrl = 'https://example.com/image.jpg';
fetchAndCacheImage(imageUrl); // 首次获取并缓存
displayImageFromCache(imageUrl, 'myImage'); // 从缓存中显示图片

LocalStorage缓存

// 保存图片到 localStorage
function cacheImage(url) {fetch(url).then(response => response.blob()).then(blob => {const reader = new FileReader();reader.onload = function () {localStorage.setItem('cachedImage', reader.result); // 将Base64数据存入localStorage};reader.readAsDataURL(blob);});
}

3、图片懒加载

懒加载和占位图也是提升前端图片加载性能的技巧,虽然不算是严格意义的缓存。懒加载会等到图片在视窗中出现时才开始加载,减少初始页面加载的资源量,占位图则在图片未加载完成前提供一个小尺寸、模糊的占位图,让页面看起来更平滑。

假设你有多个图片,添加 data-src 属性存储图片的实际 URL,src 属性设置为占位符(比如一张模糊的小图或空白图片),这样只有当图片进入视口时,才会加载实际的图片。

<img class="lazy" data-src="https://example.com/photo1.jpg" src="placeholder.jpg" alt="Image 1" />
<img class="lazy" data-src="https://example.com/photo2.jpg" src="placeholder.jpg" alt="Image 2" />
<img class="lazy" data-src="https://example.com/photo3.jpg" src="placeholder.jpg" alt="Image 3" />
<!-- 更多图片 -->

使用 IntersectionObserver 来监视图片是否进入视口,如果进入视口,就把 data-src 的值赋给 src,从而触发图片加载。

// 创建一个 IntersectionObserver 实例,监视图片是否进入视口
const lazyLoadImages = document.querySelectorAll('img.lazy');const imageObserver = new IntersectionObserver((entries, observer) => {entries.forEach(entry => {// 如果图片进入视口if (entry.isIntersecting) {const image = entry.target;// 将 data-src 的真实图片 URL 赋值给 src 属性image.src = image.dataset.src;// 一旦图片加载完毕,停止观察该图片image.onload = () => {image.classList.remove('lazy'); // 可选:移除懒加载样式};observer.unobserve(image); // 停止观察已加载的图片}});
}, {rootMargin: '0px', // 可选:在视口边缘触发加载(当图片接近视口时开始加载)threshold: 0.1  // 可选:当图片至少 10% 显示时开始加载
});// 观察所有懒加载图片
lazyLoadImages.forEach(image => {imageObserver.observe(image);
});

代码解释
IntersectionObserver:
创建 IntersectionObserver 实例来观察图片元素是否进入视口。IntersectionObserver 会异步监测指定元素与视口的交集变化。
entries 是一个包含所有监测元素的数组,entry.target 是当前进入视口的图片元素。
isIntersecting 属性表示图片是否已经进入视口(或者与视口重叠)。当该属性为 true 时,图片就进入了视口。
rootMargin:

rootMargin 是视口的扩展区域。当图片距离视口边缘一定距离时就触发加载。可以使用类似 CSS 的值(如 10px 0px)。
threshold:

threshold 定义了当多少比例的图片进入视口时触发懒加载,0.1 表示图片至少 10% 进入视口时触发加载。
image.onload:

一旦图片加载完毕,可以执行一些操作,比如移除懒加载样式(如 lazy 类),表示图片已成功加载。
observer.unobserve(image):

加载完图片后,停止观察该图片,优化性能。

使用 loading=“lazy” 属性

使用 loading=“lazy” 属性可以非常简单地实现图片的懒加载。浏览器就会在图片进入视口时自动加载它。这是原生浏览器对懒加载的支持,无需额外的 JavaScript 代码。这个属性已经被大多数现代浏览器支持。

<img src="image1.jpg" alt="Image 1" loading="lazy" />
<img src="image2.jpg" alt="Image 2" loading="lazy" />
<img src="image3.jpg" alt="Image 3" loading="lazy" />

4、不同分辨率下使用不同的图片

<picture><source media="(max-width: 600px)" srcset="image-small.jpg"><source media="(max-width: 1200px)" srcset="image-medium.jpg"><img src="image-large.jpg" alt="Responsive Image">
</picture>

或者

<img src="image-small.jpg" srcset="image-small.jpg 500w, image-medium.jpg 1000w, image-large.jpg 2000w" sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw" alt="Responsive Image">

5、使用webp格式的图片

使用 WebP 格式(如果浏览器支持)可以显著减小图片文件大小,从而提高加载速度。
可以通过 元素来根据浏览器支持选择图片格式。

<picture><source srcset="image.webp" type="image/webp"><img src="image.jpg" alt="Responsive Image">
</picture>

6、配置图片CDN

  1. 选择和设置 CDN 服务提供商
    首先,选择一个合适的 CDN 服务提供商。常见的 CDN 提供商包括:

Cloudflare
AWS CloudFront
Fastly
KeyCDN
Alibaba Cloud CDN
Tencent Cloud CDN

  1. 上传图片到 CDN
    选择图片存储方式:

存储在对象存储服务中:你可以使用云服务提供商的对象存储(如 Amazon S3、Alibaba OSS、腾讯云 COS)来存储图片文件,并通过 CDN 进行分发。通过这种方式,你可以确保文件安全,并允许 CDN 节点从这些存储服务获取资源。

直接通过 CDN 上传:有些 CDN 服务商允许直接将图片资源上传到其 CDN 网络。

上传图片:将图片上传到选定的存储服务(如 S3),并记录图片的 URL。

  1. 配置 CDN
    创建 CDN 加速域名:

登录你的 CDN 提供商控制台,创建一个加速域名(例如 cdn.yoursite.com)。
配置源站点(通常是你存储图片的服务器或对象存储服务)。源站点是 CDN 获取图片资源的地方。
设置缓存策略:

配置缓存时间(TTL,生存时间),指示 CDN 节点在没有更新时缓存图片的时间。一般情况下,静态资源(如图片)可以设置较长的缓存时间,如一周或一月。
启用 图片优化 功能(如果支持),以便根据设备类型和网络状况自动调整图片的大小和质量。
4. 修改图片 URL
在网页中引用 CDN 提供的图片 URL。假设你的 CDN 域名是 cdn.yoursite.com,你可以像这样引用图片:

<img src="https://cdn.yoursite.com/images/photo1.jpg" alt="Image 1" />
<img src="https://cdn.yoursite.com/images/photo2.jpg" alt="Image 2" />

将原本直接指向服务器的图片 URL 替换为指向 CDN 的图片 URL。

7、减少图片和动图的使用

这可能需要有较强的canvas功底,和较多的开发时间。但的确是能大幅度优化图片的方案。
能用css实现的简单动画,就别用动态图片。能用css实现的样式,就别用图片。

css样式如何优化?

1、关键css优先,非关键css等页面加载完成再加载或引入

在优化 CSS 加载时,遵循“先加载关键 CSS,再懒加载非关键 CSS”的策略,可以显著提升页面加载速度。

1、提取关键css
这就要分析一个页面的功能样式,是否可以分离为进入页面就要展示的css和等用户操作后才展示的css

<style>/* 关键 CSS */body { margin: 0; font-family: Arial, sans-serif; }header { background-color: #333; color: white; padding: 10px; }/* 添加更多关键样式 */
</style>

2、 懒加载非关键 CSS
如果页面有复杂特效(如动画、hover 状态、特定 JavaScript 动画等),可以将这些 CSS 动效代码延迟到页面加载完成后再应用,从而加快页面初始渲染速度。通过在 标签中添加 media=“print” 和 onload 事件来实现非阻塞加载。

<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">

3、使用 rel=“preload” 优化 CSS 加载
对于需要优先加载的非关键 CSS,可以用 preload 指令提前加载,提高资源加载效率。

<link rel="preload" href="important.css" as="style" onload="this.οnlοad=null; this.rel='stylesheet'">

除了上述处理非关键css,还可以使用js直接引入

window.addEventListener('load', function() {let link = document.createElement('link');link.rel = 'stylesheet';link.href = 'additional-styles.css';document.head.appendChild(link);
});

2、使用 CSS 预处理器和后处理器

预处理器如 SCSS、LESS 可以更简洁地编写和管理 CSS。
后处理器如 PostCSS 可以根据浏览器的兼容性要求,自动添加前缀、压缩代码、处理变量等。

3、利用 CSS 变量

使用 CSS 变量可以减少重复代码,便于动态调整样式。比如色彩、尺寸等样式都可以用 CSS 变量来定义,从而减少代码量并优化可维护性。

:root {--main-color: #4CAF50;--padding: 10px;
}body {color: var(--main-color);padding: var(--padding);
}

4、减少和优化选择器的复杂性

尽量使用简单的选择器,避免使用深层嵌套或复杂选择器。深层嵌套和通配符(如 *)会增加浏览器的解析成本。

5、删除无用的 CSS

使用工具如 PurgeCSS 或 UnCSS 来移除未使用的 CSS 代码。这样可以极大地减少 CSS 文件体积,提高加载速度。

6、利用缓存

为 CSS 文件设置长缓存时间。通过配置缓存策略,浏览器可以在多次访问时直接加载缓存中的 CSS 文件,避免重新请求 (前端的缓存策略,无非就是 Localstorage,service work)

7、编写代码时尽量减少重排和重绘

尽量避免频繁修改布局属性(如 width、height、padding),减少重绘和重排。可以使用 transform、opacity 等性能友好的属性,进行页面更新。
transform 调用的GPU来实现渲染 ,减少使用translate

相关文章:

前端 性能优化 (图片与样式篇)

文章目录 前端能够做哪些图片优化?1、减小图片体积2、图片缓存服务工作线程 (Service Workers)缓存IndexDB缓存图片LocalStorage缓存 3、图片懒加载使用 loading"lazy" 属性 4、不同分辨率下使用不同的图片5、使用webp格式的图片6、配置图片CDN7、减少图片和动图的使…...

A021基于Spring Boot的自习室管理和预约系统设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…...

量化交易系统开发-实时行情自动化交易-Okex市场深度数据

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来聊聊基于Okex交易所API获取市场深…...

Qt教程(006):QMainWindow主窗口

文章目录 6.1 菜单栏和工具栏6.2 状态栏6.3 铆接部件QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏 (menu bar)、多个工具栏 (tools bar)、多个错接部件 (dock widgets)、一个状态栏 (status bar)及一个中心部件 (central widget),是许多应用程序的基础,…...

测试用例的设计

测试用例的概念 什么是测试⽤例&#xff1f; 测试⽤例&#xff08;Test Case&#xff09;是为了实施测试⽽向被测试的系统提供的⼀组集合&#xff0c;这组集合包含&#xff1a;测试环境、操作步骤、测试数据、预期结果等要素。 比如我们买回来了一个新电视&#xff0c;要进行测…...

代码随想录训练营Day20 | 93.复原IP地址 - 78.子集 - 90.子集II

93.复原IP地址 题目链接&#xff1a;93.复原IP地址思路&#xff1a; 做法和分割回文字符串那题类似&#xff0c;是对字符串进行切割&#xff1b;本题需要多几个条件&#xff0c;就是每次回溯字符串的长度最多三位&#xff0c;字符串对应的数值必须 在[0, 255]之间&#xff0c;…...

[Meachines] [Medium] MonitorsThree SQLI+Cacti-CMS-RCE+Duplicati权限提升

信息收集 IP AddressOpening Ports10.10.11.30TCP:22&#xff0c;80 $ nmap -p- 10.10.11.30 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | …...

Elasticsearch专栏-4.es基本用法-查询api

es基本用法-查询api 说明查询所有某一字段匹配查询多字段查询bool查询范围查询精确查询正则匹配模糊查询结果处理 说明 es对数据的检索&#xff0c;总结下来就是两部分&#xff0c;即查询和处理。查询指的是查找符合条件的数据&#xff0c;包括查询所有、匹配查询、布尔查询、…...

jmeter基础04_设置外观和字体

1、设置外观 默认跟随系统风格&#xff0c;你可以试一试选择自己喜欢的风格。&#xff08;浅色模式/深色模式…&#xff09; 操作&#xff1a;菜单栏“选项” - “外观”&#xff0c;选择外观风格。 2、放缩显示比例&#xff08;重启后复原&#xff09; “选项” - “放大/缩小…...

重构代码之替换参数为显式方法

替换参数为显式方法 是一种重构技术&#xff0c;旨在通过替换方法参数来创建更清晰、更具可读性的代码。当一个方法包含标志性参数时&#xff0c;该方法的行为可能会根据参数的不同而发生改变。这样会导致方法的调用方式不够明确&#xff0c;因为调用者不一定能直观地知道每个参…...

三菱QD77MS定位模块速度限制功能

“速度限制功能”是控制中的指令速度超过“速度限制值”的情况下&#xff0c;将指令速度限制在“速度限制值”的设置范围内的功能。 [1]速度限制功能与各控制的关系 速度限制功能”与各控制的关系如下所示。 [3]速度限制功能的设置方法 使用“速度限制功能”时&#xff0c;在如…...

Axure PR 9 多级下拉选择器 设计交互

​ 大家好&#xff0c;我是大明同学。 Axure选择器是一种在交互设计中常用的组件&#xff0c;这期内容&#xff0c;我们来探讨Axure中多级下拉选择器设计与交互技巧。 下拉列表选择输入框元件 创建选择输入框所需的元件 1.在元件库中拖出一个矩形元件。 2.选中矩形元件&…...

Java基础使用②Java数据变量和类型+小知识点

目录 1. Java小知识点 1.1 Java注释 1.2 Java标识符命名 1.3 Java关键字 2. 字面常量和数据变量 2.1 字面常量 2.2 数据类型 3.变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.4 浮点型变量 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.8 类型提升 4. 字符…...

从 HTTP 到 HTTPS 再到 HSTS:网站安全的演变与实践

近年来&#xff0c;随着域名劫持、信息泄漏等网络安全事件的频繁发生&#xff0c;网站安全变得越来越重要。这促使网络传输协议从 HTTP 发展到 HTTPS&#xff0c;再到 HSTS。本文将详细介绍这些协议的演变过程及其在实际应用中的重要性。 一、HTTP 协议 1.1 HTTP 简介 HTTP&…...

Qt的跨平台介绍

在实际开发中&#xff0c;Ubuntu 使用 Qt 编译并跨平台到 Windows 的场景并不算特别常见&#xff0c;但在一些特定情况下是非常有用的&#xff0c;尤其是在开发需要支持多个平台的跨平台应用时。这种方式的应用主要体现在以下几个方面&#xff1a; Linux 环境下开发 Windows 应…...

数据库DQL

DQL 语法 SELECT字段列表 FROM表名列表 WHERE条件列表 GROUP BY分组字段列表 HAVING分组后条件列表 ORDER BY排序字段列表 LIMIT分页参数 基本查询 查询多个字段 SELECT 字段1,字段2,字段3,... FROM 表名; SELECT * FROM 表名; 设置别名 SELECT 字段1 [AS 别名1],字段2 …...

Am I Isolated:一款安全态势基准测试工具

基于Rust的容器运行时扫描器作为一个容器运行&#xff0c;检测用户容器运行时隔离中的漏洞。 它还提供指导&#xff0c;帮助用户改善运行时环境&#xff0c;以提供更强的隔离保证。 容器的现状是它们并不包含&#xff08;隔离&#xff09;。 容器隔离的缺失在云原生环境中有…...

Unity性能优化 -- 性能分析工具

Stats窗口Profiler窗口Memory Profiler其他性能分析工具&#xff08;Physica Debugger 窗口&#xff0c;Import Activity 窗口&#xff0c;Code Coverage 窗口&#xff0c;Profile Analyzer 窗口&#xff0c;IMGUI Debugger 窗口&#xff09; Stats 统级数据窗口 game窗口 可…...

【微信小程序】基本语法

一、导入小程序 选择代码目录 项目配置文件 appid 当前小程序的 AppIDprojectname 当前小程序的项目名称 变更AppID&#xff08;视情况而定&#xff0c;如果没有开发权限时需要变更成个人的 AppID&#xff09; 二、模板语法 在页面中渲染数据时所用到的一系列语法叫做模板…...

go中的类型断言详解

在Go语言中&#xff0c;类型断言&#xff08;Type Assertion&#xff09;是一种将接口类型的变量转换为具体类型的机制。类型断言允许我们从接口类型的变量中提取出具体的值&#xff0c;以便访问具体类型的方法或属性。类型断言的语法如下&#xff1a; value, ok : interfaceV…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

6.9-QT模拟计算器

源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...