0%

一、Linux 是什么

Linux 是一个开源的类 Unix 操作系统内核,由 Linus Torvalds 于 1991 年创建。它广泛应用于服务器、嵌入式设备、超级计算机和移动端(Android),是后端开发和 DevOps 的核心环境。

阅读全文 »

第一章 概述

一、判断题
1、Linux 内核是单内核结构,执行效率高,可维护性好。( × )

1
2
为什么要使用模块?
linux内核之所以提供模块机制,是因为它本身是一个单内核。而单内核的最大优点就是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。
阅读全文 »

动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。它的核心思想是利用历史记录避免重复计算。本文将从基础到进阶,全面讲解动态规划。

阅读全文 »

分治算法(Divide and Conquer)是一种重要的算法设计思想,它将一个复杂的问题分解成若干个相同或相似的子问题,递归地解决这些子问题,然后将子问题的解合并成原问题的解。本文将从概念到实践,全面讲解分治算法的思想、适用场景及常见题型。

阅读全文 »

一、content-visibility——跳过屏幕外内容渲染

对于大量离屏内容,使用 content-visibility: auto 可大幅减少渲染时间。

阅读全文 »

一、避免频繁读写 DOM

缓存 DOM 引用

1
2
var dom = document.querySelector('element');
// 后续操作使用缓存的 dom 变量,不要重复查询

缓存读取的属性

1
2
3
4
5
6
7
8
9
10
11
// ❌ 每次循环都读取 dom.style.left(触发回流)
setInterval(() => {
dom.style.left = parseInt(dom.style.left) + 1 + 'px';
}, 16);

// ✅ 缓存变量,避免反复读取 DOM
let left = parseInt(dom.style.left);
setInterval(() => {
left++;
dom.style.left = left + 'px';
}, 16);

合并多次写操作

1
2
3
4
5
6
7
8
9
10
11
// ❌ 每次循环都修改 innerHTML
for (let i = 0; i < 100; i++) {
document.getElementById('text').innerHTML += 'text' + i;
}

// ✅ 合并为一次写操作
let html = '';
for (let i = 0; i < 100; i++) {
html += 'text' + i;
}
document.getElementById('text').innerHTML = html;

使用 DocumentFragment

1
2
3
4
5
6
7
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.innerHTML = i;
fragment.appendChild(div);
}
document.body.appendChild(fragment);

二、CSS 避免重排重绘

基本原则

  • 使用 className 替代多次 style 操作
  • 使用 visibility:hidden 替代 display:none(前者只触发重绘,后者触发重排)
  • 避免使用 table 布局
  • 对动画元素使用 absolute / fixed
  • 对 resize 事件做防抖节流处理

开启 GPU 渲染动画

以下属性可以避免主线程频繁操作:

  • transform:不触发 Layout,只触发 Composite
  • opacity:不触发 Layout,只触发 Composite
  • will-change:提前告知浏览器优化

transform

1
2
3
4
5
/* ❌ 触发 Layout */
div { margin-left: 20px; transition: margin-left 1s; }

/* ✅ 仅触发 Composite */
div { transform: translateX(20px); transition: transform 1s; }

opacity 优化阴影动画

通过伪元素配合 opacity 过渡替代 box-shadow 过渡:

1
2
3
4
5
6
7
8
div::before {
content: '';
position: absolute;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
opacity: 0;
transition: opacity 1s;
}
div:hover::before { opacity: 1; }

will-change

1
2
3
.animate {
will-change: transform, opacity;
}

使用原则:

  • 不要应用到太多元素上
  • 在变化前通过 JS 添加,变化完成后移除
  • 给浏览器足够的时间做优化准备

三、JS 避免重排重绘

引起回流的属性

读取以下属性会强制触发回流:

1
2
3
4
5
offsetTop / offsetLeft / offsetWidth / offsetHeight
scrollTop / scrollLeft / scrollWidth / scrollHeight
clientTop / clientLeft / clientWidth / clientHeight
getBoundingClientRect() / getClientRects()
getComputedStyle()

读写分离

1
2
3
4
5
6
7
8
9
10
11
// ❌ 每次修改都触发强制回流
dom.style.width = '100px';
console.log(dom.offsetWidth);
dom.style.height = '200px';
console.log(dom.offsetHeight);

// ✅ 集中读取,集中写入
const width = el.offsetWidth + 10;
const height = el.offsetHeight + 10;
el.style.width = width + 'px';
el.style.height = height + 'px';

使用 display:none 离线操作

对于需要多次操作的 DOM 元素,先设置为 display:none,操作完毕再显示:

1
2
3
el.style.display = 'none';
// 进行大量 DOM 操作...
el.style.display = 'block';

使用 cloneNode

1
2
3
const clone = el.cloneNode(true);
// 操作 clone...
el.parentNode.replaceChild(clone, el);

四、简化 DOM 结构

DOM 结构越深,内部元素变化引发的祖先重排越多。对于大量数据表格的展示,使用分页而非一次性渲染数万个 DOM。

五、DOM 事件优化

事件委托

1
2
3
4
5
// 在父容器绑定一个事件,通过 target 分发
container.addEventListener('click', (e) => {
const item = e.target.closest('.item');
if (item) handleClick(item.dataset.id);
});

节流

1
2
3
4
5
6
7
8
9
10
11
function throttle(func, wait) {
let previous = 0;
return function () {
const now = +new Date();
if (now - previous > wait) {
func.apply(this, arguments);
previous = now;
}
};
}
// 适用场景:scroll、resize

防抖

1
2
3
4
5
6
7
8
function debounce(func, wait) {
let timeout;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, arguments), wait);
};
}
// 适用场景:输入搜索、窗口 resize 结束

一、React 性能问题的本质

React 的性能问题几乎都指向同一个根源:不必要的重新渲染。当组件的 state、props 或 context 变化时,React 会重新调用该组件及其所有子组件的 render 函数(或函数体),即使子组件的 props 没有变化。

阅读全文 »