浏览器常见面试题及答案(续)
五、前端性能优化策略及应用实例
1. 懒加载组件封装方法
图片懒加载是前端性能优化的重要手段,以下是一个基于Intersection Observer API的懒加载组件封装实现:
class LazyLoad {
constructor(options = {}) {
this.options = {
root: null,
rootMargin: '0px',
threshold: 0.1,
dataSrc: 'data-src',
...options
};
this.observer = null;
this.init();
}
init() {
// 检查浏览器是否支持IntersectionObserver
if ('IntersectionObserver' in window) {
this.observer = new IntersectionObserver(this.handleIntersect.bind(this), this.options);
this.observeElements();
} else {
// 降级处理:立即加载所有图片
this.loadAllImages();
}
}
observeElements() {
const images = document.querySelectorAll(`img[${this.options.dataSrc}]`);
images.forEach(img => this.observer.observe(img));
}
handleIntersect(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const src = img.getAttribute(this.options.dataSrc);
if (src) {
img.src = src;
img.removeAttribute(this.options.dataSrc);
img.classList.add('loaded');
}
this.observer.unobserve(img);
}
});
}
loadAllImages() {
const images = document.querySelectorAll(`img[${this.options.dataSrc}]`);
images.forEach(img => {
const src = img.getAttribute(this.options.dataSrc);
if (src) {
img.src = src;
img.removeAttribute(this.options.dataSrc);
img.classList.add('loaded');
}
});
}
}
// 使用示例
document.addEventListener('DOMContentLoaded', () => {
new LazyLoad({
rootMargin: '200px 0px', // 提前200px加载
threshold: 0.2
});
});
2. 防抖与节流函数封装
在处理高频触发事件时,防抖(Debounce)和节流(Throttle)是常用的优化手段:
// 防抖函数:延迟执行,重复触发则重置计时器
export function debounce(fn, delay = 300, immediate = false) {
let timer = null;
return function(...args) {
const context = this;
// 立即执行的情况
if (immediate && !timer) {
fn.apply(context, args);
}
// 清除之前的计时器
if (timer) clearTimeout(timer);
// 设置新的计时器
timer = setTimeout(() => {
if (!immediate) {
fn.apply(context, args);
}
timer = null;
}, delay);
};
}
// 节流函数:固定间隔执行一次
export function throttle(fn, limit = 300) {
let inThrottle;
let lastFn;
let lastTime;
return function(...args) {
const context = this;
if (!inThrottle) {
fn.apply(context, args);
lastTime = Date.now();
inThrottle = true;
} else {
clearTimeout(lastFn);
lastFn = setTimeout(() => {
if (Date.now() - lastTime >= limit) {
fn.apply(context, args);
lastTime = Date.now();
}
}, Math.max(limit - (Date.now() - lastTime), 0));
}
};
}
3. 组件化缓存策略实现
在现代前端框架中,合理的缓存策略可以显著提升应用性能:
// 基于Vue 3的组件缓存实现示例
import { ref, computed, onMounted, onUnmounted } from 'vue';
export default {
name: 'CachedComponent',
props: {
cacheKey: {
type: String,
required: true
},
fetchData: {
type: Function,
required: true
},
cacheTime: {
type: Number,
default: 60 * 1000 // 默认缓存1分钟
}
},
setup(props) {
const cacheStorage = ref({});
const cacheExpiry = ref({});
const data = ref(null);
const isLoading = ref(false);
const error = ref(null);
// 检查缓存是否有效
const isCacheValid = computed(() => {
const expiry = cacheExpiry.value[props.cacheKey];
return expiry && Date.now() < expiry;
});
// 从缓存中获取数据
const getCache = () => {
if (isCacheValid.value) {
return cacheStorage.value[props.cacheKey];
}
return null;
};
// 设置缓存
const setCache = (value) => {
cacheStorage.value[props.cacheKey] = value;
cacheExpiry.value[props.cacheKey] = Date.now() + props.cacheTime;
};
// 加载数据
const loadData = async () => {
isLoading.value = true;
error.value = null;
try {
// 优先使用缓存
const cached = getCache();
if (cached) {
data.value = cached;
return;
}
// 从服务器获取数据
const result = await props.fetchData();
data.value = result;
setCache(result);
} catch (err) {
error.value = err;
} finally {
isLoading.value = false;
}
};
// 初始化加载
onMounted(() => {
loadData();
});
// 清理缓存
onUnmounted(() => {
// 可以实现按需清理缓存的逻辑
});
return {
data,
isLoading,
error,
refresh: loadData // 提供刷新方法
};
}
};
六、浏览器缓存机制与应用实例
1. HTTP缓存配置示例
// Express.js服务器端缓存配置示例
const express = require('express');
const app = express();
// 静态资源缓存配置
app.use('/static', express.static('public', {
maxAge: 3600 * 1000, // 1小时
etag: true,
lastModified: true
}));
// 动态资源缓存控制
app.get('/api/data', (req, res) => {
// 设置缓存控制头
res.setHeader('Cache-Control', 'public, max-age=60'); // 60秒公共缓存
// 生成响应数据
const data = { message: 'Hello World', timestamp: Date.now() };
res.json(data);
});
// 协商缓存示例
app.get('/api/posts', (req, res) => {
const { posts, etag } = getPostsFromDatabase();
// 检查客户端发送的ETag
if (req.headers['if-none-match'] === etag) {
res.status(304).end();
return;
}
// 设置新的ETag
res.setHeader('ETag', etag);
res.json(posts);
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
2. Service Worker缓存实现
// service-worker.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('static-v1').then(cache => {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/main.js',
'/images/logo.png'
]);
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(
keys.filter(key => key.startsWith('static-') && key !== 'static-v1')
.map(key => caches.delete(key))
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(response => {
// 缓存优先策略
if (response) return response;
// 从网络获取
return fetch(event.request).then(networkResponse => {
// 克隆响应,因为响应只能被使用一次
const responseToCache = networkResponse.clone();
// 将新的响应添加到缓存
caches.open('static-v1').then(cache => {
cache.put(event.request, responseToCache);
});
return networkResponse;
});
})
);
});
3. Web Storage使用封装
// storage.js - 本地存储封装
export default class Storage {
constructor(prefix = 'app_') {
this.prefix = prefix;
}
// 获取完整的键名
getKey(key) {
return `${this.prefix}${key}`;
}
// 设置本地存储项
setItem(key, value, expires = null) {
const item = {
value,
expires: expires ? Date.now() + expires : null
};
try {
localStorage.setItem(this.getKey(key), JSON.stringify(item));
} catch (e) {
console.error('Failed to set localStorage item:', e);
}
}
// 获取本地存储项
getItem(key) {
try {
const itemStr = localStorage.getItem(this.getKey(key));
if (!itemStr) return null;
const item = JSON.parse(itemStr);
// 检查是否过期
if (item.expires && Date.now() > item.expires) {
localStorage.removeItem(this.getKey(key));
return null;
}
return item.value;
} catch (e) {
console.error('Failed to get localStorage item:', e);
return null;
}
}
// 移除本地存储项
removeItem(key) {
try {
localStorage.removeItem(this.getKey(key));
} catch (e) {
console.error('Failed to remove localStorage item:', e);
}
}
// 清空本地存储
clear() {
try {
const keysToRemove = [];
// 收集所有需要删除的键
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.startsWith(this.prefix)) {
keysToRemove.push(key);
}
}
// 删除这些键
keysToRemove.forEach(key => localStorage.removeItem(key));
} catch (e) {
console.error('Failed to clear localStorage:', e);
}
}
}
// 使用示例
const storage = new Storage('myapp_');
storage.setItem('user', { name: 'John', age: 30 }, 3600 * 1000); // 1小时后过期
const user = storage.getItem('user');
七、组件封装最佳实践
1. 通用原则
- 单一职责原则:每个组件只负责一个特定的功能或任务
- 高内聚低耦合:组件内部联系紧密,与外部依赖尽可能少
- 可配置性:通过props提供灵活的配置选项
- 无状态与有状态分离:将展示组件和容器组件分离
- 生命周期管理:合理使用组件生命周期钩子
- 错误边界处理:确保组件在异常情况下仍能正常运行
2. 封装一个通用的模态框组件
以下是一个基于React的通用模态框组件封装示例:
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
const Modal = ({
isOpen,
onClose,
title,
children,
confirmText = '确认',
cancelText = '取消',
onConfirm,
showFooter = true,
className = '',
backdropClassName = '',
animationDuration = 300
}) => {
const [isAnimating, setIsAnimating] = useState(false);
// 控制动画
useEffect(() => {
if (isOpen) {
setIsAnimating(true);
} else {
// 延迟关闭以完成动画
setTimeout(() => {
setIsAnimating(false);
}, animationDuration);
}
}, [isOpen, animationDuration]);
// 点击背景关闭
const handleBackdropClick = (e) => {
if (e.target === e.currentTarget) {
onClose();
}
};
// 阻止冒泡,避免点击内容时关闭模态框
const handleContentClick = (e) => {
e.stopPropagation();
};
// 确认按钮点击事件
const handleConfirm = () => {
if (onConfirm) {
onConfirm();
} else {
onClose();
}
};
return (
isOpen && (
<div
className={`fixed inset-0 flex items-center justify-center z-50 transition-opacity duration-${animationDuration} ${
isAnimating ? 'opacity-100' : 'opacity-0'
} ${backdropClassName}`}
onClick={handleBackdropClick}
>
<div
className={`bg-white rounded-lg shadow-xl max-w-md w-full mx-4 transform transition-all duration-${animationDuration} ${
isAnimating ? 'scale-100 opacity-100' : 'scale-95 opacity-0'
} ${className}`}
onClick={handleContentClick}
>
{/* 标题 */}
{title && (
<div className="px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-medium text-gray-900">{title}</h3>
</div>
)}
{/* 内容 */}
<div className="px-6 py-4">{children}</div>
{/* 底部按钮 */}
{showFooter && (
<div className="px-6 py-4 border-t border-gray-200 flex justify-end space-x-3">
<button
className="px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
onClick={onClose}
>
{cancelText}
</button>
<button
className="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
onClick={handleConfirm}
>
{confirmText}
</button>
</div>
)}
</div>
</div>
)
);
};
Modal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
title: PropTypes.node,
children: PropTypes.node.isRequired,
confirmText: PropTypes.string,
cancelText: PropTypes.string,
onConfirm: PropTypes.func,
showFooter: PropTypes.bool,
className: PropTypes.string,
backdropClassName: PropTypes.string,
animationDuration: PropTypes.number
};
export default Modal;
3. 使用自定义Hook封装复杂逻辑
// useFetch.js - 封装数据获取逻辑
import { useState, useEffect, useCallback } from 'react';
export const useFetch = (url, initialOptions = {}) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [options, setOptions] = useState(initialOptions);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}, [url, options]);
useEffect(() => {
fetchData();
}, [fetchData]);
const refetch = (newOptions = {}) => {
setOptions(prev => ({ ...prev, ...newOptions }));
};
return { data, loading, error, refetch };
};
// 使用示例
const MyComponent = () => {
const { data, loading, error, refetch } = useFetch('https://api.example.com/data');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
<button onClick={() => refetch()}>Refresh</button>
</div>
);
};
八、浏览器安全与防护措施
1. XSS攻击防护
// 输入过滤函数 - 防止XSS攻击
export function sanitizeInput(input) {
if (!input) return '';
// 转换特殊字符
return input
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// 安全地设置HTML内容
export function setSafeHTML(element, html) {
if (!element) return;
// 使用DocumentFragment和textContent处理
const fragment = document.createDocumentFragment();
const temp = document.createElement('div');
temp.textContent = html;
while (temp.firstChild) {
fragment.appendChild(temp.firstChild);
}
// 清空原内容并添加安全内容
element.textContent = '';
element.appendChild(fragment);
}
// 在React中使用示例
const SafeComponent = ({ userInput }) => {
const safeInput = sanitizeInput(userInput);
return (
<div
className="user-content"
// 避免直接使用dangerouslySetInnerHTML
ref={el => el && (el.textContent = safeInput)}
/>
);
};
2. CSRF防护
// CSRF防护实现 - 在服务端生成和验证CSRF令牌
const crypto = require('crypto');
// 生成CSRF令牌
function generateCSRFToken() {
return crypto.randomBytes(16).toString('hex');
}
// 设置CSRF令牌到Cookie
function setCSRFTokenCookie(res, token) {
res.cookie('csrf_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 3600 * 1000 // 1小时
});
}
// 验证CSRF令牌
function verifyCSRFToken(req) {
const cookieToken = req.cookies.csrf_token;
const headerToken = req.headers['x-csrf-token'];
if (!cookieToken || !headerToken) {
return false;
}
return cookieToken === headerToken;
}
// Express中间件实现
function csrfProtection(req, res, next) {
// 对于GET请求,生成并设置新的CSRF令牌
if (req.method === 'GET') {
const token = generateCSRFToken();
setCSRFTokenCookie(res, token);
res.locals.csrfToken = token; // 可以在视图中使用
next();
}
// 对于其他请求,验证CSRF令牌
else {
if (!verifyCSRFToken(req)) {
return res.status(403).json({ error: 'CSRF验证失败' });
}
next();
}
}
module.exports = {
csrfProtection
};
九、性能监控与优化实践
1. 使用Performance API监控性能
// 性能监控工具
class PerformanceMonitor {
constructor() {
this.isSupported = 'performance' in window;
this.markers = new Set();
}
// 开始性能标记
start(name) {
if (!this.isSupported) return;
if (this.markers.has(name)) {
console.warn(`Performance marker "${name}" already exists`);
return;
}
performance.mark(`start_${name}`);
this.markers.add(name);
}
// 结束性能标记并计算时间
end(name) {
if (!this.isSupported) return null;
if (!this.markers.has(name)) {
console.warn(`Performance marker "${name}" does not exist`);
return null;
}
performance.mark(`end_${name}`);
performance.measure(name, `start_${name}`, `end_${name}`);
const entry = performance.getEntriesByName(name)[0];
const duration = entry.duration;
// 清理
performance.clearMarks(`start_${name}`);
performance.clearMarks(`end_${name}`);
performance.clearMeasures(name);
this.markers.delete(name);
return duration;
}
// 测量特定函数执行时间
measureFunction(fn, name = 'function') {
if (!this.isSupported) {
return fn();
}
this.start(name);
const result = fn();
const duration = this.end(name);
console.log(`Function "${name}" executed in ${duration.toFixed(2)}ms`);
return result;
}
// 监控页面加载时间
monitorPageLoad() {
if (!this.isSupported) return;
window.addEventListener('load', () => {
setTimeout(() => {
const timing = performance.timing;
const loadTime = timing.loadEventEnd - timing.navigationStart;
console.log(`Page loaded in ${loadTime}ms`);
// 发送性能数据到分析服务器
this.sendPerformanceData({
type: 'page_load',
loadTime,
dnsTime: timing.domainLookupEnd - timing.domainLookupStart,
tcpTime: timing.connectEnd - timing.connectStart,
requestTime: timing.responseEnd - timing.requestStart,
domRenderTime: timing.domComplete - timing.domInteractive
});
}, 0);
});
}
// 发送性能数据到服务器
sendPerformanceData(data) {
// 实现将性能数据发送到服务器的逻辑
console.log('Sending performance data:', data);
// 示例:使用Beacon API发送数据
if ('navigator' in window && 'sendBeacon' in navigator) {
navigator.sendBeacon('/api/performance', JSON.stringify(data));
} else {
// 回退方案
fetch('/api/performance', {
method: 'POST',
body: JSON.stringify(data),
keepalive: true
});
}
}
}
// 使用示例
const monitor = new PerformanceMonitor();
monitor.monitorPageLoad();
// 测量某个操作的性能
monitor.start('heavyCalculation');
// 执行一些耗时操作
const result = performHeavyCalculation();
monitor.end('heavyCalculation');
2. 懒加载组件使用示例
<!-- 懒加载图片示例 -->
<img
data-src="https://example.com/large-image.jpg"
alt="懒加载图片"
class="lazy-image"
loading="lazy"
/>
<!-- 懒加载脚本示例 -->
<script
src="https://example.com/heavy-script.js"
async
defer
class="lazy-script"
></script>
<!-- 懒加载iframe示例 -->
<iframe
data-src="https://example.com/embed-content"
class="lazy-iframe"
loading="lazy"
></iframe>
<script>
// 简单的懒加载实现
document.addEventListener('DOMContentLoaded', () => {
// 懒加载图片
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.add('loaded');
observer.unobserve(img);
}
});
});
observer.observe(img);
});
// 懒加载iframe
const lazyIframes = document.querySelectorAll('iframe[data-src]');
lazyIframes.forEach(iframe => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const iframe = entry.target;
iframe.src = iframe.dataset.src;
observer.unobserve(iframe);
}
});
});
observer.observe(iframe);
});
});
</script>
十、应用实例与最佳实践
1. 完整的前端性能优化方案
// performance-optimization.js - 前端性能优化工具箱
export class PerformanceOptimizer {
constructor(options = {}) {
this.options = {
lazyLoad: true,
debounce: true,
throttle: true,
resourcePreload: true,
cache: true,
...options
};
this.init();
}
init() {
if (this.options.lazyLoad) {
this.initLazyLoad();
}
if (this.options.resourcePreload) {
this.initResourcePreload();
}
if (this.options.cache) {
this.initCache();
}
}
// 初始化懒加载
initLazyLoad() {
// 图片懒加载
const lazyImages = document.querySelectorAll('img[data-src]');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.add('lazy-loaded');
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => imageObserver.observe(img));
} else {
// 回退方案:立即加载所有图片
lazyImages.forEach(img => {
img.src = img.dataset.src;
img.classList.add('lazy-loaded');
});
}
// 脚本懒加载
const lazyScripts = document.querySelectorAll('script[data-src]');
lazyScripts.forEach(script => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const s = document.createElement('script');
s.src = script.dataset.src;
s.async = true;
document.body.appendChild(s);
observer.unobserve(script);
}
});
}, {
rootMargin: '500px 0px' // 提前500px加载
});
observer.observe(script);
});
}
// 初始化资源预加载
initResourcePreload() {
const preloadLinks = document.querySelectorAll('link[rel="preload"]');
// 监控预加载资源
preloadLinks.forEach(link => {
link.addEventListener('load', () => {
console.log(`Preloaded resource: ${link.href}`);
});
link.addEventListener('error', () => {
console.error(`Failed to preload resource: ${link.href}`);
});
});
}
// 初始化缓存策略
initCache() {
// 检查是否支持Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}
// 初始化本地存储缓存
this.cache = new CacheManager();
}
// 创建防抖函数
debounce(func, wait, immediate) {
if (!this.options.debounce) return func;
let timeout;
return function() {
const context = this;
const args = arguments;
const later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
// 创建节流函数
throttle(func, limit) {
if (!this.options.throttle) return func;
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// 预加载关键资源
preloadResource(url, as) {
const link = document.createElement('link');
link.rel = 'preload';
link.href = url;
link.as = as;
document.head.appendChild(link);
}
// 监控性能
monitorPerformance() {
// 使用Performance API监控性能
if ('performance' in window) {
window.addEventListener('load', () => {
setTimeout(() => {
const perfData = performance.timing;
const loadTime = perfData.loadEventEnd - perfData.navigationStart;
console.log(`页面加载完成: ${loadTime}ms`);
// 可以发送性能数据到服务器
this.sendPerformanceMetrics({
loadTime,
dnsLookup: perfData.domainLookupEnd - perfData.domainLookupStart,
tcpConnection: perfData.connectEnd - perfData.connectStart,
requestResponse: perfData.responseEnd - perfData.requestStart,
domProcessing: perfData.domComplete - perfData.domInteractive
});
}, 0);
});
}
}
// 发送性能指标到服务器
sendPerformanceMetrics(metrics) {
// 实现发送性能指标的逻辑
console.log('发送性能指标:', metrics);
// 使用fetch API发送数据
fetch('/api/performance-metrics', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(metrics)
});
}
}
// 缓存管理器
class CacheManager {
constructor(prefix = 'app-cache-') {
this.prefix = prefix;
this.supported = typeof localStorage !== 'undefined';
}
// 获取缓存
get(key) {
if (!this.supported) return null;
const item = localStorage.getItem(`${this.prefix}${key}`);
if (!item) return null;
try {
const { value, expires } = JSON.parse(item);
if (expires && Date.now() > expires) {
this.remove(key);
return null;
}
return value;
} catch (e) {
console.error('Failed to parse cache item:', e);
this.remove(key);
return null;
}
}
// 设置缓存
set(key, value, ttl = 3600) { // 默认1小时
if (!this.supported) return;
const expires = Date.now() + (ttl * 1000);
try {
localStorage.setItem(
`${this.prefix}${key}`,
JSON.stringify({ value, expires })
);
} catch (e) {
console.error('Failed to set cache item:', e);
}
}
// 移除缓存
remove(key) {
if (!this.supported) return;
localStorage.removeItem(`${this.prefix}${key}`);
}
// 清空所有缓存
clear() {
if (!this.supported) return;
for (let i = localStorage.length - 1; i >= 0; i--) {
const key = localStorage.key(i);
if (key.startsWith(this.prefix)) {
localStorage.removeItem(key);
}
}
}
}
2. 组件化实现方案示例
以下是一个基于Vue的组件化实现方案示例,展示了如何组织和构建前端应用:
// 项目结构示例
my-project/
├── src/
│ ├── components/ // 通用组件
│ │ ├── Button/
│ │ │ ├── Button.vue
│ │ │ └── Button.test.js
│ │ ├── Card/
│ │ │ ├── Card.vue
│ │ │ └── Card.test.js
│ │ └── Modal/
│ │ ├── Modal.vue
│ │ ├── Modal.test.js
│ │ └── useModal.js
│ ├── composables/ // 组合式函数
│ │ ├── useFetch.js
│ │ ├── useLocalStorage.js
│ │ └── useDebounce.js
│ ├── layouts/ // 布局组件
│ │ ├── DefaultLayout.vue
│ │ └── BlankLayout.vue
│ ├── pages/ // 页面组件
│ │ ├── Home.vue
│ │ ├── About.vue
│ │ └── Contact.vue
│ ├── plugins/ // 插件
│ │ ├── axios.js
│ │ └── vue-router.js
│ ├── stores/ // 状态管理
│ │ ├── user.js
│ │ └── products.js
│ ├── utils/ // 工具函数
│ │ ├── formatters.js
│ │ └── validators.js
│ ├── App.vue
│ └── main.js
└── package.json
3. 浏览器安全防护集成
// security.js - 浏览器安全防护工具箱
export class SecurityGuard {
constructor(options = {}) {
this.options = {
xssProtection: true,
csrfProtection: true,
clickjackingProtection: true,
contentSecurityPolicy: true,
...options
};
this.init();
}
init() {
if (this.options.xssProtection) {
this.initXSSProtection();
}
if (this.options.csrfProtection) {
this.initCSRFProtection();
}
if (this.options.clickjackingProtection) {
this.initClickjackingProtection();
}
if (this.options.contentSecurityPolicy) {
this.initContentSecurityPolicy();
}
}
// XSS防护
initXSSProtection() {
// 过滤用户输入
window.sanitizeInput = (input) => {
if (!input) return '';
// 转换特殊字符
return input
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
// 安全设置HTML
window.setSafeHTML = (element, html) => {
if (!element) return;
const temp = document.createElement('div');
temp.textContent = html;
element.innerHTML = temp.innerHTML;
};
}
// CSRF防护
initCSRFProtection() {
// 生成CSRF令牌
const generateCSRFToken = () => {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let token = '';
for (let i = 0; i < 32; i++) {
token += characters.charAt(Math.floor(random() * characters.length));
}
return token;
};
// 设置CSRF令牌到Cookie
const setCSRFToken = (token) => {
document.cookie = `csrf_token=${token}; path=/; secure; samesite=strict`;
};
// 从Cookie获取CSRF令牌
const getCSRFToken = () => {
const name = 'csrf_token=';
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);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return null;
};
// 为AJAX请求添加CSRF令牌
if (window.XMLHttpRequest) {
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
originalOpen.apply(this, arguments);
const csrfToken = getCSRFToken();
if (csrfToken && this.method !== 'GET') {
this.setRequestHeader('X-CSRF-Token', csrfToken);
}
};
}
// 为Fetch API添加CSRF令牌
if (window.fetch) {
const originalFetch = window.fetch;
window.fetch = function(input, init = {}) {
const csrfToken = getCSRFToken();
if (csrfToken && init.method && init.method !== 'GET') {
init.headers = {
...init.headers,
'X-CSRF-Token': csrfToken
};
}
return originalFetch(input, init);
};
}
// 初始化CSRF令牌
if (!getCSRFToken()) {
setCSRFToken(generateCSRFToken());
}
}
// 点击劫持防护
initClickjackingProtection() {
// 设置X-Frame-Options头
const setXFrameOptions = () => {
// 注意:这实际上需要在服务器端设置,这里只是示例
document.addEventListener('DOMContentLoaded', () => {
const meta = document.createElement('meta');
meta.httpEquiv = 'X-Frame-Options';
meta.content = 'SAMEORIGIN';
document.head.appendChild(meta);
});
};
// 自我防御脚本
const selfDefenseScript = () => {
if (window.top !== window.self) {
window.top.location = window.self.location;
}
};
// 执行防御措施
setXFrameOptions();
selfDefenseScript();
}
// 内容安全策略
initContentSecurityPolicy() {
// 注意:这实际上需要在服务器端设置,这里只是示例
document.addEventListener('DOMContentLoaded', () => {
const meta = document.createElement('meta');
meta.httpEquiv = 'Content-Security-Policy';
meta.content = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'";
document.head.appendChild(meta);
});
}
// 防止敏感数据泄露
preventDataLeakage() {
// 防止密码在URL中泄露
if (window.history && window.history.replaceState) {
const originalPushState = window.history.pushState;
const originalReplaceState = window.history.replaceState;
window.history.pushState = function() {
const url = arguments[2];
if (url && url.includes('password=')) {
console.error('敏感数据不应该出现在URL中');
return;
}
originalPushState.apply(this, arguments);
};
window.history.replaceState = function() {
const url = arguments[2];
if (url && url.includes('password=')) {
console.error('敏感数据不应该出现在URL中');
return;
}
originalReplaceState.apply(this, arguments);
};
}
}
// 验证URL安全
validateURL(url) {
try {
const parsedUrl = new URL(url);
return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
} catch (e) {
return false;
}
}
}
以上组件封装和使用方法涵盖了前端开发中的多个关键领域,包括性能优化、安全防护、状态管理等。通过合理使用这些技术和方法,可以构建出高性能、安全可靠的前端应用。在实际项目中,应根据具体需求选择合适的技术方案,并进行适当的调整和优化。
浏览器面试题,浏览器面试答案,浏览器面试深度解析,浏览器典型例题,浏览器原理,前端面试,面试题解析,JavaScript,HTML,CSS, 浏览器渲染机制,浏览器缓存,跨域问题,HTTP 协议,Web 安全
资源地址: pan.quark.cn/s/50438c9ee…