避免同步阻塞API优化指南
问题描述
项目中使用alert、confirm、prompt等同步阻塞API,阻塞用户界面和JavaScript执行,影响用户体验。
优化建议
1. 使用异步模态框替代alert
不推荐的写法
javascript
// 不推荐:使用alert阻塞执行
function showAlert() {
alert('这是一个警告信息');
console.log('这行代码在用户关闭alert后才会执行');
}推荐的异步模态框
javascript
// 推荐:使用自定义异步模态框
function showAsyncAlert(message) {
return new Promise((resolve) => {
const modal = document.createElement('div');
modal.className = 'custom-modal';
modal.innerHTML = `
<div class="modal-content">
<p>${message}</p>
<button id="confirm-btn">确定</button>
</div>
`;
document.body.appendChild(modal);
document.getElementById('confirm-btn').onclick = () => {
document.body.removeChild(modal);
resolve();
};
});
}
// 使用示例
async function handleAction() {
await showAsyncAlert('操作完成!');
console.log('这行代码会立即执行');
}2. 使用异步确认框替代confirm
不推荐的写法
javascript
// 不推荐:使用confirm阻塞执行
function deleteItem() {
const confirmed = confirm('确定要删除这个项目吗?');
if (confirmed) {
performDelete();
}
}推荐的异步确认框
javascript
// 推荐:使用自定义异步确认框
function showAsyncConfirm(message) {
return new Promise((resolve) => {
const modal = document.createElement('div');
modal.className = 'custom-modal';
modal.innerHTML = `
<div class="modal-content">
<p>${message}</p>
<div class="modal-buttons">
<button id="cancel-btn">取消</button>
<button id="confirm-btn">确定</button>
</div>
</div>
`;
document.body.appendChild(modal);
document.getElementById('confirm-btn').onclick = () => {
document.body.removeChild(modal);
resolve(true);
};
document.getElementById('cancel-btn').onclick = () => {
document.body.removeChild(modal);
resolve(false);
};
});
}
// 使用示例
async function deleteItem() {
const confirmed = await showAsyncConfirm('确定要删除这个项目吗?');
if (confirmed) {
performDelete();
}
}3. 使用异步输入框替代prompt
不推荐的写法
javascript
// 不推荐:使用prompt阻塞执行
function renameItem() {
const newName = prompt('请输入新名称:');
if (newName) {
performRename(newName);
}
}推荐的异步输入框
javascript
// 推荐:使用自定义异步输入框
function showAsyncPrompt(message, defaultValue = '') {
return new Promise((resolve) => {
const modal = document.createElement('div');
modal.className = 'custom-modal';
modal.innerHTML = `
<div class="modal-content">
<p>${message}</p>
<input type="text" id="prompt-input" value="${defaultValue}">
<div class="modal-buttons">
<button id="cancel-btn">取消</button>
<button id="confirm-btn">确定</button>
</div>
</div>
`;
document.body.appendChild(modal);
const input = document.getElementById('prompt-input');
input.focus();
document.getElementById('confirm-btn').onclick = () => {
const value = input.value;
document.body.removeChild(modal);
resolve(value || null);
};
document.getElementById('cancel-btn').onclick = () => {
document.body.removeChild(modal);
resolve(null);
};
// 支持回车确认
input.onkeypress = (e) => {
if (e.key === 'Enter') {
document.getElementById('confirm-btn').click();
}
};
});
}
// 使用示例
async function renameItem() {
const newName = await showAsyncPrompt('请输入新名称:');
if (newName) {
performRename(newName);
}
}4. 使用现代UI库
使用Element Plus
javascript
// 使用Element Plus的MessageBox
import { ElMessageBox } from 'element-plus';
async function handleAction() {
try {
await ElMessageBox.alert('这是一条消息', '提示', {
confirmButtonText: '确定'
});
console.log('用户点击了确定');
} catch (action) {
console.log('用户关闭了对话框');
}
}
async function deleteItem() {
try {
await ElMessageBox.confirm('确定要删除这个项目吗?', '确认删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
performDelete();
} catch (action) {
console.log('用户取消了删除');
}
}5. 实施步骤
- 识别项目中使用的同步阻塞API
- 设计异步替代方案
- 实现自定义模态框或集成UI库
- 替换原有同步调用
- 验证优化效果
6. 注意事项
- 确保异步模态框的样式和体验
- 处理键盘导航和无障碍访问
- 考虑移动端适配
- 测试不同浏览器兼容性
7. 验证方法
- 使用Chrome开发者工具Performance面板
- 检查页面阻塞情况
- 对比优化前后的用户交互体验
- 验证功能完整性
通过避免同步阻塞API,可以有效提升用户交互体验,避免页面阻塞。