性能优化问题
提升首屏的加载速度,是前端性能优化中「最重要」的环节,这里笔者梳理出一些 常规且有效
的首屏优化建议
1、路由懒加载
SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文件,「当用户打开首页时,会一次性加载所有的资源」,造成首页加载很慢,降低用户体验
列一个实际项目的打包详情:
-
app.js 初始体积:
1175 KB
-
-
app.css 初始体积:
274 KB
-
将路由全部改成懒加载
// 通过webpackChunkName设置分割后代码块的名字 const Home = () => import(/* webpackChunkName: "home" */ "@/views/home/index.vue"); const MetricGroup = () => import(/* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue"); ………… const routes = [{path: "/",name: "home",component: Home},{path: "/metricGroup",name: "metricGroup",component: MetricGroup},…………]
重新打包后,首页资源拆分为 app.js 和 home.js,以及对应的 css 文件
-
app.js:
244 KB
、 home.js:35KB
app.css:
67 KB
、home.css:15KB
通过路由懒加载,该项目的首页资源压缩约 52%
路由懒加载的原理
懒加载前提的实现:ES6 的动态地加载模块——import()
调用 import() 之处,被作为分离的模块起点,意思是,被请求的模块和它引用的所有子模块,会分离到一个单独的 chunk 中
——摘自《webpack——模块方法》的 import\(\)小节
要实现懒加载,就得先将进行懒加载的子模块分离出来,打包成一个单独的文件
webpackChunkName 作用是 webpack 在打包的时候,对异步引入的库代码(lodash)进行代码分割时,设置代码块的名字。webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中
2、组件懒加载
除了路由的懒加载外,组件的懒加载在很多场景下也有重要的作用
举个 🌰:
home 页面 和 about 页面,都引入了 dialogInfo 弹框组件,该弹框不是一进入页面就加载,而是需要用户手动触发后才展示出来
home 页面示例:
<template><div class="homeView"><p>home 页面</p><el-button @click="dialogVisible = !dialogVisible">打开弹框</el-button><dialogInfo v-if="dialogVisible" /></div>
</template>
<script>
import dialogInfo from '@/components/dialogInfo';
export default {name: 'homeView',components: {dialogInfo}
}
</script>
项目打包后,发现 home.js 和 about.js 均包括了该弹框组件的代码(在 dist 文件中搜索 dialogInfo 弹框组件)
当用户打开 home 页时,会一次性加载该页面所有的资源,「我们期望的是用户触发按钮后,再加载该弹框组件的资源」
这种场景下,就很适合用懒加载的方式引入
弹框组件懒加载:
<script>
const dialogInfo = () => import(/* webpackChunkName: "dialogInfo" */ '@/components/dialogInfo');
export default {name: 'homeView',components: {dialogInfo}
}
</script>
重新打包后,home.js 和 about.js 中没有了弹框组件的代码,该组件被独立打包成 dialogInfo.js,「当用户点击按钮时,才会去加载 dialogInfo.js 和 dialogInfo.css」
最终,使用组件路由懒后,该项目的首页资源进一步减少约 11%
组件懒加载的使用场景
有时资源拆分的过细也不好,可能会造成浏览器 http 请求的增多
总结出三种适合组件懒加载的场景:
1)该页面的 JS 文件体积大,导致页面打开慢,可以通过组件懒加载进行资源拆分,利用浏览器并行下载资源,提升下载速度(比如首页)
2)该组件不是一进入页面就展示,需要一定条件下才触发(比如弹框组件)
3)该组件复用性高,很多页面都有引入,利用组件懒加载抽离出该组件,一方面可以很好利用缓存,同时也可以减少页面的 JS 文件大小(比如表格组件、图形组件等)
3、合理使用 Tree shaking
Tree shaking 的作用:消除无用的 JS 代码,减少代码体积
举个 🌰:
// util.js
export function targetType(target) {return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
}
export function deepClone(target) {return JSON.parse(JSON.stringify(target));
}
项目中只使用了 targetType 方法,但未使用 deepClone 方法,项目打包后,deepClone 方法不会被打包到项目里
tree-shaking 原理:
依赖于 ES6 的模块特性,ES6 模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这就是 tree-shaking 的基础
静态分析就是不需要执行代码,就可以从字面量上对代码进行分析。ES6 之前的模块化,比如 CommonJS 是动态加载,只有执行后才知道引用的什么模块,就不能通过静态分析去做优化,正是基于这个基础上,才使得 tree-shaking 成为可能
Tree shaking 并不是万能的
并不是说所有无用的代码都可以被消除,还是上面的代码,换个写法 tree-shaking 就失效了
// util.js
export default {targetType(target) {return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();},deepClone(target) {return JSON.parse(JSON.stringify(target));}
};// 引入并使用
import util from '../util';
util.targetType(null)
同样的,项目中只使用了 targetType 方法,未使用 deepClone 方法,项目打包后,deepClone 方法还是被打包到项目里
在 dist 文件中搜索 deepClone 方法:
究其原因,export default 导出的是一个对象,「无法通过静态分析判断出一个对象的哪些变量未被使用,所以 tree-shaking 只对使用 export 导出的变量生效」
这也是函数式编程越来越火的原因,因为可以很好利用 tree-shaking 精简项目的体积,也是 vue3 全面拥抱了函数式编程的原因之一
4、骨架屏优化白屏时长
使用骨架屏,可以缩短白屏时间,提升用户体验。国内大多数的主流网站都使用了骨架屏,特别是手机端的项目
SPA 单页应用,无论 vue 还是 react,最初的 html 都是空白的,需要通过加载 JS 将内容挂载到根节点上,这套机制的副作用:会造成长时间的白屏
常见的骨架屏插件就是基于这种原理,在项目打包时将骨架屏的内容直接放到 html 文件的根节点中
使用骨架屏插件,打包后的 html 文件(根节点内部为骨架屏):
同一项目,对比使用骨架屏前后的 FP 白屏时间:
-
无骨架屏:白屏时间
1063ms
-
有骨架屏:白屏时间
144ms
骨架屏确实是优化白屏的不二选择,白屏时间缩短了 86%
骨架屏插件
这里以 vue-skeleton-webpack-plugin
插件为例,该插件的亮点是可以给不同的页面设置不同的骨架屏,这点确实很酷
1)安装
npm i vue-skeleton-webpack-plugin
2)vue.config.js 配置
// 骨架屏
const SkeletonWebpackPlugin = require("vue-skeleton-webpack-plugin");
module.exports = {configureWebpack: {plugins: [new SkeletonWebpackPlugin({// 实例化插件对象webpackConfig: {entry: {app: path.join(__dirname, './src/skeleton.js') // 引入骨架屏入口文件}},minimize: true, // SPA 下是否需要压缩注入 HTML 的 JS 代码quiet: true, // 在服务端渲染时是否需要输出信息到控制台router: {mode: 'hash', // 路由模式routes: [// 不同页面可以配置不同骨架屏// 对应路径所需要的骨架屏组件id,id的定义在入口文件内{ path: /^\/home(?:\/)?/i, skeletonId: 'homeSkeleton' },{ path: /^\/detail(?:\/)?/i, skeletonId: 'detailSkeleton' }]}})]}
}
3)新建 skeleton.js 入口文件
// skeleton.js
import Vue from "vue";
// 引入对应的骨架屏页面
import homeSkeleton from "./views/homeSkeleton";
import detailSkeleton from "./views/detailSkeleton";export default new Vue({components: {homeSkeleton,detailSkeleton,},template: `<div><homeSkeleton id="homeSkeleton" style="display:none;" /><detailSkeleton id="detailSkeleton" style="display:none;" /></div>`,
});
5、长列表虚拟滚动
首页中不乏有需要渲染长列表的场景,当渲染条数过多时,所需要的渲染时间会很长,滚动时还会造成页面卡顿,整体体验非常不好
「虚拟滚动——指的是只渲染可视区域的列表项,非可见区域的」不渲染,在滚动时动态更新可视区域,该方案在优化大量数据渲染时效果是很明显的
虚拟滚动图例:
虚拟滚动基本原理:
计算出 totalHeight 列表总高度,并在触发时滚动事件时根据 scrollTop 值不断更新 startIndex 以及 endIndex ,以此从列表数据 listData 中截取对应元素
虚拟滚动性能对比:
-
在不使用虚拟滚动的情况下,渲染 10 万个文本节点:
使用虚拟滚动的情况后:
使用虚拟滚动使性能提升了 78%
虚拟滚动插件
虚拟滚动的插件有很多,比如 vue-virtual-scroller、vue-virtual-scroll-list、react-tiny-virtual-list、react-virtualized 等
这里简单介绍 vue-virtual-scroller 的使用
// 安装插件
npm install vue-virtual-scroller// main.js
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'Vue.use(VueVirtualScroller)// 使用
<template><RecycleScrollerclass="scroller":items="list":item-size="32"key-field="id"v-slot="{ item }"><div class="user"> {{ item.name }} </div></RecycleScroller>
</template>
该插件主要有 RecycleScroller.vue、DynamicScroller.vue 这两个组件,其中 RecycleScroller 需要 item 的高度为静态的,也就是列表每个 item 的高度都是一致的,而 DynamicScroller 可以兼容 item 的高度为动态的情况
6、Web Worker 优化长任务
由于浏览器 GUI 渲染线程与 JS 引擎线程是互斥的关系,当页面中有很多长任务时,会造成页面 UI 阻塞,出现界面卡顿、掉帧等情况
查看页面的长任务:
打开控制台,选择 Performance 工具,点击 Start 按钮,展开 Main 选项,会发现有很多红色的三角,这些就属于长任务(长任务:执行时间超过 50ms 的任务)
测试实验:
如果直接把下面这段代码直接丢到主线程中,计算过程中页面一直处于卡死状态,无法操作
let sum = 0;
for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}
使用 Web Worker 执行上述代码时,计算过程中页面正常可操作、无卡顿
// worker.js
onmessage = function (e) {// onmessage获取传入的初始值let sum = e.data;for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}// 将计算的结果传递出去postMessage(sum);
}
Web Worker 具体的使用与案例,详情见 一文彻底了解 Web Worker,十万、百万条数据都是弟弟 🔥
Web Worker 的通信时长
并不是执行时间超过 50ms 的任务,就可以使用 Web Worker,还要先考虑通信时长
的问题
假如一个运算执行时长为 100ms,但是通信时长为 300ms, 用了 Web Worker 可能会更慢
比如新建一个 web worker, 浏览器会加载对应的 worker.js 资源,下图中的 Time 是这个资源的通信时长(也叫加载时长)
「当任务的运算时长 - 通信时长 > 50ms,推荐使用 Web Worker」
7、requestAnimationFrame 制作动画
requestAnimationFrame
是浏览器专门为动画提供的 API,它的刷新频率与显示器的频率保持一致,使用该 api 可以解决用 setTimeout/setInterval 制作动画卡顿的情况
1)引擎层面
setTimeout/setInterval 属于 JS引擎
,requestAnimationFrame 属于 GUI引擎
JS引擎与GUI引擎
是互斥的,也就是说 GUI 引擎在渲染时会阻塞 JS 引擎的计算
2)时间是否准确
requestAnimationFrame 刷新频率是固定且准确的,但 setTimeout/setInterval 是宏任务,根据事件轮询机制,其他任务会阻塞或延迟 js 任务的执行,会出现定时器不准的情况
3)性能层面
当页面被隐藏或最小化时,setTimeout/setInterval 定时器仍会在后台执行动画任务,而使用 requestAnimationFrame 当页面处于未激活的状态下,屏幕刷新任务会被系统暂停
8、JS 的 6 种加载方式
1)正常模式
<script src="index.js"></script>
这种情况下 JS 会阻塞 dom 渲染,浏览器必须等待 index.js 加载和执行完成后才能去做其它事情
2)async 模式
<script async src="index.js"></script>
async 模式下,它的加载是异步的,JS 不会阻塞 DOM 的渲染,async 加载是无顺序的,当它加载结束,JS 会立即执行
使用场景:若该 JS 资源与 DOM 元素没有依赖关系,也不会产生其他资源所需要的数据时,可以使用 async 模式,比如埋点统计
3)defer 模式
<script defer src="index.js"></script>
defer 模式下,JS 的加载也是异步的,defer 资源会在 DOMContentLoaded
执行之前,并且 defer 是有顺序的加载
如果有多个设置了 defer 的 script 标签存在,则会按照引入的前后顺序执行,即便是后面的 script 资源先返回
所以 defer 可以用来控制 JS 文件的执行顺序,比如 element-ui.js 和 vue.js,因为 element-ui.js 依赖于 vue,所以必须先引入 vue.js,再引入 element-ui.js
<script defer src="vue.js"></script>
<script defer src="element-ui.js"></script>
defer 使用场景:一般情况下都可以使用 defer,特别是需要控制资源加载顺序时
4)module 模式
<script type="module">import { a } from './a.js'</script>
在主流的现代浏览器中,script 标签的属性可以加上 type="module"
,浏览器会对其内部的 import 引用发起 HTTP 请求,获取模块内容。这时 script 的行为会像是 defer 一样,在后台下载,并且等待 DOM 解析
Vite 就是利用浏览器支持原生的 es module
模块,开发时跳过打包的过程,提升编译效率
5) preload
<link rel="preload" as="script" href="index.js">
link 标签的 preload 属性:用于提前加载一些需要的依赖,这些资源会优先加载(如下图红框)
vue2 项目打包生成的 index.html 文件,会自动给首页所需要的资源,全部添加 preload,实现关键资源的提前加载
preload 特点:
1)preload 加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞 onload 事件;
2)preload 加载的 JS 脚本其加载和执行的过程是分离的,即 preload 会预加载相应的脚本代码,待到需要时自行调用;
6)prefetch
<link rel="prefetch" as="script" href="index.js">
prefetch 是利用浏览器的空闲时间,加载页面将来可能用到的资源的一种机制;通常可以用于加载其他页面(非首页)所需要的资源,以便加快后续页面的打开速度
prefetch.png
prefetch 特点:
1)pretch 加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少 5 分钟(无论资源是否可以缓存)
2)当页面跳转时,未完成的 prefetch 请求不会被中断
加载方式总结
async、defer 是 script 标签的专属属性,对于网页中的其他资源,可以通过 link 的 preload、prefetch 属性来预加载
如今现代框架已经将 preload、prefetch 添加到打包流程中了,通过灵活的配置,去使用这些预加载功能,同时我们也可以审时度势地向 script 标签添加 async、defer 属性去处理资源,这样可以显著提升性能
9、图片的优化
平常大部分性能优化工作都集中在 JS 方面,但图片也是页面上非常重要的部分
特别是对于移动端来说,完全没有必要去加载原图,浪费带宽。如何去压缩图片,让图片更快的展示出来,有很多优化工作可以做
淘宝首页的图片资源都很小:
图片的动态裁剪
很多云服务,比如阿里云或七牛云,都提供了图片的动态裁剪功能,效果很棒,确实是钱没有白花
只需在图片的 url 地址上动态添加参数,就可以得到你所需要的尺寸大小,比如:http://7xkv1q.com1.z0.glb.clouddn.com/grape.jpg?imageView2/1/w/200/h/200
图片瘦身前后对比:
-
原图:
1.8M
-
裁剪后:
12.8KB
经过动态裁剪后的图片,加载速度会有非常明显的提升
图片的懒加载
对于一些图片量比较大的首页,用户打开页面后,只需要呈现出在屏幕可视区域内的图片,当用户滑动页面时,再去加载出现在屏幕内的图片,以优化图片的加载效果
图片懒加载实现原理:
由于浏览器会自动对页面中的 img 标签的 src 属性发送请求并下载图片,可以通过 html5 自定义属性 data-xxx 先暂存 src 的值,然后在图片出现在屏幕可视区域的时候,再将 data-xxx 的值重新赋值到 img 的 src 属性即可
<img src="" alt="" src="./images/1.jpg">
<img src="" alt="" src="./images/2.jpg">
这里以 vue-lazyload
插件为例
// 安装
npm install vue-lazyload// main.js 注册
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
// 配置项
Vue.use(VueLazyload, {preLoad: 1.3,error: 'dist/error.png', // 图片加载失败时的占位图loading: 'dist/loading.gif', // 图片加载中时的占位图attempt: 1
})// 通过 v-lazy 指令使用
<ul><li v-for="img in list"><img v-lazy="img.src" :key="img.src" ></li>
</ul>
使用字体图标
字体图标是页面使用小图标的不二选择,最常用的就是 iconfont
字体图标的优点:
1)轻量级:一个图标字体要比一系列的图像要小。一旦字体加载了,图标就会马上渲染出来,减少了 http 请求
2)灵活性:可以随意的改变颜色、产生阴影、透明效果、旋转等
3)兼容性:几乎支持所有的浏览器,请放心使用
图片转 base64 格式
将小图片转换为 base64 编码字符串,并写入 HTML 或者 CSS 中,减少 http 请求
转 base64 格式的优缺点:
1)它处理的往往是非常小的图片,因为 Base64 编码后,图片大小会膨胀为原文件的 4/3,如果对大图也使用 Base64 编码,后者的体积会明显增加,即便减少了 http 请求,也无法弥补这庞大的体积带来的性能开销,得不偿失
2)在传输非常小的图片的时候,Base64 带来的文件体积膨胀、以及浏览器解析 Base64 的时间开销,与它节省掉的 http 请求开销相比,可以忽略不计,这时候才能真正体现出它在性能方面的优势
项目可以使用 url-loader
将图片转 base64:
// 安装
npm install url-loader --save-dev// 配置
module.exports = {module: {rules: [{test: /.(png|jpg|gif)$/i,use: [{loader: 'url-loader',options: {// 小于 10kb 的图片转化为 base64limit: 1024 * 10}}]}]}
};
优化总结
本文主要介绍的是 「代码层面」 的性能优化,经过上面的一系列优化,首页打开速度有了明显的提升,虽然都是一些常规方案,但其中可以深挖的知识点并不少
相关文章:

性能优化问题
提升首屏的加载速度,是前端性能优化中「最重要」的环节,这里笔者梳理出一些 常规且有效 的首屏优化建议 1、路由懒加载 SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文…...

【云原生系列】云计算概念与架构设计介绍
1 什么是云计算 云计算是一种基于互联网的计算模式,在这个模式下,各种计算资源(例如计算机、存储设备、网络设备、应用程序等)可以通过互联网实现共享和交付。云计算架构设计的主要目标是实现高效、可扩展、可靠、安全和经济的计算…...
Swoole协程系统HTTP服务
先启动宝塔 /etc/init.d/bt start 源码参考 https://github.com/zhangyue0503/swoole/tree/main/4.Swoole%E5%8D%8F%E7%A8%8B 对于异步来说,我们需要监听事件,并且监听的进程是并发的,所以会有一个问题,那就是无法保证前后顺…...

SpringCloud学习路线(13)——分布式搜索ElasticSeach集群
前言 单机ES做数据存储,必然面临两个问题:海量数据的存储,单点故障。 如何解决这两个问题? 海量数据的存储问题: 将索引库从逻辑上拆分为N个分片(shard),存储到多个节点。单点故障…...
CMIP6数据处理及在气候变化、水文、生态等领域中的应用
目录 专题一 CMIP6中的模式比较计划 专题二 数据下载 专题三 基础知识 专题四 单点降尺度 专题五 统计方法的区域降尺度 专题六 基于WRF模式的动力降尺度动态降尺度 专题七 典型应用案例-气候变化1 专题八 典型应用案例-气候变化2 专题九 典型应用案例-生态领域 专题…...
hadoop之mapreduce详解
一、概述 优化前我们需要知道hadoop适合干什么活,适合什么场景,在工作中,我们要知道业务是怎样的,能才结合平台资源达到最有优化。除了这些我们当然还要知道mapreduce的执行过程,比如从文件的读取,map处理&…...
leetcode做题笔记44
给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 ? 和 * 匹配规则的通配符匹配: ? 可以匹配任何单个字符。 * 可以匹配任意字符序列(包括空字符序列)。 判定匹配成功的充要条件是:字符模式必须能够 完…...

mac brew安装 node 踩坑日记- n切换node不生效
最近用了一个旧电脑开发,发现里面node管理混乱,有nvm、n和homebrew,导致切换node 切换不了,开发也有莫名其妙的错误。所以我打算重新装一下node,使用n做为管理工具。 1. 删除nvm cd ~ rm -rf .nvm2. 删除n sudo rm -…...

数据预处理matlab
matlab数据的获取、预处理、统计、可视化、降维 数据的预处理 - MATLAB & Simulink - MathWorks 中国https://ww2.mathworks.cn/help/matlab/preprocessing-data.html 一、数据的获取 1.1 从Excel中获取 使用readtable() 例1: 使用spreadsheetImportOption…...

ubuntu18.04安装autoware1.15
目录 前言一、准备工作1.安装autoware1.152.安装依赖3.把src/autoware/common/autoware_build_flags/cmake文件夹下的CUDA版本改为11.4(或者你电脑上的版本) 二、解决报错错误类型1错误类型2错误类型3错误类型4错误类型5错误类型6 前言 本文参考链接&am…...
在CSDN学Golang云原生(Docker基础)
一,docker安装配置 要在golang中使用Docker,需要先安装并配置好Docker。下面是基本的Docker安装和配置步骤: 下载并安装Docker 官方下载地址:https://docs.docker.com/get-docker/ 根据你的操作系统选择对应版本的Docker&…...

Zookeeper命令总结
目录 1、常用命令2、ls path3、create xxx创建持久化节点创建临时节点创建持久化序列节点 4、get path5、set path6、delete path7、监听器总结1)节点的值变化监听2)节点的子节点变化监听(路径变化)3)当某个节点创建或…...

C语言中的函数(超详细)
C语言中的函数(超详细) 一、函数概述二、C语言中函数的分类1.库函数2.自定义函数三、函数的参数1.实际参数(实参)2.形式参数(形参)四、函数的调用1.传值调用2.传址调用五、函数的嵌套调用和链式访问1.嵌套调…...
华为H3C思科网络设备命令对照表
类别命令功能华为H3C思科通用取消关闭当前设置undoundono通用显示查看displaydisplayshow通用退回上级quitquitquit通用设置设备名称sysnamesysnamehostname通用到全局模式system-viewsystem-viewenable config terminal通用删除文件deletedeletedelete通用重启设备rebootreboo…...

产品需求、系统架构设计经验篇
需求设计思维导图UML 建模原型规范什么样的需求该忽略1.拍拍脑袋得来的想法,往往是没用的2.用户反馈的信息,不应该直接纳入需求3.扭改用户习惯的需求,一律不考虑 什么样的需求该重视1.从运维系统中根据数据结果分析得出的结论2.重视有洞见者的…...
关于websocket的几点注意事项
第一、普通websocket直接集成即可 <!-- Spring Websocket 相关依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency> 第二、web后端两点,创…...

go学习 4、复合数据类型
4、复合数据类型 数组、slice、map和结构体 如何使用结构体来解码和编码到对应JSON格式的数据,并且通过结合使用模板来生成HTML页面 数组和结构体是聚合类型;它们的值由许多元素或成员字段的值组成。数组是由同构的元素组成(每个数组元素都是完全相同的…...
Rust: Vec类型的into_boxed_slice()方法
比如,我们经常看到Vec类型,但取转其裸指针,经常会看到into_boxed_slice()方法,这是为何? use std::{fmt, slice};#[derive(Clone, Copy)] struct RawBuffer {ptr: *mut u8,len: usize, }impl From<Vec<u8>&g…...

Python - Opencv + pyzbar实时摄像头识别二维码
直接上代码: import cv2 from pyzbar.pyzbar import decodecap cv2.VideoCapture(0) # 打开摄像头while True: # 循环读取摄像头帧ret, frame cap.read()# 在循环中,将每一帧作为图像输入,使用pyzbar的decode()函数识别二维码barcodes …...

网络安全(黑客)就业分析指导
一、针对网络安全市场分析 市场需求量高;则是发展相对成熟入门比较容易。所需要的技术水平国家政策环境 对于国家与企业的地位愈发重要,没有网络安全就没有国家安全 更有为国效力的正义黑客—红客联盟 可见其重视程度。 需要掌握的知识点偏多 外围打点…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...