study.md 26 KB

SSXZ Web 项目学习指南

第1步:项目整体架构和技术选型原因

项目整体架构

SSXZ Web 是一个基于 Vue 3 的单页面应用(SPA),采用了现代化的前端架构设计。整体架构可以分为以下几个层次:

  1. 表现层(Presentation Layer):由 Vue 组件构成,负责用户界面的渲染和交互
  2. 业务逻辑层(Business Logic Layer):通过 Vue 的 Composition API 和自定义 Hooks 实现
  3. 数据访问层(Data Access Layer):通过 Axios 封装的 API 模块与后端进行通信
  4. 状态管理层(State Management Layer):使用 Pinia 管理全局状态
  5. 工具层(Utility Layer):提供各种通用工具函数和辅助功能

技术选型原因

前端框架:Vue 3

  • 选择原因

    • Vue 3 的 Composition API 提供了更灵活的代码组织方式,便于大型项目的维护
    • 性能优化:Vue 3 在虚拟 DOM、编译优化等方面有显著提升
    • TypeScript 支持更好:Vue 3 对 TypeScript 的支持更加完善
    • 生态成熟:拥有丰富的插件和工具链
  • 项目中的应用

    • 使用 <script setup> 语法简化组件定义
    • 通过 Composition API 组织复杂逻辑
    • 利用响应式系统管理组件状态

构建工具:Vite

  • 选择原因

    • 开发体验极佳:基于原生 ES 模块的快速冷启动
    • 热更新速度快:利用浏览器的 ES 模块支持,实现按需编译
    • 配置简单:默认配置合理,减少配置工作量
    • 插件生态丰富:支持各种插件扩展功能
  • 项目中的应用

    • 快速的开发服务器启动
    • 高效的热模块替换(HMR)
    • TypeScript 集成
    • 路径别名配置(@ 指向 src 目录)

状态管理:Pinia

  • 选择原因

    • Vue 3 官方推荐的状态管理库
    • API 简洁直观,学习成本低
    • 完整的 TypeScript 支持
    • 模块化设计,便于代码组织
    • 支持开发工具调试
  • 项目中的应用

    • 全局状态管理(如用户信息、系统配置等)
    • 跨组件状态共享
    • 状态持久化

UI 组件库:Element Plus

  • 选择原因

    • Vue 3 生态中最成熟的 UI 组件库之一
    • 组件丰富:提供 60+ 高质量组件
    • 设计规范统一:遵循现代设计原则
    • 定制能力强:支持主题定制
    • 文档完善:提供详细的 API 文档和示例
  • 项目中的应用

    • 基础组件:按钮、输入框、对话框等
    • 布局组件:栅格系统、容器等
    • 数据展示:表格、列表、卡片等
    • 反馈组件:消息提示、加载等

样式处理:Sass

  • 选择原因

    • CSS 预处理器,提供变量、嵌套、混合等高级功能
    • 提高样式代码的可维护性和复用性
    • 广泛使用,生态成熟
  • 项目中的应用

    • 全局样式变量定义
    • 组件样式嵌套组织
    • 响应式设计实现

HTTP 客户端:Axios

  • 选择原因

    • 基于 Promise 的 HTTP 客户端,支持异步请求
    • 丰富的功能:请求/响应拦截、转换、取消等
    • 浏览器兼容性好
    • 广泛使用,社区活跃
  • 项目中的应用

    • API 请求封装
    • 请求拦截器添加认证信息
    • 响应拦截器统一处理错误
    • 请求取消功能

音频处理:Howler.js、Wavesurfer.js、RecordRTC

  • 选择原因

    • Howler.js:简化音频播放,处理兼容性问题
    • Wavesurfer.js:提供音频波形可视化
    • RecordRTC:强大的媒体录制功能
  • 项目中的应用

    • 语音消息播放
    • 音频波形展示
    • 音频录制功能

Markdown 渲染:Markdown-it 及相关插件

  • 选择原因

    • 高性能的 Markdown 解析器
    • 插件系统丰富,支持扩展功能
    • 安全性好,可配置白名单
  • 项目中的应用

    • 聊天消息中的 Markdown 内容渲染
    • 代码高亮显示
    • 安全的 HTML 输出

第2步:核心目录结构详解

项目根目录结构

d:\Projects\sxc\web/
├── .env                    # 环境变量配置
├── .env.development        # 开发环境变量
├── .env.production         # 生产环境变量
├── .gitattributes          # Git 属性配置
├── .gitignore              # Git 忽略文件配置
├── .prettierrc.json        # Prettier 代码格式化配置
├── API接口文档.md           # API 接口文档
├── README.md               # 项目说明文档
├── package.json            # 项目依赖和脚本配置
├── tsconfig.json           # TypeScript 配置
├── tsconfig.app.json       # 应用 TypeScript 配置
├── tsconfig.node.json      # Node.js TypeScript 配置
├── vite.config.ts          # Vite 构建配置
├── cert/                   # 证书目录
├── public/                 # 静态资源目录
└── src/                    # 源代码目录

src 目录详解

api/ - API 接口模块

这个目录包含了所有与后端 API 交互的模块,按功能领域划分:

  • basic.ts - 基础信息接口,如网站配置、点赞/踩操作
  • category.ts - 服务分类接口,获取服务分类信息
  • commonProblem.ts - 常见问题接口,获取 FAQ 列表
  • media.ts - 媒体处理接口,语音转文字、文字转语音
  • message.ts - 消息相关接口,发送消息、获取消息历史
  • opinion.ts - 意见反馈接口,提交用户反馈
  • service.ts - 服务导航接口,获取服务项目信息

每个模块都封装了特定领域的 API 调用,使用 Axios 发送 HTTP 请求,并处理响应数据。

assets/ - 项目资源

这个目录包含了项目的静态资源:

  • base.css - 基础样式,包含 CSS 变量定义、全局重置样式等
  • fonts.css - 字体定义,引入 PingFang SC 字体
  • main.css - 主样式文件,包含全局样式和组件样式

components/ - 可复用的 Vue 组件

这个目录包含了所有可复用的 Vue 组件,按功能划分:

  • SsCommonProblem.vue - 常见问题组件,展示 FAQ 列表
  • SsFooter.vue - 页脚组件,显示版权和链接信息
  • SsGridEntrance.vue - 网格入口组件,展示服务入口网格
  • SsHeader.vue - 页头组件,显示导航和 logo
  • SsHeadline.vue - 标题组件,显示页面标题
  • SsHotline.vue - 热线组件,显示联系电话
  • SsInputBox.vue - 输入框组件,提供文本输入功能
  • SsNavigation.vue - 导航组件,提供页面导航
  • SsOpinion.vue - 意见反馈组件,收集用户反馈
  • SsPanel.vue - 面板组件,提供内容面板
  • SsRecording.vue - 录音组件,提供音频录制功能
  • SsService.vue - 服务组件,展示服务信息

特别值得注意的是 ss_chat/ 子目录,它包含了聊天相关的所有组件:

  • SsChat.vue - 主聊天组件,整合聊天功能
  • components/ - 聊天子组件目录
    • SsChatHistory.vue - 聊天历史组件,显示历史消息
    • SsChatInput.vue - 聊天输入组件,提供消息输入功能
    • SsChatMessage.vue - 聊天消息组件,显示单条消息
    • SsChatReply.vue - 聊天回复组件,显示 AI 回复
    • SsChatSendMessage.vue - 发送消息组件,处理消息发送
  • hooks/ - 聊天相关钩子
    • useEventSource.ts - EventSource 钩子,处理 SSE 连接

hooks/ - 组合式函数

这个目录包含了可复用的组合式函数(Hooks):

  • useClipboard.ts - 剪贴板操作钩子,提供复制到剪贴板功能

plugins/ - 全局插件

这个目录包含了 Vue 的全局插件:

  • globalMethods.ts - 全局方法插件,注册全局可用的工具函数

router/ - Vue Router 配置

这个目录包含了路由配置:

  • index.ts - 路由配置文件,定义页面路由

stores/ - Pinia 状态仓库

这个目录包含了 Pinia 状态管理:

  • global.ts - 全局状态,存储应用级别的状态

types/ - TypeScript 类型定义

这个目录包含了 TypeScript 类型定义文件:

  • api.d.ts - API 相关类型定义
  • global.d.ts - 全局类型定义
  • markdown-it-*.d.ts - Markdown-it 插件类型定义
  • string.extensions.d.ts - 字符串扩展类型定义

utils/ - 工具函数

这个目录包含了各种工具函数:

  • EventSourceWrapper.ts - EventSource 封装,处理 SSE 连接
  • PCMAudioPlayer.ts - PCM 音频播放器,处理音频播放
  • common.ts - 通用工具函数,提供图片 URL 构造、空值检查等功能
  • formatDate.ts - 日期格式化工具,提供日期格式化功能
  • parseMarkdown.ts - Markdown 解析工具,处理 Markdown 渲染
  • request.ts - 请求封装,封装 Axios 请求
  • string.extensions.ts - 字符串扩展,提供字符串处理方法
  • useDeviceDetection.ts - 设备检测,检测移动设备

views/ - 页面视图

这个目录包含了页面级组件:

  • HomeView.vue - 主页视图,应用的主页面

public/ - 静态资源

这个目录包含了不需要经过构建处理的静态资源:

  • favicon.ico - 网站图标
  • fonts/ - 字体文件,包含 PingFang SC 字体的各种字重
  • images/ - 图片资源,包含应用中使用的各种图片

第3步:简单功能模块分析

让我们选择 useClipboard 这个简单的功能模块进行详细分析,它位于 src/hooks/useClipboard.ts

功能概述

useClipboard 是一个自定义的组合式函数(Hook),用于提供复制文本到剪贴板的功能。这个功能在聊天应用中很常见,用户可能需要复制 AI 的回复或自己的消息。

实现分析

让我们先查看这个文件的完整内容:

import { ref } from 'vue'
import { ElMessage } from 'element-plus'

export function useClipboard() {
  const copied = ref(false)

  const copyToClipboard = async (text: string) => {
    try {
      if (navigator.clipboard && window.isSecureContext) {
        await navigator.clipboard.writeText(text)
      } else {
        // 降级方案
        const textArea = document.createElement('textarea')
        textArea.value = text
        document.body.appendChild(textArea)
        textArea.focus()
        textArea.select()
        document.execCommand('copy')
        document.body.removeChild(textArea)
      }

      copied.value = true
      ElMessage.success('复制成功')
      setTimeout(() => {
        copied.value = false
      }, 2000)
    } catch (error) {
      ElMessage.error('复制失败')
      console.error('复制失败:', error)
    }
  }

  return {
    copied,
    copyToClipboard
  }
}

代码解析

  1. 导入依赖

    import { ref } from 'vue'
    import { ElMessage } from 'element-plus'
    
    • 从 Vue 导入 ref,用于创建响应式引用
    • 从 Element Plus 导入 ElMessage,用于显示提示消息
  2. 状态定义

    const copied = ref(false)
    
    • 创建一个响应式引用 copied,表示是否已复制
    • 初始值为 false
  3. 核心功能实现

    const copyToClipboard = async (text: string) => {
     try {
       // 主要逻辑
     } catch (error) {
       // 错误处理
     }
    }
    
    • 定义一个异步函数 copyToClipboard,接收要复制的文本
    • 使用 try-catch 进行错误处理
  4. 复制逻辑

    if (navigator.clipboard && window.isSecureContext) {
     await navigator.clipboard.writeText(text)
    } else {
     // 降级方案
     const textArea = document.createElement('textarea')
     textArea.value = text
     document.body.appendChild(textArea)
     textArea.focus()
     textArea.select()
     document.execCommand('copy')
     document.body.removeChild(textArea)
    }
    
    • 首先检查浏览器是否支持现代的 Clipboard API(navigator.clipboard)且在安全上下文中(window.isSecureContext
    • 如果支持,使用 navigator.clipboard.writeText() 方法复制文本
    • 如果不支持,使用降级方案:创建一个临时的 textarea 元素,设置其值,选中并执行复制命令,然后移除元素
  5. 成功处理

    copied.value = true
    ElMessage.success('复制成功')
    setTimeout(() => {
     copied.value = false
    }, 2000)
    
    • 设置 copied 状态为 true
    • 显示成功消息
    • 2秒后将 copied 状态重置为 false
  6. 错误处理

    ElMessage.error('复制失败')
    console.error('复制失败:', error)
    
    • 显示错误消息
    • 在控制台输出错误信息
  7. 返回接口

    return {
     copied,
     copyToClipboard
    }
    
    • 返回 copied 状态和 copyToClipboard 函数,供组件使用

使用示例

这个 Hook 在组件中的使用方式如下:

<template>
  <div>
    <button @click="handleCopy">复制文本</button>
    <span v-if="copied">已复制!</span>
  </div>
</template>

<script setup>
import { useClipboard } from '@/hooks/useClipboard'

const { copied, copyToClipboard } = useClipboard()

const handleCopy = () => {
  copyToClipboard('要复制的文本内容')
}
</script>

设计亮点

  1. 兼容性处理:同时支持现代 Clipboard API 和降级方案,确保在各种浏览器环境下都能工作

  2. 状态管理:提供 copied 状态,方便 UI 根据复制状态进行变化

  3. 用户反馈:使用 Element Plus 的消息组件提供操作反馈

  4. 错误处理:捕获并处理可能的错误,提供友好的错误提示

  5. 自动重置:复制状态在 2 秒后自动重置,避免状态一直保持为 true

  6. 封装性:将复杂的剪贴板操作封装为简单的函数,组件调用非常简洁

扩展思考

这个简单的 Hook 展示了 Vue 3 Composition API 的几个重要概念:

  1. 逻辑复用:将剪贴板操作逻辑抽取为可复用的 Hook
  2. 响应式状态:使用 ref 创建响应式状态
  3. 异步处理:处理异步操作(剪贴板 API)
  4. 错误边界:提供错误处理机制
  5. 生命周期管理:自动管理状态的创建和销毁

这种模式在项目中广泛使用,使得代码更加模块化、可维护和可测试。

第4步:项目中的设计模式和最佳实践

设计模式

1. 组合模式 (Composition Pattern)

项目广泛使用了 Vue 3 的 Composition API,这是一种组合模式的体现:

// 在组件中使用组合式函数
import { useClipboard } from '@/hooks/useClipboard'
import { useDeviceDetection } from '@/utils/useDeviceDetection'

export default defineComponent({
  setup() {
    const { copied, copyToClipboard } = useClipboard()
    const { isMobile } = useDeviceDetection()
    
    return {
      copied,
      copyToClipboard,
      isMobile
    }
  }
})

优点

  • 逻辑复用性强
  • 代码组织更灵活
  • 类型推导更好

2. 工厂模式 (Factory Pattern)

在 API 模块中,使用了工厂模式创建请求实例:

// src/utils/request.ts
import axios from 'axios'

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000
})

// 添加请求拦截器
request.interceptors.request.use(config => {
  // 添加认证信息
  const timestamp = new Date().getTime()
  const sign = md5(`${timestamp}${import.meta.env.VITE_API_SECRET}`)
  
  config.headers['h-timestamp'] = timestamp
  config.headers['h-sign'] = sign
  
  return config
})

export default request

优点

  • 统一管理请求配置
  • 便于添加全局拦截器
  • 易于维护和扩展

3. 单例模式 (Singleton Pattern)

全局状态管理使用了单例模式:

// src/stores/global.ts
import { defineStore } from 'pinia'

export const useGlobalStore = defineStore('global', {
  state: () => ({
    userInfo: null,
    systemConfig: {}
  }),
  actions: {
    setUserInfo(info) {
      this.userInfo = info
    }
  }
})

优点

  • 确保全局状态唯一
  • 状态访问点统一
  • 便于状态管理和调试

4. 策略模式 (Strategy Pattern)

在 Markdown 解析中使用了策略模式:

// src/utils/parseMarkdown.ts
import MarkdownIt from 'markdown-it'
import subscript from 'markdown-it-sub'
import superscript from 'markdown-it-sup'
import footnote from 'markdown-it-footnote'
import taskLists from 'markdown-it-task-lists'

const md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true
})
  .use(subscript)
  .use(superscript)
  .use(footnote)
  .use(taskLists)

优点

  • 插件化设计,易于扩展
  • 功能模块化,职责单一
  • 可灵活组合不同功能

5. 观察者模式 (Observer Pattern)

在 EventSource 封装中使用了观察者模式:

// src/utils/EventSourceWrapper.ts
export class EventSourceWrapper {
  private eventSource: EventSource | null = null
  private listeners: { [key: string]: Function[] } = {}

  on(event: string, callback: Function) {
    if (!this.listeners[event]) {
      this.listeners[event] = []
    }
    this.listeners[event].push(callback)
  }

  emit(event: string, data: any) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(callback => callback(data))
    }
  }
}

优点

  • 松耦合的事件通信
  • 支持多个监听器
  • 易于扩展新事件类型

最佳实践

1. 组件设计原则

单一职责原则: 每个组件只负责一个功能,如 SsChatInput 只负责输入,SsChatMessage 只负责消息显示。

<!-- SsChatInput.vue - 只负责输入功能 -->
<template>
  <div class="chat-input">
    <textarea v-model="inputText" @keydown.enter="handleEnter"></textarea>
    <button @click="sendMessage">发送</button>
  </div>
</template>

<script setup>
const inputText = ref('')
const emit = defineEmits(['send'])

const sendMessage = () => {
  emit('send', inputText.value)
  inputText.value = ''
}
</script>

可复用性: 组件设计考虑复用场景,通过 props 和 slots 提供灵活性。

<!-- SsPanel.vue - 可复用的面板组件 -->
<template>
  <div class="panel">
    <div class="panel-header" v-if="$slots.header">
      <slot name="header"></slot>
    </div>
    <div class="panel-body">
      <slot></slot>
    </div>
    <div class="panel-footer" v-if="$slots.footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

2. 状态管理最佳实践

模块化状态: 按功能模块划分状态,避免单一巨大状态对象。

// 聊天状态
export const useChatStore = defineStore('chat', {
  state: () => ({
    messages: [],
    isLoading: false
  }),
  actions: {
    addMessage(message) {
      this.messages.push(message)
    }
  }
})

// 用户状态
export const useUserStore = defineStore('user', {
  state: () => ({
    profile: null,
    preferences: {}
  }),
  actions: {
    updateProfile(profile) {
      this.profile = profile
    }
  }
})

状态规范化: 使用规范化结构存储数据,避免数据冗余。

state: () => ({
  messages: {
    byId: {},
    allIds: []
  }
})

3. API 设计最佳实践

统一错误处理: 在请求拦截器中统一处理错误。

// src/utils/request.ts
request.interceptors.response.use(
  response => {
    return response.data
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 处理未授权
          break
        case 404:
          // 处理未找到
          break
        default:
          // 处理其他错误
      }
    }
    return Promise.reject(error)
  }
)

请求取消: 实现请求取消功能,避免组件卸载后仍然处理响应。

// 在组件中
import { onUnmounted } from 'vue'

let cancelToken

const fetchData = () => {
  cancelToken = axios.CancelToken.source()
  
  request.get('/api/data', {
    cancelToken: cancelToken.token
  })
}

onUnmounted(() => {
  if (cancelToken) {
    cancelToken.cancel('组件卸载,取消请求')
  }
})

4. 代码组织最佳实践

按功能组织: 代码按功能模块组织,而不是按文件类型。

src/
├── features/
│   ├── chat/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── services/
│   │   └── types/
│   └── user/
│       ├── components/
│       ├── hooks/
│       ├── services/
│       └── types/

工具函数分类: 工具函数按功能分类,便于查找和维护。

src/utils/
├── date/          # 日期相关工具
├── format/        # 格式化工具
├── validation/    # 验证工具
└── dom/           # DOM 操作工具

5. 性能优化最佳实践

懒加载组件: 使用动态导入实现组件懒加载。

const SsChatReply = defineAsyncComponent(() => import('./SsChatReply.vue'))

列表虚拟化: 对于长列表使用虚拟滚动技术。

<template>
  <VirtualList :items="messages" :itemHeight="80">
    <template #default="{ item }">
      <SsChatMessage :message="item" />
    </template>
  </VirtualList>
</template>

防抖和节流: 对频繁触发的事件使用防抖和节流。

import { debounce } from 'lodash-es'

const handleInput = debounce((value) => {
  // 处理输入
}, 300)

6. 安全最佳实践

XSS 防护: 使用 DOMPurify 清理用户输入。

import DOMPurify from 'dompurify'

const sanitizedContent = DOMPurify.sanitize(userInput)

CSRF 防护: 在请求中添加 CSRF 令牌。

request.interceptors.request.use(config => {
  config.headers['X-CSRF-TOKEN'] = getCsrfToken()
  return config
})

敏感信息保护: 避免在前端存储敏感信息。

// 不推荐
localStorage.setItem('password', password)

// 推荐
const token = getTemporaryToken() // 短期有效的令牌

第5步:后续深入学习的建议

1. Vue 3 生态系统深入学习

核心概念

  • 深入理解 Vue 3 的响应式系统原理
  • 学习 Composition API 的高级用法
  • 掌握 Vue 3 的性能优化技巧

推荐资源

2. TypeScript 进阶

类型系统

  • 深入学习 TypeScript 高级类型
  • 掌握泛型编程
  • 理解类型推断和类型守卫

实践项目

  • 尝试为现有 JavaScript 项目添加类型
  • 编写自己的类型声明文件
  • 使用 TypeScript 设计复杂的数据结构

推荐资源

3. 前端工程化

构建工具

  • 深入学习 Vite 的工作原理
  • 掌握 Webpack 的高级配置
  • 了解前端模块化标准(ESM、CommonJS)

代码质量

  • 学习 ESLint 和 Prettier 的高级配置
  • 掌握自动化测试(单元测试、集成测试)
  • 了解 CI/CD 流程

推荐资源

4. 状态管理进阶

Pinia 深入

  • 学习 Pinia 的高级特性(插件、订阅等)
  • 掌握状态持久化方案
  • 了解状态管理的最佳实践

其他状态管理方案

  • 了解 Redux 和 MobX
  • 学习状态管理的设计模式
  • 掌握状态调试技巧

推荐资源

5. 前端性能优化

渲染性能

  • 学习浏览器渲染原理
  • 掌握虚拟 DOM 优化技巧
  • 了解重绘和回流优化

加载性能

  • 学习资源加载优化策略
  • 掌握代码分割和懒加载
  • 了解缓存策略

监控与调试

  • 学习性能监控工具(Lighthouse、Performance API)
  • 掌握前端调试技巧
  • 了解性能瓶颈分析方法

推荐资源

6. 前端安全

安全基础

  • 学习常见的前端安全漏洞(XSS、CSRF、点击劫持等)
  • 掌握安全编码规范
  • 了解内容安全策略(CSP)

实践应用

  • 在项目中实施安全措施
  • 学习安全测试方法
  • 了解安全最佳实践

推荐资源

7. 实际项目实践

贡献开源项目

  • 选择感兴趣的开源项目参与贡献
  • 学习项目代码结构和协作流程
  • 提交 Pull Request 并参与代码审查

个人项目

  • 从零开始构建一个完整的前端应用
  • 尝试不同的技术栈和架构
  • 部署到生产环境并维护

技术分享

  • 写技术博客总结学习心得
  • 参与技术社区讨论
  • 分享自己的经验和见解

8. 学习路径建议

初级阶段(1-3个月)

  1. 巩固 Vue 3 基础知识
  2. 学习 TypeScript 基础
  3. 掌握项目构建和调试
  4. 理解现有项目结构和代码

中级阶段(3-6个月)

  1. 深入学习 Vue 3 高级特性
  2. 掌握 TypeScript 进阶
  3. 学习前端工程化工具
  4. 参与项目功能开发

高级阶段(6-12个月)

  1. 深入理解前端性能优化
  2. 掌握前端安全知识
  3. 学习架构设计和最佳实践
  4. 主导项目模块开发

专家阶段(1年以上)

  1. 深入理解前端底层原理
  2. 掌握多种技术栈
  3. 具备架构设计能力
  4. 能够指导团队开发

9. 推荐学习资源

书籍

  • 《Vue.js 设计与实现》
  • 《TypeScript 编程》
  • 《前端工程化:体系设计与实践》
  • 《Web性能权威指南》
  • 《白帽子讲Web安全》

在线课程

  • Vue School
  • Frontend Masters
  • Udemy 前端课程
  • Coursera 前端专项课程

社区和博客

  • Vue 官方论坛
  • DEV Community
  • Medium 前端专栏
  • 掘金社区
  • 知乎前端话题

实践平台

  • GitHub
  • CodePen
  • StackBlitz
  • CodeSandbox

通过循序渐进的学习和实践,你将能够从新手成长为一名熟练的前端开发者,不仅能够理解和维护现有项目,还能够独立设计和开发高质量的前端应用。记住,持续学习和实践是成为优秀前端开发者的关键。