您好!我作为一名资深的前端架构师和代码精益求精的专家,将为您精心整理和展示前端开发中那些不可或缺、高频使用且极具实用价值的代码片段。 这些片段涵盖了从基础操作到高级技巧,旨在帮助您提升开发效率和代码质量。
HTML 是网页内容的骨架,语义化的 HTML 有助于提高可访问性、SEO 和代码可维护性。
一个标准的 HTML5 页面模板,包含必要的元信息和结构。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的前端页面</title>
<link rel="stylesheet" href="styles.css"> <!-- 引入外部 CSS 文件 -->
</head>
<body>
<header>
<h1>页面标题</h1>
<nav>
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">关于我们</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</nav>
</header>
<main>
<section>
<h2>主要内容区域</h2>
<p>这里是页面的核心内容。</p>
</section>
<aside>
<h3>侧边栏</h3>
<p>一些补充信息或广告。</p>
</aside>
</main>
<footer>
<p>© 2023 我的公司. 版权所有.</p>
</footer>
<script src="main.js"></script> <!-- 引入外部 JavaScript 文件 -->
</body>
</html>
构建用户交互的核心。
<form action="/submit" method="post">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" required><br><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" minlength="6"><br><br>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email"><br><br>
<label for="gender">性别:</label>
<input type="radio" id="male" name="gender" value="male">
<label for="male">男</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">女</label><br><br>
<label for="interests">兴趣:</label>
<input type="checkbox" id="reading" name="interests" value="reading">
<label for="reading">阅读</label>
<input type="checkbox" id="sports" name="interests" value="sports">
<label for="sports">运动</label><br><br>
<label for="country">国家:</label>
<select id="country" name="country">
<option value="" disabled selected>请选择国家</option>
<option value="china">中国</option>
<option value="usa">美国</option>
<option value="japan">日本</option>
</select><br><br>
<label for="message">留言:</label>
<textarea id="message" name="message" rows="5" cols="30"></textarea><br><br>
<input type="submit" value="提交">
<button type="reset">重置</button>
</form>
CSS 负责页面的美化和布局,掌握常用的 CSS 技巧能让您的页面更具表现力。
弹性盒模型是现代前端布局的利器,非常适合构建响应式和动态排列的元素。
/* 父容器 */
.flex-container {
display: flex; /* 启用 Flexbox */
justify-content: space-between; /* 子元素在主轴上均匀分布,两端对齐 */
align-items: center; /* 子元素在交叉轴上居中对齐 */
flex-wrap: wrap; /* 子元素如果空间不足,允许换行 */
gap: 10px; /* 子元素之间的间距 (CSS Gap 属性) */
height: 200px;
border: 1px solid #ccc;
padding: 10px;
}
/* 子元素 */
.flex-item {
width: 80px;
height: 80px;
background-color: #3498db;
color: white;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
}
CSS Grid 提供了强大的二维网格布局能力,适合复杂的页面结构。
/* 父容器 */
.grid-container {
display: grid; /* 启用 Grid 布局 */
grid-template-columns: 1fr 2fr 1fr; /* 定义三列,比例为 1:2:1 */
grid-template-rows: auto 100px; /* 定义两行,第一行高度自适应,第二行固定 100px */
gap: 15px; /* 行和列之间的间距 */
width: 100%;
height: 300px;
border: 1px solid #ccc;
padding: 10px;
}
/* 子元素可以放置在特定网格区域 */
.grid-item-1 {
grid-column: 1 / 3; /* 占据第 1 列到第 3 列 (跨越两列) */
grid-row: 1; /* 占据第 1 行 */
background-color: #27ae60;
color: white;
padding: 10px;
}
.grid-item-2 {
grid-column: 3;
grid-row: 1 / 3; /* 占据第 1 行到第 3 行 (跨越两行) */
background-color: #e67e22;
color: white;
padding: 10px;
}
.grid-item-3 {
grid-column: 1;
grid-row: 2;
background-color: #8e44ad;
color: white;
padding: 10px;
}
.grid-item-4 {
grid-column: 2;
grid-row: 2;
background-color: #c0392b;
color: white;
padding: 10px;
}
让您的网页在不同设备上都能良好显示。
/* 默认样式 (适用于大屏幕) */
.my-element {
width: 800px;
font-size: 18px;
padding: 20px;
background-color: lightblue;
}
/* 当屏幕宽度小于等于 768px 时应用 */
@media (max-width: 768px) {
.my-element {
width: 100%; /* 全宽 */
font-size: 16px;
padding: 15px;
background-color: lightcoral;
}
}
/* 当屏幕宽度小于等于 480px 时应用 */
@media (max-width: 480px) {
.my-element {
font-size: 14px;
padding: 10px;
background-color: lightgreen;
}
}
经典的 CSS 挑战之一,这里提供两种常用方法:Flexbox 和绝对定位+transform。
/* 方法一:使用 Flexbox (推荐) */
.parent-flex {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 300px; /* 父元素需有固定高度 */
border: 1px dashed #999;
}
.child-flex {
width: 100px;
height: 100px;
background-color: #f39c12;
color: white;
text-align: center;
line-height: 100px; /* 单行文本垂直居中 */
}
/* 方法二:使用绝对定位 + transform */
.parent-absolute {
position: relative; /* 父元素需要定位 */
height: 300px;
border: 1px dashed #999;
}
.child-absolute {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 自身宽高的一半进行偏移 */
width: 100px;
height: 100px;
background-color: #1abc9c;
color: white;
text-align: center;
line-height: 100px;
}
JavaScript 是前端的灵魂,它赋予页面交互能力。以下是一些高频使用的 JS 片段。
获取元素、修改内容、添加/删除类名、事件监听等。
// 1. 获取元素
const myButton = document.getElementById('myButton'); // 按 ID 获取
const paragraphs = document.getElementsByClassName('my-paragraph'); // 按类名获取 (HTMLCollection)
const firstParagraph = document.querySelector('.my-paragraph'); // 获取第一个匹配的元素
const allLinks = document.querySelectorAll('a'); // 获取所有匹配的元素 (NodeList)
// 2. 修改元素内容和属性
if (firstParagraph) {
firstParagraph.textContent = '新的段落内容。'; // 修改文本内容
firstParagraph.innerHTML = '<strong>更强的</strong>内容。'; // 修改 HTML 内容
firstParagraph.setAttribute('data-info', 'important'); // 设置自定义属性
firstParagraph.style.color = 'blue'; // 修改内联样式
}
// 3. 添加/删除/切换类名
const myDiv = document.getElementById('myDiv');
if (myDiv) {
myDiv.classList.add('active'); // 添加类
myDiv.classList.remove('inactive'); // 移除类
myDiv.classList.toggle('highlight'); // 切换类 (存在则移除,不存在则添加)
console.log(myDiv.classList.contains('active')); // 检查是否包含类
}
// 4. 事件监听
if (myButton) {
myButton.addEventListener('click', function() {
alert('按钮被点击了!');
console.log('按钮点击事件触发');
});
// 移除事件监听 (如果需要)
// function handleClick() { alert('点击'); }
// myButton.addEventListener('click', handleClick);
// myButton.removeEventListener('click', handleClick);
}
// 5. 创建和插入元素
const newDiv = document.createElement('div');
newDiv.textContent = '这是一个新创建的 div。';
newDiv.classList.add('new-element');
document.body.appendChild(newDiv); // 添加到 body 的末尾
const container = document.getElementById('container');
if (container) {
const existingElement = document.getElementById('existing');
container.insertBefore(newDiv, existingElement); // 在 existingElement 之前插入
}
// 6. 删除元素
const elementToRemove = document.getElementById('toRemove');
if (elementToRemove && elementToRemove.parentNode) {
elementToRemove.parentNode.removeChild(elementToRemove);
}
前端经常需要处理数据,数组是其中最常见的数据结构。
// 1. 遍历数组
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(num, index) {
console.log(`索引 ${index} 的值是: ${num}`);
});
// 2. 映射 (map): 创建一个新数组,其每个元素是原数组对应元素执行回调函数后的结果
const doubledNumbers = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]
console.log('翻倍后的数字:', doubledNumbers);
// 3. 过滤 (filter): 创建一个新数组,包含通过测试的元素
const evenNumbers = numbers.filter(num => num % 2 === 0); // [2, 4]
console.log('偶数:', evenNumbers);
// 4. 查找 (find/findIndex): 查找第一个符合条件的元素或其索引
const found = numbers.find(num => num > 3); // 4
const foundIndex = numbers.findIndex(num => num === 3); // 2
console.log('找到大于3的第一个数:', found, ';3的索引:', foundIndex);
// 5. 归约 (reduce): 对数组中的所有元素执行一个归约函数,将其归约成一个单一的值
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 15
console.log('总和:', sum);
// 6. 展开运算符 (...) 和数组合并
const arr1 = [1, 2];
const arr2 = [3, 4];
const combinedArr = [...arr1, ...arr2]; // [1, 2, 3, 4]
const newArrWithAdditions = [...numbers, 6, 7]; // [1, 2, 3, 4, 5, 6, 7]
console.log('合并数组:', combinedArr);
// 7. 对象属性的遍历 (ES6)
const user = { name: 'Alice', age: 30, city: 'New York' };
for (const key in user) {
if (Object.hasOwnProperty.call(user, key)) {
console.log(`${key}: ${user[key]}`);
}
}
Object.keys(user).forEach(key => {
console.log(`Key: ${key}, Value: ${user[key]}`);
});
Object.values(user).forEach(value => {
console.log(`Value: ${value}`);
});
Object.entries(user).forEach(([key, value]) => {
console.log(`Entry - Key: ${key}, Value: ${value}`);
});
处理网络请求和耗时操作的现代方式,避免回调地狱。
// 1. Promise 基本用法
function fetchData(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`请求失败: ${xhr.status}`));
}
};
xhr.onerror = () => {
reject(new Error('网络错误'));
};
xhr.send();
});
}
fetchData('https://api.example.com/data')
.then(data => {
console.log('数据获取成功:', data);
return fetchData('https://api.example.com/more-data?id=' + data.id); // 链式调用
})
.then(moreData => {
console.log('更多数据获取成功:', moreData);
})
.catch(error => {
console.error('数据获取失败:', error);
})
.finally(() => {
console.log('请求完成,无论成功或失败。');
});
// 2. Async/Await (基于 Promise 的语法糖)
async function getPosts() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1'); // 等待 fetch 完成
if (!response.ok) {
throw new Error(`HTTP 错误! 状态: ${response.status}`);
}
const post = await response.json(); // 等待 JSON 解析完成
console.log('获取到的 Post:', post);
const commentsResponse = await fetch(`https://jsonplaceholder.typicode.com/posts/${post.id}/comments`);
if (!commentsResponse.ok) {
throw new Error(`HTTP 错误! 状态: ${commentsResponse.status}`);
}
const comments = await commentsResponse.json();
console.log('获取到的评论:', comments);
} catch (error) {
console.error('获取数据时发生错误:', error);
} finally {
console.log('异步操作结束。');
}
}
getPosts();
// 3. Promise.all() - 并行处理多个 Promise
const promise1 = Promise.resolve(3);
const promise2 = 42; // 非 Promise 值也会被包装成 Promise
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log('所有 Promise 都已解决:', values); // [3, 42, "foo"]
})
.catch(error => {
console.error('其中一个 Promise 失败:', error);
});
// 4. Promise.race() - 哪个 Promise 先解决或拒绝,就返回哪个结果
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 500, 'one'));
const p2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'two'));
Promise.race([p1, p2])
.then((value) => {
console.log('Race Winner:', value); // 'two'
});
客户端表单验证是提升用户体验的重要环节。
// HTML 结构 (假设有一个简单的表单)
/*
<form id="myForm">
<input type="email" id="emailInput" placeholder="请输入邮箱">
<div id="emailError" style="color: red;"></div>
<input type="password" id="passwordInput" placeholder="请输入密码">
<div id="passwordError" style="color: red;"></div>
<button type="submit">提交</button>
</form>
*/
document.addEventListener('DOMContentLoaded', () => {
const myForm = document.getElementById('myForm');
const emailInput = document.getElementById('emailInput');
const passwordInput = document.getElementById('passwordInput');
const emailError = document.getElementById('emailError');
const passwordError = document.getElementById('passwordError');
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(String(email).toLowerCase());
}
function validatePassword(password) {
// 密码至少6位,包含数字和字母
return password.length >= 6 && /[0-9]/.test(password) && /[a-zA-Z]/.test(password);
}
myForm.addEventListener('submit', function(event) {
event.preventDefault(); // 阻止表单默认提交行为
let isValid = true;
// 验证邮箱
if (!validateEmail(emailInput.value)) {
emailError.textContent = '请输入有效的邮箱地址。';
isValid = false;
} else {
emailError.textContent = '';
}
// 验证密码
if (!validatePassword(passwordInput.value)) {
passwordError.textContent = '密码至少6位,且包含数字和字母。';
isValid = false;
} else {
passwordError.textContent = '';
}
if (isValid) {
alert('表单验证通过,准备提交!');
// 可以在这里发送 AJAX 请求提交表单数据
// this.submit(); // 或者如果希望原生提交,取消注释
} else {
console.log('表单验证失败!');
}
});
// 实时验证 (可选)
emailInput.addEventListener('input', () => {
if (emailInput.value === '' || validateEmail(emailInput.value)) {
emailError.textContent = '';
}
});
passwordInput.addEventListener('input', () => {
if (passwordInput.value === '' || validatePassword(passwordInput.value)) {
passwordError.textContent = '';
}
});
});
浏览器本地存储,用于持久化数据或会话数据。
// 设置数据
localStorage.setItem('username', 'Alice');
sessionStorage.setItem('tempData', JSON.stringify({ item1: 'value1', item2: 'value2' }));
// 获取数据
const username = localStorage.getItem('username');
const tempData = JSON.parse(sessionStorage.getItem('tempData'));
console.log('从 localStorage 获取:', username); // Alice
console.log('从 sessionStorage 获取:', tempData); // { item1: 'value1', item2: 'value2' }
// 移除数据
localStorage.removeItem('username');
sessionStorage.clear(); // 清除 sessionStorage 中所有数据
// 检查某个键是否存在
if (localStorage.getItem('username') === null) {
console.log('username 已被移除。');
}
// 遍历所有存储的键
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(`localStorage Key: ${key}, Value: ${value}`);
}
编写可复用的工具函数是提高代码质量和开发效率的关键。
在事件持续触发时,只在事件停止后 N 毫秒执行一次回调函数。常用于搜索框输入、窗口 resize 等。
/**
* 防抖函数
* @param {Function} func - 要执行的函数
* @param {number} delay - 延迟时间(毫秒)
* @param {boolean} immediate - 是否立即执行一次
* @returns {Function} 防抖后的函数
*/
function debounce(func, delay, immediate = false) {
let timeout;
let result;
return function(...args) {
const context = this; // 保存函数上下文
const later = function() {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, delay);
if (callNow) {
result = func.apply(context, args);
}
return result;
};
}
// 示例使用
function search(query) {
console.log('正在搜索:', query);
}
const debouncedSearch = debounce(search, 500);
// 模拟用户输入
// debouncedSearch('hello');
// debouncedSearch('hello world'); // 0.1秒后再次输入,会重新计时
// setTimeout(() => debouncedSearch('final query'), 600); // 最终只会执行这一次
document.addEventListener('DOMContentLoaded', () => {
const inputElement = document.getElementById('searchInput');
if (inputElement) {
inputElement.addEventListener('input', debounce((e) => {
console.log('防抖后的输入内容:', e.target.value);
}, 500));
}
});
// HTML 假设: <input type="text" id="searchInput" placeholder="搜索...">
在事件持续触发时,每隔 N 毫秒执行一次回调函数。常用于滚动加载、拖拽事件等。
/**
* 节流函数
* @param {Function} func - 要执行的函数
* @param {number} interval - 间隔时间(毫秒)
* @returns {Function} 节流后的函数
*/
function throttle(func, interval) {
let timeout;
let lastArgs;
let lastThis;
let lastExecTime = 0; // 上次执行时间
return function(...args) {
const context = this;
const now = Date.now();
// 首次执行或距离上次执行超过间隔时间
if (now - lastExecTime > interval) {
func.apply(context, args);
lastExecTime = now;
} else {
// 在间隔时间内,设置定时器,等待时间到了再执行
lastArgs = args;
lastThis = context;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(lastThis, lastArgs);
lastExecTime = Date.now(); // 定时器执行后更新时间
}, interval - (now - lastExecTime));
}
};
}
// 示例使用
function handleScroll() {
console.log('滚动事件触发...');
}
const throttledScroll = throttle(handleScroll, 1000); // 每秒最多执行一次
// window.addEventListener('scroll', throttledScroll);
一个简单的用于设置、获取和删除 Cookie 的工具函数。
// 设置 Cookie
function setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
// 获取 Cookie
function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for(let i=0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// 删除 Cookie
function eraseCookie(name) {
document.cookie = name + '=; Max-Age=-99999999; path=/'; // 设置过期时间为过去
}
// 示例
setCookie('user_token', 'abc123xyz', 7); // 设置名为 user_token 的 cookie,7天后过期
console.log('获取 user_token:', getCookie('user_token'));
setCookie('lang', 'zh-CN'); // 会话 Cookie,浏览器关闭即失效
console.log('获取 lang:', getCookie('lang'));
eraseCookie('lang');
console.log('删除 lang 后再获取:', getCookie('lang')); // null
从 URL 中获取查询参数。
/**
* 解析 URL 查询参数
* @param {string} url - 待解析的 URL 字符串 (可选,默认为当前页面 URL)
* @returns {Object} 包含所有查询参数的对象
*/
function getQueryParams(url = window.location.search) {
const params = {};
// 确保处理的是查询字符串部分
const queryString = url.includes('?') ? url.split('?')[1] : url;
if (queryString) {
queryString.split('&').forEach(param => {
const parts = param.split('=');
const key = decodeURIComponent(parts[0]);
const value = parts.length > 1 ? decodeURIComponent(parts.slice(1).join('=')) : '';
params[key] = value;
});
}
return params;
}
// 示例
const currentUrlParams = getQueryParams();
console.log('当前 URL 参数:', currentUrlParams); // 例如: { id: "123", name: "test" }
const customUrlParams = getQueryParams('https://example.com/page?category=webdev&sort=date&filter=hot%20topics');
console.log('自定义 URL 参数:', customUrlParams); // { category: "webdev", sort: "date", filter: "hot topics" }
// 使用 URLSearchParams (现代浏览器推荐)
function getQueryParamsModern(url = window.location.search) {
const params = {};
const urlParams = new URLSearchParams(url);
for (const [key, value] of urlParams.entries()) {
params[key] = value;
}
return params;
}
console.log('现代方法获取 URL 参数:', getQueryParamsModern('https://example.com/page?category=webdev&sort=date'));
前端性能是用户体验的基石,以下是一些常见的优化技巧。
只有当图片进入视口时才加载,减少首屏加载时间和带宽消耗。
<!-- HTML 结构 -->
<img data-src="path/to/image1.jpg" alt="Description 1" class="lazyload-img">
<img data-src="path/to/image2.png" alt="Description 2" class="lazyload-img">
<img data-src="path/to/image3.gif" alt="Description 3" class="lazyload-img">
<!-- 可以添加一个占位符图片或者低质量图片 -->
<img src="placeholder.jpg" data-src="path/to/image4.jpg" alt="Description 4" class="lazyload-img">
document.addEventListener('DOMContentLoaded', () => {
const lazyImages = document.querySelectorAll('.lazyload-img');
if ('IntersectionObserver' in window) {
// 使用 Intersection Observer API
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 将 data-src 赋值给 src
img.removeAttribute('data-src'); // 移除 data-src 属性
img.onload = () => {
console.log('图片加载完成:', img.src);
};
img.onerror = () => {
console.error('图片加载失败:', img.src);
};
observer.unobserve(img); // 一旦加载,停止观察
}
});
}, {
rootMargin: '0px 0px 100px 0px' // 在图片进入视口前 100px 开始加载
});
lazyImages.forEach(img => {
observer.observe(img);
});
} else {
// 降级方案:监听滚动事件 (效率较低,不推荐用于大量图片)
console.warn('浏览器不支持 IntersectionObserver,使用降级方案。');
let lazyLoadThrottleTimeout;
function lazyload() {
if (lazyLoadThrottleTimeout) {
clearTimeout(lazyLoadThrottleTimeout);
}
lazyLoadThrottleTimeout = setTimeout(() => {
lazyImages.forEach(img => {
// getBoundingClientRect().top 小于 window.innerHeight (图片顶部进入视口)
// 或者 img.getBoundingClientRect().bottom 大于 0 (图片底部仍在视口内)
if (img.dataset.src && img.getBoundingClientRect().top < window.innerHeight + 100) {
img.src = img.dataset.src;
img.removeAttribute('data-src');
img.onload = () => console.log('图片加载完成 (降级):', img.src);
img.onerror = () => console.error('图片加载失败 (降级):', img.src);
}
});
// 移除已加载的图片,减少循环次数
lazyImages = Array.from(lazyImages).filter(img => img.hasAttribute('data-src'));
if (lazyImages.length === 0) {
window.removeEventListener('scroll', lazyload);
window.removeEventListener('resize', lazyload);
}
}, 200); // 节流
}
window.addEventListener('scroll', lazyload);
window.addEventListener('resize', lazyload);
lazyload(); // 首次加载执行一次
}
});
注意: 对于图片懒加载,强烈推荐使用 Intersection Observer API,因为它比传统的滚动监听性能更好、更高效。如果需要兼容老旧浏览器,才考虑滚动监听的降级方案。
将事件监听器添加到父元素而非每个子元素,提高性能,尤其适用于动态生成的元素。
// HTML 假设
/*
<ul id="myList">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<button id="addItemBtn">添加新项目</button>
*/
document.addEventListener('DOMContentLoaded', () => {
const myList = document.getElementById('myList');
const addItemBtn = document.getElementById('addItemBtn');
// 使用事件委托
if (myList) {
myList.addEventListener('click', function(event) {
// 检查点击事件是否来源于 li 元素或其内部
if (event.target.tagName === 'LI') {
console.log('点击了列表项:', event.target.textContent);
event.target.style.backgroundColor = 'yellow';
}
});
}
// 动态添加新项目
if (addItemBtn) {
let itemCount = 3;
addItemBtn.addEventListener('click', () => {
itemCount++;
const newItem = document.createElement('li');
newItem.textContent = `Item ${itemCount} (新)`;
myList.appendChild(newItem);
console.log('添加了新项目。');
});
}
});
用于字符串匹配和验证。
// 1. 验证邮箱
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log('[email protected] 邮箱验证:', emailRegex.test('[email protected]')); // true
console.log('invalid-email 邮箱验证:', emailRegex.test('invalid-email')); // false
// 2. 验证手机号 (中国大陆,宽松匹配)
const phoneRegex = /^1[3-9]\d{9}$/;
console.log('13812345678 手机号验证:', phoneRegex.test('13812345678')); // true
console.log('12345678901 手机号验证:', phoneRegex.test('12345678901')); // false
// 3. 验证 URL
const urlRegex = /^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/[a-zA-Z0-9]+\.[^\s]{2,}|[a-zA-Z0-9]+\.[^\s]{2,})$/i;
console.log('https://www.google.com URL 验证:', urlRegex.test('https://www.google.com')); // true
console.log('invalid url URL 验证:', urlRegex.test('invalid url')); // false
// 4. 验证数字 (整数或浮点数)
const numberRegex = /^-?\d+(\.\d+)?$/;
console.log('123 数字验证:', numberRegex.test('123')); // true
console.log('3.14 数字验证:', numberRegex.test('3.14')); // true
console.log('-100 数字验证:', numberRegex.test('-100')); // true
console.log('abc 数字验证:', numberRegex.test('abc')); // false
// 5. 替换字符串中的所有空格
const textWithSpaces = "Hello World !";
const noSpacesText = textWithSpaces.replace(/\s+/g, ''); // g 表示全局匹配,+ 表示匹配一个或多个空格
console.log('移除空格:', noSpacesText); // HelloWorld!
// 6. 提取数字
const strWithNumbers = "订单号: ORD12345, 金额: 99.50元";
const numbersExtracted = strWithNumbers.match(/\d+(\.\d+)?/g);
console.log('提取数字:', numbersExtracted); // ["12345", "99.50"]
避免修改引用类型数据时影响原始数据。
// 简单深拷贝 (适用于 JSON 安全的数据类型:数字、字符串、布尔、null、数组、普通对象)
function deepCloneSimple(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
return JSON.parse(JSON.stringify(obj));
}
const originalObjSimple = {
name: 'Test',
age: 25,
address: { city: 'Beijing', street: 'Road A' },
hobbies: ['coding', 'reading'],
func: function() { console.log('hello'); }, // 函数会被忽略
date: new Date() // Date 对象会变成字符串
};
const clonedObjSimple = deepCloneSimple(originalObjSimple);
clonedObjSimple.address.city = 'Shanghai';
clonedObjSimple.hobbies.push('travel');
console.log('原始对象 (简单):', originalObjSimple);
console.log('克隆对象 (简单):', clonedObjSimple);
// 更完善的深拷贝 (处理函数、Date、RegExp、循环引用等,更复杂,通常会用 lodash.cloneDeep)
function deepClone(obj, hash = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
// 避免循环引用
if (hash.has(obj)) return hash.get(obj);
// 处理特殊对象类型
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
const cloneObj = Array.isArray(obj) ? [] : {};
hash.set(obj, cloneObj); // 存储已克隆的对象
for (const key in obj) {
// 确保是对象自身的属性,而不是原型链上的属性
if (Object.hasOwnProperty.call(obj, key)) {
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
const originalObjComplex = {
a: 1,
b: { c: 2 },
d: [3, { e: 4 }],
f: new Date(),
g: function() { console.log('complex'); },
h: /test/g
};
originalObjComplex.self = originalObjComplex; // 循环引用
const clonedObjComplex = deepClone(originalObjComplex);
clonedObjComplex.b.c = 99;
clonedObjComplex.d[1].e = 88;
clonedObjComplex.g(); // 可以执行
console.log('原始对象 (复杂):', originalObjComplex);
console.log('克隆对象 (复杂):', clonedObjComplex);
console.log('循环引用是否正确处理:', clonedObjComplex.self === clonedObjComplex);
根据用户语言显示不同文本。
const messages = {
'en': {
'greeting': 'Hello, {name}!',
'farewell': 'Goodbye!',
'welcome': 'Welcome to our website!'
},
'zh-CN': {
'greeting': '你好,{name}!',
'farewell': '再见!',
'welcome': '欢迎来到我们的网站!'
},
'es': {
'greeting': '¡Hola, {name}!',
'farewell': '¡Adiós!',
'welcome': '¡Bienvenido a nuestro sitio web!'
}
};
/**
* 获取翻译文本
* @param {string} key - 翻译键
* @param {string} [locale=navigator.language] - 语言环境,默认为浏览器语言
* @param {Object} [params={}] - 替换参数,例如 { name: 'Alice' }
* @returns {string} 翻译后的文本
*/
function getTranslation(key, locale = navigator.language, params = {}) {
// 简单处理语言代码,例如 zh-CN -> zh
const primaryLocale = locale.split('-')[0];
let translation = messages[locale]?.[key] || messages[primaryLocale]?.[key] || messages['en'][key];
if (!translation) {
return `[Missing translation for ${key}]`;
}
// 替换参数
for (const paramKey in params) {
if (Object.hasOwnProperty.call(params, paramKey)) {
translation = translation.replace(`{${paramKey}}`, params[paramKey]);
}
}
return translation;
}
// 示例使用
console.log(getTranslation('welcome', 'zh-CN')); // 欢迎来到我们的网站!
console.log(getTranslation('greeting', 'en', { name: 'Bob' })); // Hello, Bob!
console.log(getTranslation('farewell', 'es')); // ¡Adiós!
console.log(getTranslation('unknown_key', 'zh-CN')); // [Missing translation for unknown_key]
// 动态设置语言
let currentLanguage = 'en';
function setLanguage(lang) {
currentLanguage = lang;
document.documentElement.lang = lang; // 设置 HTML lang 属性
console.log(`语言已切换到: ${lang}`);
// 重新渲染页面或更新相关文本
}
// setLanguage('zh-CN');
// console.log(getTranslation('greeting', currentLanguage, { name: '李华' }));
在组件之间或非父子关系之间进行通信。
document.addEventListener('DOMContentLoaded', () => {
const eventLog = document.getElementById('eventLog');
if (!eventLog) return;
function logEvent(message) {
const li = document.createElement('li');
li.textContent = message;
eventLog.appendChild(li);
}
// 1. 创建自定义事件
const myCustomEvent = new CustomEvent('dataLoaded', {
detail: {
// detail 属性用于传递额外数据
timestamp: Date.now(),
data: { id: 1, name: 'Sample Data' }
},
bubbles: true, // 事件是否冒泡
cancelable: true // 事件是否可以取消 (preventDefault())
});
// 2. 监听自定义事件
document.addEventListener('dataLoaded', function(event) {
logEvent(`'dataLoaded' 事件触发!`);
logEvent(`事件源: ${event.target.id || 'document'}`);
logEvent(`详细数据: ${JSON.stringify(event.detail, null, 2)}`);
if (event.cancelable && Math.random() < 0.5) {
event.preventDefault(); // 模拟取消事件
logEvent('事件被取消!');
}
});
// 3. 触发自定义事件
setTimeout(() => {
logEvent('正在派发 dataLoaded 事件...');
document.dispatchEvent(myCustomEvent); // 在 document 上派发
}, 1000);
// 另一个在特定元素上触发的例子
const customElement = document.createElement('div');
customElement.id = 'my-custom-element';
customElement.style.cssText = 'padding: 10px; background: #e0f7fa; border: 1px solid #b2ebf2; margin-top: 20px;';
customElement.textContent = '点击我派发事件';
document.body.appendChild(customElement);
customElement.addEventListener('click', () => {
const anotherCustomEvent = new CustomEvent('elementClicked', {
detail: { clicks: 1 },
bubbles: true
});
customElement.dispatchEvent(anotherCustomEvent);
logEvent('Element Clicked 事件在 customElement 上派发。');
});
document.addEventListener('elementClicked', (event) => {
logEvent(`'elementClicked' 事件捕获 (冒泡):`);
logEvent(` 事件源: ${event.target.id}`);
logEvent(` 点击次数: ${event.detail.clicks}`);
});
});
/* HTML 结构补充:
<ul id="eventLog" style="border: 1px solid #ddd; padding: 10px; min-height: 100px; background: #f9f9f9;">
<li>事件日志:</li>
</ul>
*/
总结: 以上就是前端开发中一些非常常见且实用的代码片段。它们涵盖了从页面的结构、样式到交互逻辑的方方面面。掌握并灵活运用这些片段,将大大提高您的开发效率,帮助您构建更加健壮、高效和用户友好的前端应用。
作为一名前端架构师,我建议您不仅仅是复制粘贴这些代码,更重要的是理解它们背后的原理和最佳实践。持续学习和实践,是成为一名优秀前端工程师的关键。