摸鱼宝典的终极目标:用最少代码,搞最大事情
摸鱼宝典的终极目标:用最少代码,搞最大事情
前端开发的世界里,效率就是王道。能用三行代码解决的问题绝不写十行,能复用的逻辑绝不重复造轮子。摸鱼不是偷懒,而是用智慧解放双手。
代码复用:从函数到组件
函数是代码复用的最小单位。一个简单的例子:需要频繁格式化日期,与其每次写一长串new Date().toLocaleString()
,不如封装成函数:
const formatDate = (date = new Date()) =>
date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
// 使用
formatDate(); // "2023/05/15"
formatDate(new Date('2022-01-01')); // "2022/01/01"
组件化更将复用提升到新高度。比如这个可复用的加载指示器:
const Spinner = ({ size = 24, color = '#1890ff' }) => (
<div
className="spinner"
style={{
width: size,
height: size,
border: `3px solid ${color}20`,
borderTopColor: color,
borderRadius: '50%',
animation: 'spin 1s linear infinite'
}}
/>
);
// 使用
<Spinner />
<Spinner size={48} color="#ff4d4f" />
善用语言特性
现代JavaScript提供了大量语法糖。解构赋值能瞬间简化代码:
// 旧写法
const firstName = user.firstName;
const lastName = user.lastName;
// 新写法
const { firstName, lastName } = user;
可选链操作符(?.)和空值合并运算符(??)让代码更健壮:
// 以前
const street = user && user.address && user.address.street;
// 现在
const street = user?.address?.street ?? '默认街道';
CSS魔法:少写多效
CSS变量配合calc()能实现动态样式:
:root {
--base-size: 16px;
--padding: calc(var(--base-size) * 1.5);
}
.card {
padding: var(--padding);
font-size: calc(var(--base-size) + 2px);
}
单行居中大法:
.center {
display: grid;
place-items: center;
}
工具函数库:站在巨人肩上
lodash的get函数解决深层对象访问:
import _ from 'lodash';
const user = { profile: { address: { city: '北京' } } };
_.get(user, 'profile.address.city', '未知'); // "北京"
date-fns处理日期比原生API更友好:
import { format, addDays } from 'date-fns';
format(new Date(), 'yyyy-MM-dd'); // "2023-05-15"
addDays(new Date(), 7); // 一周后的日期
自动化脚本:一劳永逸
用Node.js写个批量重命名工具:
const fs = require('fs');
const path = require('path');
const folderPath = './images';
fs.readdirSync(folderPath).forEach((file, index) => {
const ext = path.extname(file);
fs.renameSync(
path.join(folderPath, file),
path.join(folderPath, `image_${index}${ext}`)
);
});
浏览器API的妙用
Clipboard API实现一键复制:
const copyToClipboard = async (text) => {
try {
await navigator.clipboard.writeText(text);
console.log('复制成功');
} catch (err) {
console.error('复制失败:', err);
}
};
Intersection Observer实现懒加载:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
框架的威力
React Hooks让状态逻辑复用变得简单:
const useToggle = (initialState = false) => {
const [state, setState] = useState(initialState);
const toggle = () => setState(!state);
return [state, toggle];
};
// 使用
const [isDark, toggleDark] = useToggle(false);
<button onClick={toggleDark}>
{isDark ? '切换亮色' : '切换暗色'}
</button>
Vue的Composition API同样强大:
import { ref } from 'vue';
export function useCounter(initialValue = 0) {
const count = ref(initialValue);
const increment = () => count.value++;
return { count, increment };
}
// 使用
const { count, increment } = useCounter();
构建工具自动化
webpack的alias配置避免冗长路径:
// webpack.config.js
resolve: {
alias: {
'@': path.resolve(__dirname, 'src/'),
'@components': path.resolve(__dirname, 'src/components/')
}
}
// 使用
import Button from '@/components/Button';
正则表达式:文本处理的瑞士军刀
提取URL参数的正则:
const getUrlParams = (url) => {
const regex = /[?&]([^=#]+)=([^&#]*)/g;
const params = {};
let match;
while (match = regex.exec(url)) {
params[match[1]] = match[2];
}
return params;
};
getUrlParams('https://example.com?name=张三&age=25');
// { name: "张三", age: "25" }
设计模式的应用
单例模式确保全局唯一实例:
class Logger {
constructor() {
if (!Logger.instance) {
this.logs = [];
Logger.instance = this;
}
return Logger.instance;
}
log(message) {
this.logs.push(message);
console.log(message);
}
}
const logger1 = new Logger();
const logger2 = new Logger();
logger1 === logger2; // true
性能优化技巧
防抖与节流的实现:
// 防抖
const debounce = (fn, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
// 节流
const throttle = (fn, delay) => {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime >= delay) {
fn(...args);
lastTime = now;
}
};
};
现代CSS方案
CSS Grid实现圣杯布局:
.container {
display: grid;
grid-template:
"header header header" 80px
"nav main aside" 1fr
"footer footer footer" 60px
/ 200px 1fr 200px;
}
header { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
aside { grid-area: aside; }
footer { grid-area: footer; }
类型系统的帮助
TypeScript泛型避免重复定义:
interface Response<T> {
code: number;
data: T;
message: string;
}
// 使用
type UserResponse = Response<{
id: number;
name: string;
}>;
type ProductResponse = Response<{
id: string;
price: number;
}>;
不可变数据的艺术
使用展开运算符避免直接修改:
const user = { name: '张三', age: 25 };
// 更新年龄
const updatedUser = { ...user, age: 26 };
// 添加属性
const userWithEmail = { ...user, email: 'zhangsan@example.com' };
函数式编程的优雅
数组方法链式调用:
const users = [
{ id: 1, name: '张三', age: 25, active: true },
{ id: 2, name: '李四', age: 30, active: false }
];
const result = users
.filter(user => user.active)
.map(user => ({
...user,
name: user.name.toUpperCase()
}))
.sort((a, b) => a.age - b.age);
浏览器存储策略
localStorage封装:
const storage = {
get(key) {
try {
return JSON.parse(localStorage.getItem(key));
} catch {
return localStorage.getItem(key);
}
},
set(key, value) {
const data = typeof value === 'string' ? value : JSON.stringify(value);
localStorage.setItem(key, data);
},
remove(key) {
localStorage.removeItem(key);
}
};
// 使用
storage.set('user', { name: '张三' });
const user = storage.get('user'); // { name: "张三" }
动画性能优化
使用will-change提示浏览器:
.animated-element {
will-change: transform, opacity;
transition: transform 0.3s ease, opacity 0.3s ease;
}
requestAnimationFrame实现流畅动画:
const animate = () => {
element.style.transform = `translateX(${position}px)`;
position += 1;
if (position < 100) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
错误处理的艺术
全局错误捕获:
window.addEventListener('error', (event) => {
console.error('全局错误:', event.error);
// 上报错误到服务器
reportErrorToServer(event.error);
return true; // 阻止默认错误处理
});
window.addEventListener('unhandledrejection', (event) => {
console.error('未处理的Promise拒绝:', event.reason);
});
移动端适配方案
viewport meta标签配合rem:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
html {
font-size: calc(100vw / 7.5); /* 设计稿宽度750px时,1rem = 100px */
}
.box {
width: 1.5rem; /* 150px */
height: 1rem; /* 100px */
}
代码分割与懒加载
动态导入实现按需加载:
const loadModule = async () => {
const module = await import('./heavyModule.js');
module.doSomething();
};
// React中的懒加载组件
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
实用代码片段
生成随机ID:
const generateId = () =>
Math.random().toString(36).substr(2, 9);
// 使用
const id = generateId(); // "4f7d8e2b1"
深度克隆对象:
const deepClone = obj => JSON.parse(JSON.stringify(obj));
// 更完善的方案
const deepClone = obj => {
if (obj === null || typeof obj !== 'object') return obj;
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
};
调试技巧
console的更多用法:
console.table([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 }
]);
console.time('fetch');
await fetch('https://api.example.com/data');
console.timeEnd('fetch'); // fetch: 256ms
代码质量工具
ESLint自动修复:
eslint --fix src/**/*.js
Prettier统一代码风格:
// .prettierrc
{
"semi": false,
"singleQuote": true,
"printWidth": 80
}
文档即代码
JSDoc生成API文档:
/**
* 计算两个数的和
* @param {number} a - 第一个加数
* @param {number} b - 第二个加数
* @returns {number} 两数之和
*/
function add(a, b) {
return a + b;
}
持续集成自动化
Git Hooks防止错误提交:
// package.json
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm run test"
}
},
"lint-staged": {
"*.js": ["eslint --fix", "git add"]
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn