跳转至

前端框架

📖 阅读信息

阅读时间:1 分钟 | 中文字符:197 | 有效代码行数:271

主流前端框架概览

React

Facebook 开发的用于构建用户界面的 JavaScript 库

核心概念

JSX
// 函数组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 类组件
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

// Hook 使用
import React, { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    document.title = `点击了 ${count} 次`;
  }, [count]);
  
  return (
    <div>
      <p>你点击了 {count} </p>
      <button onClick={() => setCount(count + 1)}>
        点击我
      </button>
    </div>
  );
}

状态管理

JSX
// Context API
const ThemeContext = React.createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return <ThemedButton />;
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>主题按钮</button>;
}

Vue.js

渐进式 JavaScript 框架

基础语法

Vue
<template>
  <div id="app">
    <h1>{{ message }}</h1>
    <button @click="reverseMessage">反转消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  methods: {
    reverseMessage() {
      this.message = this.message.split('').reverse().join('')
    }
  }
}
</script>

<style>
#app {
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

组合式 API

Vue
<template>
  <div>
    <p>计数: {{ count }}</p>
    <p>双倍: {{ double }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const count = ref(0)
const double = computed(() => count.value * 2)

function increment() {
  count.value++
}
</script>

Angular

Google 开发的企业级前端框架

组件示例

TypeScript
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div>
      <h1>{{ title }}</h1>
      <button (click)="changeTitle()">改变标题</button>
    </div>
  `,
  styles: [`
    h1 {
      color: #333;
    }
  `]
})
export class AppComponent {
  title = 'Angular 应用';
  
  changeTitle() {
    this.title = '标题已改变!';
  }
}

服务示例

TypeScript
// user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private http: HttpClient) { }
  
  getUsers(): Observable<any[]> {
    return this.http.get<any[]>('/api/users');
  }
}

框架对比

特性 React Vue Angular
学习曲线 中等 简单 陡峭
数据绑定 单向 双向 双向
组件化
TypeScript 可选 可选 内置
体积 最小
生态系统 丰富 丰富 完整

现代前端工具链

包管理器

Bash
1
2
3
4
5
6
7
8
# npm
npm install react react-dom

# yarn
yarn add vue@next

# pnpm
pnpm add angular

构建工具

Vite (推荐)

Bash
# 创建项目
npm create vite@latest my-app --template react
npm create vite@latest my-vue-app --template vue

# 配置示例
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
    open: true
  }
})

Webpack

JavaScript
// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-react']
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
};

状态管理

Redux (React)

JavaScript
// store.js
import { configureStore } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => { state.value += 1 },
    decrement: state => { state.value -= 1 }
  }
})

export const { increment, decrement } = counterSlice.actions
export default configureStore({
  reducer: {
    counter: counterSlice.reducer
  }
})

Pinia (Vue)

JavaScript
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

路由管理

React Router

JSX
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/about">关于</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/user/:id" element={<User />} />
      </Routes>
    </BrowserRouter>
  )
}

Vue Router

JavaScript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/user/:id', component: User, props: true }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

UI 组件库

React UI 库

  • Ant Design: 企业级 UI 设计语言
  • Material-UI: Google 的 Material Design
  • Chakra UI: 简单、模块化和可访问的组件库

Vue UI 库

  • Element Plus: 基于 Vue 3 的组件库
  • Ant Design Vue: Ant Design 的 Vue 版本
  • Vuetify: Material Design 组件框架

使用示例 (Ant Design)

JSX
import { Button, Table, Form, Input } from 'antd'

function UserList() {
  const columns = [
    { title: '姓名', dataIndex: 'name' },
    { title: '年龄', dataIndex: 'age' },
    { 
      title: '操作', 
      render: (text, record) => (
        <Button type="primary" onClick={() => editUser(record)}>
          编辑
        </Button>
      )
    }
  ]
  
  return <Table columns={columns} dataSource={users} />
}

测试

React Testing Library

JavaScript
import { render, screen, fireEvent } from '@testing-library/react'
import Counter from './Counter'

test('计数器功能测试', () => {
  render(<Counter />)
  
  const button = screen.getByText('增加')
  fireEvent.click(button)
  
  expect(screen.getByText('计数: 1')).toBeInTheDocument()
})

Vue Test Utils

JavaScript
import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'

test('计数器功能测试', async () => {
  const wrapper = mount(Counter)
  
  await wrapper.find('button').trigger('click')
  
  expect(wrapper.text()).toContain('计数: 1')
})

部署

静态部署

Bash
1
2
3
4
5
6
# 构建生产版本
npm run build

# 部署到 GitHub Pages
npm install -g gh-pages
gh-pages -d dist

Docker 部署

Docker
# Dockerfile
FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

持续更新中...

💬 评论

评论系统加载中...