前端疑难纪要
webweb worker前端前端工程化

前端疑难纪要

前端开发中遇到的难题或者容易忽略的知识点

更新于 2025-03-08
6968

图像处理

缩略图生成

  1. 解析DataURL,获取图片的原始数据和MIME类型。
  2. 读取图片: 使用Node.js的fs模块或Buffer来读取图片数据。
  3. 调整图片大小: 使用图像处理库,如sharpJimp,来调整图片的大小。
  4. 降低图片质量: 在调整大小的同时,可以降低图片的质量,以生成更低分辨率的缩略图。
  5. 输出图片: 将处理后的图片输出为新的文件或返回给客户端。

一个使用sharp库的示例代码:将DataURL转换为Buffer,然后使用sharp库来调整图片大小并降低JPEG图片的质量以生成缩略图。

typescript
import sharp from 'sharp';
// 假设dataURL是传入的图片的DataURL
const dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAU...';
// 获取图片数据和MIME类型
const data = dataURL.split(',')[1]; // 去除前缀,获取base64编码的数据
const mimeType = dataURL.split(',')[0].split(':')[1].split(';')[0]; // 获取MIME类型
// 将base64编码的数据转换为Buffer
const imageBuffer = Buffer.from(data, 'base64');
// 使用sharp库处理图片
sharp(imageBuffer)
.toFormat(mimeType === 'image/jpeg' ? 'jpeg' : 'png') // 根据MIME类型设置输出格式
.resize(100, 100) // 设置缩略图的尺寸,例如100x100像素
.jpeg({ quality: 70 }) // 设置JPEG图片的质量,数值越低,图片质量越低
.toBuffer()
.then((buffer: Buffer) => {
// 处理后的图片数据存储在buffer中
// 这里可以进一步操作,比如写入文件系统或发送给客户端
console.log('Thumbnail generated:', buffer);
})
.catch((err: Error) => {
console.error('Error generating thumbnail:', err);
});

表单

迭代器

js
const formData = new FormData();
// 添加表单数据到 formData 对象
// ...
// 使用 formData.entries() 迭代键值对
for (const [key, value] of formData.entries()) {
console.log(key, value);
}

文件

获取 file input 文件名称

fileInput.files[0].name

input[type="datetime-local"]

jsx
<input
type="datetime-local"
defaultValue={new Date().toISOString().slice(0, 16)}
/>

formData 获取多选的 select 选中值

使用 getAll

checkbox

<input type="checkbox">元素, 如果复选框被选中,value属性的值将默认为"on"value属性并不是必需的,如果未提供value属性,那么在表单提交时,只会传递复选框的选中状态,而不会传递具体的值。例如表单数据中将会包含myCheckbox=on的键值对。默认的value值是"on"

实现未修改过的字段不提交

  1. 在 HTML 表单中为每个需要验证的字段添加一个 data-original-value 属性,用于存储原始的字段值。
  2. 在表单提交之前,使用 JavaScript 遍历所有需要验证的字段。对于每个字段,比较其当前值与 data-original-value 属性中存储的原始值是否相等。如果当前值与原始值相等,将其禁用或从表单数据中移除。

示例的 JavaScript 代码:

javascript
document.getElementById('myForm').addEventListener('submit', function(event) {
var form = event.target;
var inputs = form.querySelectorAll('[data-original-value]');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var originalValue = input.getAttribute('data-original-value');
var currentValue = input.value;
if (currentValue === originalValue) {
// 未修改过的字段,可以禁用或从表单数据中移除
input.disabled = true;
// 如果要移除字段,可以使用以下代码
// input.parentNode.removeChild(input);
}
}
});

禁用的表单项不会被提交。

禁用的表单项被视为不可编辑状态,用户无法对其进行更改,并且在提交表单时,这些禁用的表单项的值不会包含在提交的数据中。

手动触发 input 事件

DOM允许手动触发input事件。你可以使用JavaScript来模拟用户输入并触发input事件。下面是一个示例代码:

javascript
// 获取input元素
const inputElement = document.getElementById('myInput');
// 创建一个新的Event对象
const event = new Event('input', {
bubbles: true,
cancelable: true,
});
// 模拟用户输入
inputElement.value = 'Hello World';
// 触发input事件
inputElement.dispatchEvent(event);

使用dispatchEvent方法将创建的实践其分派给input元素。最后,我们将input元素的值设置为"Hello World",这将触发input事件。

请注意,触发input事件并不会自动触发与该事件关联的其他行为或响应。事件处理程序监听input事件并执行某些操作,那么手动触发input事件不会自动调用该事件处理程序。可能需要手动调用其他相关的函数或方法来模拟完整的用户交互行为。

手动触发input事件可以在以下情况下具有意义:

  1. 表单验证:通过手动触发input事件,可以立即触发表单验证逻辑,以便及时检测并显示验证错误或提供实时反馈。
  2. 实时搜索:在搜索框中输入关键字时,实时更新搜索结果,而无需等待用户手动按下回车键或点击搜索按钮。
  3. 动态更新UI:当用户输入内容时,可以使用input事件来实时更新UI元素,例如显示字符计数、实时预览或自动完成。
  4. 自定义交互。模拟用户输入,从而实现自定义的交互效果。例如,你可以在特定条件下自动填充输入框,或者在特定输入时触发其他操作。

显式调用展示校验消息

可以使用 reportValidity() 方法来显式调用展示校验消息。这个方法会触发浏览器的校验过程,并显示相应的错误消息:

html
<form id="myForm">
<input type="text" id="myInput" required>
<button type="button" onclick="showValidationMessage()">校验</button>
</form>
<script>
const input = document.getElementById('myInput');
function showValidationMessage() {
if (input.checkValidity()) {
// 输入有效,不显示校验消息
console.log('输入有效');
} else {
// 输入无效,显示校验消息
input.reportValidity();
}
}
</script>

showValidationMessage() 函数。这个函数首先使用 checkValidity() 方法检查输入的有效性,如果输入有效,则在控制台输出 "输入有效";如果输入无效,则使用 reportValidity() 方法显示校验消息。

通过显式调用 reportValidity() 方法,你可以在需要的时候手动触发校验消息的展示,而不依赖于表单的提交行为。

标记

https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting

样式

textarea

定位

图片宽高

highlight

换行问题

\n 后换行

html 默认会将 \n 表现为空格,需要调整 white-space 属性

css
white-space: pre-line;

不换行

在 Tailwind CSS 中,用于控制文本不换行的工具类名是 whitespace-nowrap

html
<div class="whitespace-nowrap">
这是一段很长的文本,将不会换行显示。
</div>

瀑布流布局

简单 css 实现

类库

focus

伪类选择器:focus:focus-within
描述选择当前获取焦点的元素选择包含有获取焦点元素的父元素
用法element:focus { /* 样式规则 */ }parent-element:focus-within { /* 样式规则 */ }

示例:

css
/* 当前获取焦点的元素 */
input:focus {
outline: 2px solid blue;
}
/* 包含有获取焦点元素的父元素 */
.container:focus-within {
background-color: yellow;
}

在上面的示例中,当用户点击一个输入框时,该输入框会显示一个蓝色的边框,表示它处于 :focus 状态。同时,它的父元素 .container 也会变成黄色背景,表示它处于 :focus-within 状态。

工程化

静态资源引入

import.meta.url is a native ESM feature that exposes the current module's URL. Combining it with the native URL constructor, we can obtain the full, resolved URL of a static asset using relative path from a JavaScript module:

js
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('hero-img').src = imgUrl
https://vitejs.dev/guide/assets
js
import Worker from 'web-worker';
const url = new URL('./worker.js', import.meta.url);
const worker = new Worker(url);
worker.addEventListener('message', e => {
console.log(e.data) // "hiya!"
});
worker.postMessage('hello');

? Notice how new URL('./worker.js', import.meta.url) is used above to load the worker relative to the current module instead of the application base URL. Without this, Worker URLs are relative to a document's URL

https://www.npmjs.com/package/web-worker

文件系统

OPFS

持久化方案

日期处理

使用 Web 原生 API 将 JavaScript 的 Date 数据转换成特定格式(例如 "2023-06-27")的字符串:

js
const date = new Date(); // 使用当前日期
// const date = new Date(2023, 5, 27); // 使用指定日期
const year = date.getFullYear(); // 获取年份
const month = date.getMonth() + 1; // 获取月份(加 1 是因为月份从 0 开始)
const day = date.getDate(); // 获取日期
const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
// padStart() 方法用来确保月份和日期的值始终是两位数(如果不足两位,则在前面补零)。
console.log(formattedDate); // 输出:2023-06-27

复制到剪贴板

js 复制到剪贴板原生实现

❌ 使用 execCommand

javascript
function copyToClipboard(text) {
// 创建一个临时的textarea元素
const textarea = document.createElement('textarea');
textarea.value = text;
// 将textarea元素添加到DOM中
document.body.appendChild(textarea);
// 选择并复制文本
textarea.select();
document.execCommand('copy');
// 删除临时的textarea元素
document.body.removeChild(textarea);
}
// 调用copyToClipboard函数,将文本复制到剪贴板
copyToClipboard('要复制的文本');

创建一个临时的textarea元素,设置使用document.execCommand('copy')命令将文本复制到剪贴板。最后删除临时的textarea元素。由于安全性限制,复制到剪贴板功能可能在某些浏览器中受到限制。在某些情况下,用户可能需要手动授权或触发复制操作。

目前 document.execCommand方法的签名已经被弃用。根据最新的规范,推荐使用更现代的 Clipboard API 来实现复制到剪贴板的功能。

使用 Clipboard API

示例:

javascript
function copyToClipboard(text) {
navigator.clipboard.writeText(text)
.then(() => {
console.log('文本已成功复制到剪贴板');
})
.catch((error) => {
console.error('复制到剪贴板时出错:', error);
});
}
// 调用copyToClipboard函数,将文本复制到剪贴板
copyToClipboard('要复制的文本');

Clipboard API需要在安全的上下文中使用,例如HTTPS网页或本地文件系统。在某些浏览器中,用户可能需要授予权限以访问剪贴板。

获取粘贴的文本

要从paste事件中获取粘贴的字符串,可以使用event.clipboardData.getData('text')方法。注意paste事件是浏览器事件,并且只能在浏览器环境中使用。

javascript
document.addEventListener('paste', function(event) {
var pastedText = event.clipboardData.getData('text');
console.log('粘贴的字符串:', pastedText);
});

  • 分列布局
  • 监听 location 变化