前端Skill全家桶:React+Vue+TypeScript开发实战

前端Skill全家桶:React+Vue+TypeScript开发实战

从组件设计到工程化落地,一文带你打通前端三大核心技术栈 ✨

开头碎碎念 👋

宝子们好呀!今天来聊一个超级硬核但又超级实用的话题------前端Skill全家桶!🔥

说实话,最近在项目里用到了React、Vue和TypeScript的组合拳,真的是越用越香 😊。很多小伙伴私信问我:"前端三大件到底怎么搭配使用?""TypeScript在前端项目里怎么落地?"------别急,今天这篇文章就是专门给你们准备的!

先碎碎念几句:前端技术栈更新太快了,React 19刚出、Vue 3.4也更新了、TypeScript 5.x又加了新特性......但是万变不离其宗,核心思想搞懂了,学什么都快 💪

好啦,言归正传,咱们开始吧!🚀


一、为什么需要前端Skill全家桶?🤔

很多同学可能会问:我学好一个框架不就行了吗?为什么还要搞React+Vue+TypeScript三件套?

这里我说几个现实场景:

  1. 公司技术栈切换:今天公司用Vue,明天被收购了要迁移到React,你不会就尴尬了 😅
  2. 开源项目贡献:GitHub上优质项目React和Vue各占半壁江山,只会一个就少了一半的机会
  3. 技术选型能力:只有都了解过,才能在架构设计时做出最优选择
  4. TypeScript是刚需:2024年了,不用TS的前端项目真的越来越少了

所以呀,掌握这三者的核心用法和最佳实践,是每个进阶前端工程师的必修课 ⭐


二、TypeScript:前端开发的基石 🏗️

2.1 为什么TypeScript这么重要?

宝宝们听我说,TypeScript不是"可选的加分项",而是"必须掌握的基本功"✨

typescript 复制代码
// 没有TS的时候,这种bug可能要运行时才发现 😱
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}

// 有了TS,类型错误在写代码的时候就能捕获
interface Product {
  id: string;
  name: string;
  price: number;
  stock: number;
  tags?: string[]; // 可选属性
}

// 定义一个购物车项的类型
interface CartItem {
  product: Product;
  quantity: number;
  discount?: number;
}

// 类型安全的购物车计算
class ShoppingCart {
  private items: CartItem[] = [];

  addItem(product: Product, quantity: number, discount?: number): void {
    if (quantity <= 0) {
      throw new Error("数量必须大于0哦 🤔");
    }
    if (product.stock < quantity) {
      throw new Error(`库存不足!当前库存:${product.stock}`);
    }
    this.items.push({ product, quantity, discount });
  }

  getTotal(): number {
    return this.items.reduce((total, item) => {
      const itemTotal = item.product.price * item.quantity;
      const discount = item.discount || 0;
      return total + itemTotal * (1 - discount);
    }, 0);
  }

  getSummary(): { totalItems: number; totalPrice: number } {
    return {
      totalItems: this.items.reduce((sum, item) => sum + item.quantity, 0),
      totalPrice: this.getTotal(),
    };
  }
}

2.2 泛型实战:写出可复用的工具函数

接下来看看泛型怎么用,这个在前端项目里超级常见 💡

typescript 复制代码
// 通用的API请求封装
interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
  timestamp: number;
}

// 通用的分页数据结构
interface PaginatedData<T> {
  list: T[];
  total: number;
  page: number;
  pageSize: number;
}

// 泛型请求函数
async function fetchApi<T>(url: string, options?: RequestInit): Promise<ApiResponse<T>> {
  const response = await fetch(url, {
    headers: {
      'Content-Type': 'application/json',
      ...options?.headers,
    },
    ...options,
  });

  if (!response.ok) {
    throw new Error(`请求失败: ${response.status}`);
  }

  return response.json();
}

// 使用示例
interface User {
  id: string;
  name: string;
  email: string;
  avatar: string;
}

// 类型安全的数据获取
const userData = await fetchApi<User[]>('/api/users');
const paginatedUsers = await fetchApi<PaginatedData<User>>('/api/users?page=1');

看到没?有了泛型,API请求的类型安全就有了保障,再也不用 any 到处飞了 🎉


三、React实战:组件化开发的艺术 🎨

3.1 React 19 + TypeScript 项目搭建

那么,咱们先来搭一个现代化的React项目 ⚡

bash 复制代码
# 使用Vite创建React+TS项目
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev

3.2 自定义Hook:封装业务逻辑

React最强大的地方之一就是自定义Hook,让我们把复杂逻辑抽离出来 🔥

tsx 复制代码
// useFetch.ts - 通用数据请求Hook
import { useState, useEffect, useCallback } from 'react';

interface UseFetchState<T> {
  data: T | null;
  loading: boolean;
  error: string | null;
}

interface UseFetchReturn<T> extends UseFetchState<T> {
  refetch: () => void;
}

function useFetch<T>(url: string): UseFetchReturn<T> {
  const [state, setState] = useState<UseFetchState<T>>({
    data: null,
    loading: true,
    error: null,
  });

  const fetchData = useCallback(async () => {
    setState(prev => ({ ...prev, loading: true, error: null }));
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const data: T = await response.json();
      setState({ data, loading: false, error: null });
    } catch (err) {
      setState({
        data: null,
        loading: false,
        error: err instanceof Error ? err.message : '未知错误',
      });
    }
  }, [url]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  return { ...state, refetch: fetchData };
}

// 使用示例:用户列表组件
function UserList() {
  const { data: users, loading, error, refetch } = useFetch<User[]>('/api/users');

  if (loading) return <div className="loading">加载中... ⏳</div>;
  if (error) return <div className="error">出错了: {error} 😱</div>;

  return (
    <div className="user-list">
      <h2>用户列表 👥</h2>
      <button onClick={refetch}>刷新 🔄</button>
      <ul>
        {users?.map(user => (
          <li key={user.id}>
            <img src={user.avatar} alt={user.name} />
            <span>{user.name}</span>
            <span>{user.email}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}

3.3 组件设计模式:复合组件

接下来给大家展示一个高级但非常实用的模式------复合组件模式 💡

tsx 复制代码
// Card复合组件
interface CardProps {
  children: React.ReactNode;
  className?: string;
}

function Card({ children, className = '' }: CardProps) {
  return <div className={`card ${className}`}>{children}</div>;
}

Card.Header = function Header({ children, title }: { children?: React.ReactNode; title: string }) {
  return (
    <div className="card-header">
      <h3>{title}</h3>
      {children}
    </div>
  );
};

Card.Body = function Body({ children }: { children: React.ReactNode }) {
  return <div className="card-body">{children}</div>;
};

Card.Footer = function Footer({ children }: { children: React.ReactNode }) {
  return <div className="card-footer">{children}</div>;
};

// 使用起来超级优雅 ✨
function UserProfile() {
  return (
    <Card className="profile-card">
      <Card.Header title="用户信息">
        <button>编辑 ✏️</button>
      </Card.Header>
      <Card.Body>
        <p>姓名:张三</p>
        <p>职位:前端工程师</p>
      </Card.Body>
      <Card.Footer>
        <button>保存 💾</button>
        <button>取消</button>
      </Card.Footer>
    </Card>
  );
}

四、Vue 3实战:优雅的响应式编程 🖼️

4.1 Vue 3 + TypeScript组合式API

好啦,React看完了,咱们再来看看Vue 3的写法 🎯

bash 复制代码
# 使用Vite创建Vue3+TS项目
npm create vite@latest my-vue-app -- --template vue-ts
cd my-vue-app
npm install
npm run dev

4.2 组合式函数(Composables)

Vue 3的Composables和React的Custom Hooks有异曲同工之妙,但写法更优雅 😊

typescript 复制代码
// composables/useCounter.ts
import { ref, computed } from 'vue';

export function useCounter(initialValue: number = 0) {
  const count = ref<number>(initialValue);
  const doubleCount = computed(() => count.value * 2);
  const isEven = computed(() => count.value % 2 === 0);

  function increment(): void {
    count.value++;
  }

  function decrement(): void {
    count.value--;
  }

  function reset(): void {
    count.value = initialValue;
  }

  function incrementBy(amount: number): void {
    count.value += amount;
  }

  return {
    count,
    doubleCount,
    isEven,
    increment,
    decrement,
    reset,
    incrementBy,
  };
}
vue 复制代码
<!-- Counter.vue -->
<template>
  <div class="counter">
    <h2>计数器 🔢</h2>
    <p class="count">{{ count }}</p>
    <p class="double">双倍值:{{ doubleCount }}</p>
    <p :class="{ even: isEven, odd: !isEven }">
      {{ isEven ? '偶数 ✅' : '奇数 ⭕' }}
    </p>
    <div class="buttons">
      <button @click="decrement">-1</button>
      <button @click="increment">+1</button>
      <button @click="incrementBy(5)">+5</button>
      <button @click="reset">重置 🔄</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { useCounter } from '@/composables/useCounter';

const {
  count,
  doubleCount,
  isEven,
  increment,
  decrement,
  reset,
  incrementBy,
} = useCounter(0);
</script>

4.3 Pinia状态管理实战

Vue 3官方推荐的状态管理方案Pinia,用起来真的太丝滑了 🚀

typescript 复制代码
// stores/userStore.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
}

export const useUserStore = defineStore('user', () => {
  const users = ref<User[]>([]);
  const currentUser = ref<User | null>(null);
  const loading = ref(false);

  const adminUsers = computed(() =>
    users.value.filter(user => user.role === 'admin')
  );

  const totalUsers = computed(() => users.value.length);
  const isLoggedIn = computed(() => currentUser.value !== null);

  async function fetchUsers(): Promise<void> {
    loading.value = true;
    try {
      const response = await fetch('/api/users');
      users.value = await response.json();
    } finally {
      loading.value = false;
    }
  }

  function login(user: User): void {
    currentUser.value = user;
    localStorage.setItem('currentUser', JSON.stringify(user));
  }

  function logout(): void {
    currentUser.value = null;
    localStorage.removeItem('currentUser');
  }

  return {
    users, currentUser, loading,
    adminUsers, totalUsers, isLoggedIn,
    fetchUsers, login, logout,
  };
});

五、React vs Vue:如何选择?⚖️

很多宝子们最纠结的问题来了:到底选React还是Vue?我给大家一个对比表 👀

对比维度 React Vue
学习曲线 中等偏上 较低,上手快
生态规模 超大,社区活跃 大,中文生态好
TypeScript支持 原生支持,体验好 Vue 3支持优秀
状态管理 Redux/Zustand/Jotai Pinia(官方推荐)
适用场景 大型复杂应用 中小型到大型均可
就业市场 需求量大 国内需求旺盛

我的建议💡:

  • 如果你是新手入门,推荐先学Vue,上手快、成就感强
  • 如果你想进大厂,React是必备技能
  • 如果你想技术全面,两个都学!先学一个,再学第二个会很快

六、实战案例:打造一个Todo App 📝

最后,咱们用一个完整的Todo App来串联所有知识点 🔥

tsx 复制代码
// React + TypeScript 版本的Todo App
import { useState, useCallback, useMemo } from 'react';

interface Todo {
  id: string;
  text: string;
  completed: boolean;
  priority: 'low' | 'medium' | 'high';
  createdAt: number;
}

type FilterType = 'all' | 'active' | 'completed';

function TodoApp() {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [inputText, setInputText] = useState('');
  const [filter, setFilter] = useState<FilterType>('all');

  const addTodo = useCallback(() => {
    if (!inputText.trim()) return;
    const newTodo: Todo = {
      id: crypto.randomUUID(),
      text: inputText.trim(),
      completed: false,
      priority: 'medium',
      createdAt: Date.now(),
    };
    setTodos(prev => [newTodo, ...prev]);
    setInputText('');
  }, [inputText]);

  const toggleTodo = useCallback((id: string) => {
    setTodos(prev =>
      prev.map(todo =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  }, []);

  const deleteTodo = useCallback((id: string) => {
    setTodos(prev => prev.filter(todo => todo.id !== id));
  }, []);

  const filteredTodos = useMemo(() => {
    switch (filter) {
      case 'active': return todos.filter(t => !t.completed);
      case 'completed': return todos.filter(t => t.completed);
      default: return todos;
    }
  }, [todos, filter]);

  const stats = useMemo(() => ({
    total: todos.length,
    completed: todos.filter(t => t.completed).length,
    active: todos.filter(t => !t.completed).length,
  }), [todos]);

  return (
    <div className="todo-app">
      <h1>📝 Todo App</h1>
      <div className="input-group">
        <input
          value={inputText}
          onChange={e => setInputText(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && addTodo()}
          placeholder="添加新任务..."
        />
        <button onClick={addTodo}>添加 ➕</button>
      </div>
      <div className="filters">
        {(['all', 'active', 'completed'] as FilterType[]).map(f => (
          <button
            key={f}
            className={filter === f ? 'active' : ''}
            onClick={() => setFilter(f)}
          >
            {f === 'all' ? '全部' : f === 'active' ? '进行中' : '已完成'}
          </button>
        ))}
      </div>
      <div className="stats">
        <span>总计: {stats.total}</span>
        <span>已完成: {stats.completed}</span>
        <span>进行中: {stats.active}</span>
      </div>
      <ul className="todo-list">
        {filteredTodos.map(todo => (
          <li key={todo.id} className={todo.completed ? 'completed' : ''}>
            <input type="checkbox" checked={todo.completed}
              onChange={() => toggleTodo(todo.id)} />
            <span>{todo.text}</span>
            <button onClick={() => deleteTodo(todo.id)}>删除 🗑️</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

七、总结与展望 🌟

好啦,今天的分享就到这里啦!咱们回顾一下重点内容 📋

  1. TypeScript是前端开发的基石,类型安全能帮你避免大量bug
  2. React的Hooks和组件模式让逻辑复用变得优雅
  3. Vue 3的组合式API和Pinia提供了简洁的开发体验
  4. 两个框架各有优势,建议都学,技多不压身 💪

接下来大家可以尝试:

  • 用React+TS重构一个现有项目
  • 用Vue 3写一个完整的CRUD应用
  • 对比两个框架在同一个项目中的不同实现

希望对大家有帮助!如果觉得有用的话,记得点赞收藏哦 ⭐🎉

有问题欢迎在评论区留言,我会一一回复的~下次见啦 👋😊

相关推荐
大大杰哥1 小时前
Vue2学习(3)--组件中的通信方式/组件之间的交互
java·前端·javascript
阿猫的故乡1 小时前
Vue3自定义插件:封装一个全局消息提示插件,所有组件都能直接用
前端·javascript·vue.js
橘子星1 小时前
树与二叉树:从概念到 JavaScript 实现
前端·javascript·面试
小小高不懂写代码1 小时前
Transformer与注意力机制
前端·人工智能
AiClaw1 小时前
AIClaw 的 Skills 机制:先注入索引,再按需读取完整说明
前端
YHHLAI1 小时前
HTML5 Canvas 从入门到实战:画布绘图 · 帧动画 · 小游戏 · 数据可视化
前端·信息可视化·html5
前端 贾公子1 小时前
npx skills:AI Agent Skill 的 npm,50+ 工具统一的 Skill 管理工具
前端
触底反弹1 小时前
面试官问"Ajax原理",我从XHR讲到async/await,他直接懵了!
前端·面试·架构
Chelsea05221 小时前
PC浏览器在线调试 Android 浏览器教程-chrome://inspect/#devices
android·前端·chrome