HTML+CSS+JavaScript(JS)零基础到精通一套搞定!

92 阅读7分钟

程序员必修的Web前端教程:从入门到实战

一、HTML5 语义化与现代Web结构

1.1 语义化HTML5文档结构

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="程序员必修的前端开发教程">
    <title>前端开发实战教程</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <!-- 页面头部 -->
    <header class="main-header">
        <nav aria-label="主导航">
            <div class="logo">
                <h1>前端学堂</h1>
            </div>
            <ul class="nav-links">
                <li><a href="#home" aria-current="page">首页</a></li>
                <li><a href="#tutorials">教程</a></li>
                <li><a href="#projects">项目</a></li>
                <li><a href="#about">关于</a></li>
            </ul>
        </nav>
    </header>

    <!-- 主要内容 -->
    <main>
        <!-- 英雄区域 -->
        <section id="home" class="hero">
            <article>
                <h2>掌握现代前端开发</h2>
                <p>从HTML5、CSS3到JavaScript框架,系统学习前端开发技能</p>
                <button class="cta-button">开始学习</button>
            </article>
        </section>

        <!-- 特性介绍 -->
        <section id="features" class="features">
            <h2>核心特性</h2>
            <div class="features-grid">
                <article class="feature-card">
                    <h3>响应式设计</h3>
                    <p>学习创建适配所有设备的网页</p>
                </article>
                <article class="feature-card">
                    <h3>组件化开发</h3>
                    <p>掌握现代前端组件化开发模式</p>
                </article>
                <article class="feature-card">
                    <h3>性能优化</h3>
                    <p>了解前端性能优化的核心技巧</p>
                </article>
            </div>
        </section>

        <!-- 教程章节 -->
        <section id="tutorials" class="tutorials">
            <h2>教程目录</h2>
            <div class="accordion">
                <details class="chapter">
                    <summary>第一章:HTML5与语义化</summary>
                    <ul>
                        <li>语义化标签的使用</li>
                        <li>表单验证与增强</li>
                        <li>多媒体元素</li>
                    </ul>
                </details>
                <details class="chapter">
                    <summary>第二章:CSS3与现代布局</summary>
                    <ul>
                        <li>Flexbox布局</li>
                        <li>Grid布局</li>
                        <li>动画与过渡</li>
                    </ul>
                </details>
            </div>
        </section>
    </main>

    <!-- 页脚 -->
    <footer>
        <p>&copy; 2024 前端学堂. 所有权利保留.</p>
    </footer>

    <script src="script.js"></script>
</body>
</html>

1.2 现代化CSS3样式

/* 基础重置与变量定义 */
:root {
    --primary-color: #2563eb;
    --secondary-color: #64748b;
    --accent-color: #f59e0b;
    --text-color: #334155;
    --bg-color: #ffffff;
    --border-radius: 8px;
    --shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
    --transition: all 0.3s ease;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    line-height: 1.6;
    color: var(--text-color);
    background-color: var(--bg-color);
}

/* 布局样式 */
.main-header {
    background: var(--bg-color);
    box-shadow: var(--shadow);
    position: sticky;
    top: 0;
    z-index: 1000;
}

nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1rem 2rem;
    max-width: 1200px;
    margin: 0 auto;
}

.nav-links {
    display: flex;
    list-style: none;
    gap: 2rem;
}

.nav-links a {
    text-decoration: none;
    color: var(--text-color);
    font-weight: 500;
    transition: var(--transition);
    padding: 0.5rem 1rem;
    border-radius: var(--border-radius);
}

.nav-links a:hover,
.nav-links a[aria-current="page"] {
    background-color: var(--primary-color);
    color: white;
}

/* 英雄区域 */
.hero {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    padding: 6rem 2rem;
    text-align: center;
}

.hero h2 {
    font-size: 3rem;
    margin-bottom: 1rem;
    animation: fadeInUp 1s ease;
}

.hero p {
    font-size: 1.25rem;
    margin-bottom: 2rem;
    opacity: 0.9;
    animation: fadeInUp 1s ease 0.2s both;
}

.cta-button {
    background-color: var(--accent-color);
    color: white;
    border: none;
    padding: 1rem 2rem;
    font-size: 1.1rem;
    border-radius: var(--border-radius);
    cursor: pointer;
    transition: var(--transition);
    animation: fadeInUp 1s ease 0.4s both;
}

.cta-button:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(245, 158, 11, 0.3);
}

/* 特性网格 */
.features {
    padding: 4rem 2rem;
    max-width: 1200px;
    margin: 0 auto;
}

.features h2 {
    text-align: center;
    font-size: 2.5rem;
    margin-bottom: 3rem;
}

.features-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 2rem;
}

.feature-card {
    background: white;
    padding: 2rem;
    border-radius: var(--border-radius);
    box-shadow: var(--shadow);
    transition: var(--transition);
    text-align: center;
}

.feature-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}

.feature-card h3 {
    color: var(--primary-color);
    margin-bottom: 1rem;
    font-size: 1.5rem;
}

/* 手风琴样式 */
.accordion {
    max-width: 800px;
    margin: 2rem auto;
}

.chapter {
    border: 1px solid #e2e8f0;
    border-radius: var(--border-radius);
    margin-bottom: 1rem;
    overflow: hidden;
}

.chapter summary {
    padding: 1.5rem;
    background-color: #f8fafc;
    cursor: pointer;
    font-weight: 600;
    list-style: none;
    position: relative;
}

.chapter summary::after {
    content: '+';
    position: absolute;
    right: 1.5rem;
    font-size: 1.5rem;
    transition: var(--transition);
}

.chapter[open] summary::after {
    content: '-';
}

.chapter ul {
    padding: 1.5rem;
    background-color: white;
}

.chapter li {
    margin-bottom: 0.5rem;
    padding-left: 1rem;
    position: relative;
}

.chapter li::before {
    content: '•';
    color: var(--primary-color);
    position: absolute;
    left: 0;
}

/* 动画 */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* 响应式设计 */
@media (max-width: 768px) {
    .nav-links {
        flex-direction: column;
        gap: 1rem;
    }
    
    .hero h2 {
        font-size: 2rem;
    }
    
    .features-grid {
        grid-template-columns: 1fr;
    }
}

二、JavaScript 现代编程实践

2.1 ES6+ 核心特性与模块化

// utils.js - 工具函数模块
export class Validator {
    static isEmail(email) {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(email);
    }

    static isPhone(phone) {
        const phoneRegex = /^1[3-9]\d{9}$/;
        return phoneRegex.test(phone);
    }

    static isEmpty(value) {
        return value === null || value === undefined || value.toString().trim() === '';
    }
}

export const Storage = {
    set(key, value) {
        try {
            localStorage.setItem(key, JSON.stringify(value));
            return true;
        } catch (error) {
            console.error('Storage set error:', error);
            return false;
        }
    },

    get(key) {
        try {
            const item = localStorage.getItem(key);
            return item ? JSON.parse(item) : null;
        } catch (error) {
            console.error('Storage get error:', error);
            return null;
        }
    },

    remove(key) {
        localStorage.removeItem(key);
    }
};

// api.js - API请求模块
export class ApiClient {
    constructor(baseURL) {
        this.baseURL = baseURL;
    }

    async request(endpoint, options = {}) {
        const url = `${this.baseURL}${endpoint}`;
        const config = {
            headers: {
                'Content-Type': 'application/json',
                ...options.headers
            },
            ...options
        };

        try {
            const response = await fetch(url, config);
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const data = await response.json();
            return { success: true, data };
        } catch (error) {
            console.error('API request failed:', error);
            return { 
                success: false, 
                error: error.message 
            };
        }
    }

    async get(endpoint) {
        return this.request(endpoint);
    }

    async post(endpoint, data) {
        return this.request(endpoint, {
            method: 'POST',
            body: JSON.stringify(data)
        });
    }
}

// userService.js - 用户服务
export class UserService {
    constructor() {
        this.api = new ApiClient('https://api.example.com');
        this.currentUser = Storage.get('currentUser');
    }

    async login(email, password) {
        if (!Validator.isEmail(email)) {
            return { success: false, error: '邮箱格式不正确' };
        }

        if (Validator.isEmpty(password)) {
            return { success: false, error: '密码不能为空' };
        }

        const result = await this.api.post('/login', { email, password });
        
        if (result.success) {
            this.currentUser = result.data;
            Storage.set('currentUser', this.currentUser);
        }

        return result;
    }

    async register(userData) {
        const { email, password, name } = userData;

        if (!Validator.isEmail(email)) {
            return { success: false, error: '邮箱格式不正确' };
        }

        if (password.length < 6) {
            return { success: false, error: '密码至少6位' };
        }

        if (Validator.isEmpty(name)) {
            return { success: false, error: '姓名不能为空' };
        }

        return await this.api.post('/register', userData);
    }

    logout() {
        this.currentUser = null;
        Storage.remove('currentUser');
    }

    isAuthenticated() {
        return !!this.currentUser;
    }
}

2.2 组件化开发与事件管理

// component.js - 基础组件类
export class Component {
    constructor(element) {
        this.element = element;
        this.handlers = new Map();
        this.init();
    }

    init() {
        // 初始化逻辑
    }

    on(event, selector, handler) {
        if (!this.handlers.has(event)) {
            this.handlers.set(event, []);
        }

        const delegateHandler = (e) => {
            if (e.target.matches(selector)) {
                handler.call(this, e);
            }
        };

        this.element.addEventListener(event, delegateHandler);
        this.handlers.get(event).push(delegateHandler);
    }

    emit(event, detail) {
        const customEvent = new CustomEvent(event, { detail });
        this.element.dispatchEvent(customEvent);
    }

    destroy() {
        for (const [event, handlers] of this.handlers) {
            handlers.forEach(handler => {
                this.element.removeEventListener(event, handler);
            });
        }
        this.handlers.clear();
    }
}

// formComponent.js - 表单组件
export class FormComponent extends Component {
    init() {
        this.fields = this.element.querySelectorAll('[data-validate]');
        this.submitButton = this.element.querySelector('[type="submit"]');
        
        this.setupValidation();
        this.setupSubmit();
    }

    setupValidation() {
        this.fields.forEach(field => {
            field.addEventListener('blur', () => this.validateField(field));
            field.addEventListener('input', () => this.clearError(field));
        });
    }

    setupSubmit() {
        this.element.addEventListener('submit', async (e) => {
            e.preventDefault();
            
            if (await this.validateForm()) {
                this.submitForm();
            }
        });
    }

    validateField(field) {
        const value = field.value.trim();
        const rules = field.dataset.validate.split('|');
        
        for (const rule of rules) {
            const error = this.checkRule(rule, value, field);
            if (error) {
                this.showError(field, error);
                return false;
            }
        }
        
        this.clearError(field);
        return true;
    }

    checkRule(rule, value, field) {
        switch (rule) {
            case 'required':
                if (Validator.isEmpty(value)) return '此字段为必填项';
                break;
            case 'email':
                if (!Validator.isEmail(value)) return '邮箱格式不正确';
                break;
            case 'phone':
                if (!Validator.isPhone(value)) return '手机号格式不正确';
                break;
            case 'min-length':
                const minLength = field.dataset.minLength;
                if (value.length < minLength) return `至少需要${minLength}个字符`;
                break;
        }
        return null;
    }

    showError(field, message) {
        this.clearError(field);
        field.classList.add('error');
        
        const errorElement = document.createElement('div');
        errorElement.className = 'error-message';
        errorElement.textContent = message;
        field.parentNode.appendChild(errorElement);
    }

    clearError(field) {
        field.classList.remove('error');
        const existingError = field.parentNode.querySelector('.error-message');
        if (existingError) {
            existingError.remove();
        }
    }

    async validateForm() {
        let isValid = true;
        
        for (const field of this.fields) {
            if (!this.validateField(field)) {
                isValid = false;
            }
        }

        return isValid;
    }

    async submitForm() {
        this.submitButton.disabled = true;
        this.submitButton.textContent = '提交中...';

        const formData = new FormData(this.element);
        const data = Object.fromEntries(formData.entries());

        try {
            this.emit('submit:start', { data });
            
            // 模拟API调用
            await new Promise(resolve => setTimeout(resolve, 2000));
            
            this.emit('submit:success', { data });
            this.element.reset();
            
        } catch (error) {
            this.emit('submit:error', { error: error.message });
        } finally {
            this.submitButton.disabled = false;
            this.submitButton.textContent = '提交';
        }
    }
}

三、响应式布局与CSS Grid实战

3.1 现代CSS Grid布局系统

/* grid-system.css - 现代网格系统 */
.grid-container {
    display: grid;
    gap: var(--gap, 1rem);
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

/* 自动填充网格 */
.auto-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1.5rem;
}

/* 12列网格系统 */
.grid-12 {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 1.5rem;
}

.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-5 { grid-column: span 5; }
.col-6 { grid-column: span 6; }
.col-7 { grid-column: span 7; }
.col-8 { grid-column: span 8; }
.col-9 { grid-column: span 9; }
.col-10 { grid-column: span 10; }
.col-11 { grid-column: span 11; }
.col-12 { grid-column: span 12; }

/* 响应式断点 */
@media (max-width: 1024px) {
    .col-lg-1 { grid-column: span 1; }
    .col-lg-2 { grid-column: span 2; }
    .col-lg-3 { grid-column: span 3; }
    .col-lg-4 { grid-column: span 4; }
    .col-lg-6 { grid-column: span 6; }
    .col-lg-12 { grid-column: span 12; }
}

@media (max-width: 768px) {
    .grid-12 {
        grid-template-columns: 1fr;
        gap: 1rem;
    }
    
    .col-md-12 { grid-column: span 12; }
    
    .auto-grid {
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
}

/* 复杂布局示例 */
.dashboard-layout {
    display: grid;
    grid-template-areas: 
        "header header header"
        "sidebar main aside"
        "footer footer footer";
    grid-template-columns: 250px 1fr 300px;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
    gap: 0;
}

.dashboard-header {
    grid-area: header;
    background: white;
    box-shadow: var(--shadow);
    z-index: 100;
}

.dashboard-sidebar {
    grid-area: sidebar;
    background: #f8fafc;
    border-right: 1px solid #e2e8f0;
}

.dashboard-main {
    grid-area: main;
    padding: 2rem;
    background: white;
}

.dashboard-aside {
    grid-area: aside;
    background: #f8fafc;
    border-left: 1px solid #e2e8f0;
}

.dashboard-footer {
    grid-area: footer;
    background: var(--text-color);
    color: white;
    padding: 2rem;
}

/* 卡片网格布局 */
.cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 2rem;
    padding: 2rem 0;
}

.card {
    background: white;
    border-radius: var(--border-radius);
    box-shadow: var(--shadow);
    overflow: hidden;
    transition: var(--transition);
}

.card:hover {
    transform: translateY(-5px);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}

.card-header {
    padding: 1.5rem;
    background: var(--primary-color);
    color: white;
}

.card-body {
    padding: 1.5rem;
}

.card-footer {
    padding: 1rem 1.5rem;
    background: #f8fafc;
    border-top: 1px solid #e2e8f0;
}

/* 表单布局 */
.form-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
}

.form-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.form-group.full-width {
    grid-column: 1 / -1;
}

.form-label {
    font-weight: 600;
    color: var(--text-color);
    margin-bottom: 0.25rem;
}

.form-input {
    padding: 0.75rem;
    border: 2px solid #e2e8f0;
    border-radius: var(--border-radius);
    font-size: 1rem;
    transition: var(--transition);
}

.form-input:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

.form-input.error {
    border-color: #ef4444;
}

.error-message {
    color: #ef4444;
    font-size: 0.875rem;
    margin-top: 0.25rem;
}

/* 响应式表单 */
@media (max-width: 768px) {
    .form-grid {
        grid-template-columns: 1fr;
    }
    
    .dashboard-layout {
        grid-template-areas: 
            "header"
            "main"
            "aside"
            "footer";
        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr auto auto;
    }
    
    .dashboard-sidebar {
        display: none;
    }
}

四、前端工程化与构建工具

4.1 现代前端工作流配置

// webpack.config.js - 现代Webpack配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';
  
  return {
    entry: {
      main: './src/index.js',
      vendor: './src/vendor.js'
    },
    
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: isProduction 
        ? 'js/[name].[contenthash].bundle.js'
        : 'js/[name].bundle.js',
      clean: true,
      publicPath: '/'
    },
    
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                ['@babel/preset-env', { 
                  targets: '> 0.25%, not dead',
                  useBuiltIns: 'usage',
                  corejs: 3
                }]
              ]
            }
          }
        },
        {
          test: /\.css$/,
          use: [
            isProduction 
              ? MiniCssExtractPlugin.loader
              : 'style-loader',
            'css-loader',
            'postcss-loader'
          ]
        },
        {
          test: /\.(png|jpg|jpeg|gif|svg)$/,
          type: 'asset/resource',
          generator: {
            filename: 'images/[name].[contenthash][ext]'
          }
        }
      ]
    },
    
    plugins: [
      new HtmlWebpackPlugin({
        template: './src/index.html',
        minify: isProduction
      }),
      
      ...(isProduction ? [
        new MiniCssExtractPlugin({
          filename: 'css/[name].[contenthash].css'
        })
      ] : [])
    ],
    
    devServer: {
      static: './dist',
      hot: true,
      open: true,
      port: 3000,
      historyApiFallback: true
    },
    
    optimization: {
      splitChunks: {
        chunks: 'all',
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all'
          }
        }
      }
    },
    
    devtool: isProduction ? 'source-map' : 'eval-source-map'
  };
};

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano')({
      preset: 'default'
    })
  ]
};

4.2 现代化JavaScript应用

// app.js - 主应用文件
import { UserService } from './services/userService.js';
import { FormComponent } from './components/formComponent.js';
import { Validator, Storage } from './utils/utils.js';

class FrontendApp {
    constructor() {
        this.userService = new UserService();
        this.components = new Map();
        this.init();
    }

    init() {
        this.initializeComponents();
        this.setupEventListeners();
        this.checkAuthentication();
        this.setupServiceWorker();
    }

    initializeComponents() {
        // 初始化所有表单组件
        document.querySelectorAll('[data-component="form"]').forEach(form => {
            const formComponent = new FormComponent(form);
            this.components.set(form, formComponent);
            
            formComponent.on('submit:success', this.handleFormSuccess.bind(this));
            formComponent.on('submit:error', this.handleFormError.bind(this));
        });

        // 初始化其他组件...
    }

    setupEventListeners() {
        // 全局事件监听
        document.addEventListener('click', this.handleGlobalClick.bind(this));
        document.addEventListener('keydown', this.handleGlobalKeydown.bind(this));
        
        // 路由监听(简单SPA路由)
        window.addEventListener('popstate', this.handleRouteChange.bind(this));
    }

    handleFormSuccess(event) {
        const { data } = event.detail;
        this.showNotification('操作成功!', 'success');
        console.log('Form submitted successfully:', data);
    }

    handleFormError(event) {
        const { error } = event.detail;
        this.showNotification(`操作失败: ${error}`, 'error');
    }

    handleGlobalClick(event) {
        // 处理链接点击(简单路由)
        const link = event.target.closest('a[data-navigation]');
        if (link) {
            event.preventDefault();
            this.navigateTo(link.href);
        }
    }

    handleGlobalKeydown(event) {
        // 全局快捷键
        if (event.ctrlKey && event.key === 'k') {
            event.preventDefault();
            this.openSearch();
        }
    }

    navigateTo(url) {
        window.history.pushState(null, '', url);
        this.handleRouteChange();
    }

    handleRouteChange() {
        const path = window.location.pathname;
        this.loadRoute(path);
    }

    async loadRoute(path) {
        try {
            // 简单的路由加载逻辑
            const main = document.querySelector('main');
            main.innerHTML = '<div class="loading">加载中...</div>';

            // 模拟路由加载
            await new Promise(resolve => setTimeout(resolve, 500));
            
            const content = await this.fetchRouteContent(path);
            main.innerHTML = content;
            
            // 重新初始化该路由的组件
            this.initializeComponents();
            
        } catch (error) {
            console.error('Route load error:', error);
            this.showNotification('页面加载失败', 'error');
        }
    }

    async fetchRouteContent(path) {
        // 实际项目中这里应该是API调用或动态导入
        const routes = {
            '/': '<h1>首页内容</h1>',
            '/about': '<h1>关于我们</h1>'
        };
        
        return routes[path] || '<h1>页面未找到</h1>';
    }

    checkAuthentication() {
        if (this.userService.isAuthenticated()) {
            this.showUserInfo();
        } else {
            this.showLoginPrompt();
        }
    }

    showUserInfo() {
        const user = this.userService.currentUser;
        // 更新UI显示用户信息
    }

    showLoginPrompt() {
        // 显示登录提示
    }

    showNotification(message, type = 'info') {
        const notification = document.createElement('div');
        notification.className = `notification notification-${type}`;
        notification.innerHTML = `
            <div class="notification-content">
                <span class="notification-message">${message}</span>
                <button class="notification-close">&times;</button>
            </div>
        `;

        document.body.appendChild(notification);

        // 自动消失
        setTimeout(() => {
            notification.remove();
        }, 5000);

        // 点击关闭
        notification.querySelector('.notification-close').onclick = () => {
            notification.remove();
        };
    }

    async setupServiceWorker() {
        if ('serviceWorker' in navigator) {
            try {
                const registration = await navigator.serviceWorker.register('/sw.js');
                console.log('ServiceWorker 注册成功:', registration);
            } catch (error) {
                console.log('ServiceWorker 注册失败:', error);
            }
        }
    }

    destroy() {
        // 清理所有组件
        this.components.forEach(component => component.destroy());
        this.components.clear();
    }
}

// 启动应用
document.addEventListener('DOMContentLoaded', () => {
    window.app = new FrontendApp();
});

// 错误边界
window.addEventListener('error', (event) => {
    console.error('Global error:', event.error);
    // 上报错误到监控系统
});

window.addEventListener('unhandledrejection', (event) => {
    console.error('Unhandled promise rejection:', event.reason);
    event.preventDefault();
});

这个完整的前端教程涵盖了现代Web开发的核心技术栈,包括:

  • HTML5语义化和现代文档结构
  • CSS3高级特性和Grid/Flexbox布局
  • ES6+ JavaScript和模块化开发
  • 组件化架构和事件管理
  • 前端工程化和构建工具配置
  • 响应式设计和移动端适配
  • 性能优化和最佳实践

所有代码都遵循现代前端开发标准,可以直接用于实际项目或作为学习参考。