继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

前端入门项目实战:从零开始的完整指南

哈士奇WWW
关注TA
已关注
手记 496
粉丝 71
获赞 400
概述

本文将带你一步步学习前端入门项目实战,从搭建开发环境开始,涵盖HTML、CSS、JavaScript的基础知识,再到React框架的应用,最后通过构建个人博客项目巩固所学,帮助你快速上手前端开发。

前端开发环境搭建

在开始学习前端开发之前,你需要搭建一个合适的开发环境。这包括安装Node.js和npm,选择一个合适的文本编辑器(如VSCode),以及安装一些常用的开发工具,如Git。

安装Node.js和npm

Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它允许你在服务器端编写和运行JavaScript代码。npm是Node.js的包管理器,用于安装和管理Node.js的库。

  1. 访问Node.js官网,下载并安装最新版本的Node.js。安装过程中,确保勾选“Add to PATH”选项。

  2. 验证安装是否成功,打开命令行工具,输入以下命令:

    node -v
    npm -v

    如果安装成功,你应该能看到Node.js和npm的版本号。

安装文本编辑器(如VSCode)

文本编辑器是编写代码的重要工具。选择一个合适的文本编辑器可以提高开发效率。这里推荐使用VSCode。

  1. 访问VSCode官网,下载并安装VSCode。

  2. 配置VSCode。你可以安装一些插件来提高开发体验,例如:

    • Live Server:用于快速启动一个本地服务器来预览HTML文件。
    • ESLint:用于代码检查,确保代码符合规范。
    • Prettier:用于代码格式化,保持代码风格一致。
安装常用工具(如Git)

Git是一个分布式版本控制系统,用于跟踪代码的修改历史。使用Git可以方便地管理代码版本,与团队成员协作。

  1. 访问Git官网,下载并安装Git。

  2. 验证安装是否成功,打开命令行工具,输入以下命令:

    git --version

    如果安装成功,你应该能看到Git的版本号。

  3. 配置Git。设置用户名和邮箱:

    git config --global user.name "Your Name"
    git config --global user.email "your.email@example.com"

通过上述步骤,你已经成功搭建了一个前端开发环境,可以开始编写代码了。

HTML与CSS基础

HTML和CSS是前端开发的基础。HTML用于定义网页的结构和内容,CSS用于控制网页的样式和布局。

HTML标签与结构

HTML(HyperText Markup Language)是用于创建网页的标准标记语言。HTML文档由一系列标签组成,这些标签定义了文档的结构和内容。

基本结构

一个HTML文档的基本结构如下:

<!DOCTYPE html>
<html>
<head>
    <title>网页标题</title>
</head>
<body>
    <h1>这是第一个标题</h1>
    <p>这是一个段落。</p>
</body>
</html>

常用标签

  • <html>:根标签,包含整个HTML文档。
  • <head>:包含文档的元数据,如<title>标签。
  • <body>:包含实际内容,如文本、图片、链接等。
  • <title>:定义文档的标题。
  • <h1> - <h6>:标题标签,从<h1><h6>表示标题的级别依次降低。
  • <p>:段落标签。
  • <a>:链接标签,用于创建超链接。
  • <img>:图像标签,用于插入图片。
  • <div>:块级容器标签,用于布局和样式划分。
  • <span>:行内容器标签,用于文本样式划分。

示例:

<!DOCTYPE html>
<html>
<head>
    <title>示例页面</title>
</head>
<body>
    <h1>欢迎来到示例页面</h1>
    <p>这是一个段落。</p>
    <a href="https://www.imooc.com/">访问慕课网</a>
    <img src="https://example.com/image.jpg" alt="示例图像">
    <div>
        <p>这是第一个段落。</p>
        <p>这是第二个段落。</p>
    </div>
</body>
</html>
CSS选择器与样式应用

CSS(Cascading Style Sheets)用于控制网页的样式和布局。CSS通过选择器来定义样式规则,这些规则会应用到匹配的HTML元素上。

基本选择器

  • 元素选择器:通过元素名选择元素。

    p {
      color: blue;
    }
  • 类选择器:通过类名选择元素。

    .highlight {
      background-color: yellow;
    }
  • ID选择器:通过ID选择元素。

    #header {
      font-size: 24px;
    }
  • 后代选择器:通过层级关系选择后代元素。

    div p {
      text-align: center;
    }
  • 子选择器:通过直接子元素选择元素。

    div > p {
      font-weight: bold;
    }

样式属性

  • 字体font-familyfont-sizefont-weight
  • 颜色colorbackground-color
  • 边框borderborder-radius
  • 盒模型marginpadding
  • 布局displaypositionfloat

示例:

<!DOCTYPE html>
<html>
<head>
    <style>
        p {
            color: blue;
        }
        .highlight {
            background-color: yellow;
        }
        #header {
            font-size: 24px;
        }
        div p {
            text-align: center;
        }
        div > p {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <h1 id="header">示例页面</h1>
    <p class="highlight">这是一个段落。</p>
    <p>这是另一个段落。</p>
    <div>
        <p>这是第一个段落。</p>
        <p>这是第二个段落。</p>
    </div>
</body>
</html>
常见布局技术(如Flexbox与Grid)

CSS提供了多种布局技术,如Flexbox和Grid,用于创建复杂的布局。

Flexbox

Flexbox(弹性布局)用于创建可伸缩的容器,使容器内的项目可以根据需要自动调整大小。

.container {
    display: flex;
    justify-content: center; /* 主轴居中对齐 */
    align-items: center; /* 侧轴居中对齐 */
}
<!DOCTYPE html>
<html>
<head>
    <style>
        .container {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 200px;
            background-color: lightgray;
        }
        .item {
            width: 100px;
            height: 100px;
            background-color: lightblue;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</body>
</html>

Grid

CSS Grid(网格布局)用于创建复杂的二维布局,使容器内的项目按照行和列排列。

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr); /* 三列,每列等宽 */
    grid-template-rows: repeat(2, 1fr); /* 两行,每行等高 */
}
<!DOCTYPE html>
<html>
<head>
    <style>
        .container {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: repeat(2, 1fr);
            height: 300px;
            background-color: lightgray;
        }
        .item {
            background-color: lightblue;
            padding: 20px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
</body>
</html>

通过上述内容,你已经掌握了HTML和CSS的基础知识,可以开始创建简单的网页了。

JavaScript入门

JavaScript是一种广泛使用的编程语言,用于在浏览器中实现交互性和动态效果。本节将介绍JavaScript的基本概念,包括变量、数据类型、运算符、流程控制(条件语句和循环)以及DOM操作和事件处理。

变量与数据类型

变量用于存储数据,可以是数字、字符串、布尔值等。在JavaScript中,可以使用letconstvar声明变量。

变量声明

  • let:可以重新声明和重新赋值
  • const:不可重新声明,但值可以改变
  • var:可以重新声明和重新赋值,但不建议使用
let name = "张三";
const age = 25;
var hobby = "编程";

数据类型

  • 数字number,使用Number类型,例如1233.14
  • 字符串string,使用String类型,例如"hello"'world'
  • 布尔值boolean,使用Boolean类型,例如truefalse
  • 数组Array,使用Array类型,例如[1, 2, 3]
  • 对象Object,使用Object类型,例如{name: "张三", age: 25}
  • nullnull,表示空值
  • undefinedundefined,表示未定义的变量
let number = 42; // Number
let string = "Hello, world!"; // String
let boolean = true; // Boolean
let array = [1, 2, 3]; // Array
let object = {name: "张三", age: 25}; // Object
let nullValue = null; // null
let undefinedValue; // undefined

类型转换

JavaScript支持类型转换,可以将一种数据类型转换为另一种。

  • 隐式类型转换(自动类型转换):

    let a = "10"; // 字符串
    let b = 20; // 数字
    let result = a + b; // 结果为 "1020",字符串拼接
  • 显式类型转换(手动类型转换):

    let a = "10"; // 字符串
    let b = 20; // 数字
    let result = Number(a) + b; // 结果为 30,数字相加
流程控制

流程控制语句用于控制程序的执行流程,包括条件语句和循环。

条件语句

  • if 语句

    let age = 25;
    if (age >= 18) {
      console.log("成年");
    } else {
      console.log("未成年");
    }
  • switch 语句
    let fruit = "apple";
    switch (fruit) {
      case "apple":
          console.log("苹果");
          break;
      case "banana":
          console.log("香蕉");
          break;
      default:
          console.log("其他水果");
    }

循环语句

  • for 循环

    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
  • while 循环

    let i = 0;
    while (i < 5) {
      console.log(i);
      i++;
    }
  • do...while 循环
    let i = 0;
    do {
      console.log(i);
      i++;
    } while (i < 5);
DOM操作与事件处理

DOM(Document Object Model)是浏览器解析HTML文档后生成的树状结构,可以用于访问和操作网页的元素。事件处理则用于响应用户的交互行为。

获取元素

  • 通过ID获取元素

    let element = document.getElementById("myElement");
  • 通过类名获取元素

    let elements = document.getElementsByClassName("myClass");
  • 通过标签名获取元素
    let elements = document.getElementsByTagName("div");

修改元素

  • 设置文本内容

    let element = document.getElementById("myElement");
    element.textContent = "新的文本内容";
  • 设置HTML内容

    let element = document.getElementById("myElement");
    element.innerHTML = "<span>新的HTML内容</span>";
  • 添加类名

    let element = document.getElementById("myElement");
    element.classList.add("newClass");
  • 删除类名
    let element = document.getElementById("myElement");
    element.classList.remove("oldClass");

事件处理

  • 绑定事件

    let button = document.getElementById("myButton");
    button.addEventListener("click", function() {
      console.log("按钮被点击了");
    });
  • 移除事件
    let button = document.getElementById("myButton");
    let clickHandler = function() {
      console.log("按钮被点击了");
    };
    button.removeEventListener("click", clickHandler);

通过上述内容,你已经掌握了JavaScript的基础知识,可以开始编写简单的脚本来实现网页的交互功能。

常见前端框架介绍

前端框架是现代Web开发中不可或缺的一部分,它们提供了丰富的组件和工具,简化了开发过程。本节将介绍三个流行的前端框架:React、Vue和Angular。

React基础使用

React是由Facebook开发并开源的JavaScript库,主要用于构建用户界面。React的核心思想是“组件化开发”,即将复杂的UI拆分为多个小的、可重用的组件。

创建React应用

  1. 安装Node.js和npm(如果尚未安装,请参阅“前端开发环境搭建”章节)。
  2. 安装Create React App,这是一个官方推荐的脚手架工具,用于快速创建React应用。

    npx create-react-app my-app
    cd my-app
    npm start
  3. 基本组件:React应用由多个组件组成,每个组件都有自己的功能和状态。

    import React from 'react';
    import './App.css';
    
    function App() {
       return (
           <div className="App">
               <h1>Hello, World!</h1>
               <Header />
               <Footer />
           </div>
       );
    }
    
    function Header() {
       return <header>我是头部</header>;
    }
    
    function Footer() {
       return <footer>我是底部</footer>;
    }
    
    export default App;

使用状态(State)

状态用于存储组件内部的数据。React提供了useState函数来管理状态。

import React, { useState } from 'react';
import './App.css';

function App() {
    const [count, setCount] = useState(0);

    return (
        <div className="App">
            <h1>Hello, World!</h1>
            <Header />
            <Footer />
            <Counter count={count} setCount={setCount} />
        </div>
    );
}

function Header() {
    return <header>我是头部</header>;
}

function Footer() {
    return <footer>我是底部</footer>;
}

function Counter({ count, setCount }) {
    return (
        <div>
            <p>当前计数:{count}</p>
            <button onClick={() => setCount(count + 1)}>增加</button>
            <button onClick={() => setCount(count - 1)}>减少</button>
        </div>
    );
}

export default App;

使用生命周期方法

React组件有生命周期方法,用于在组件的各个生命周期阶段执行特定的操作。

import React, { Component } from 'react';
import './App.css';

class App extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }

    componentDidMount() {
        console.log('组件挂载完成');
    }

    componentWillUnmount() {
        console.log('组件将要卸载');
    }

    render() {
        return (
            <div className="App">
                <h1>Hello, World!</h1>
                <Header />
                <Footer />
                <Counter count={this.state.count} />
            </div>
        );
    }
}

function Header() {
    return <header>我是头部</header>;
}

function Footer() {
    return <footer>我是底部</footer>;
}

function Counter({ count }) {
    return (
        <div>
            <p>当前计数:{count}</p>
        </div>
    );
}

export default App;
Vue基础使用

Vue是由Evan You开发并开源的JavaScript框架,主要用于构建交互式的Web应用。Vue的核心思想也是“组件化开发”,并且提供了丰富的插件和工具来简化开发过程。

创建Vue应用

  1. 安装Node.js和npm(如果尚未安装,请参阅“前端开发环境搭建”章节)。
  2. 安装Vue CLI,这是一个官方推荐的脚手架工具,用于快速创建Vue应用。

    npm install -g @vue/cli
    vue create my-vue-app
    cd my-vue-app
    npm run serve
  3. 基本组件:Vue应用由多个组件组成,每个组件都有自己的功能和状态。

    <template>
       <div id="app">
           <h1>Hello, World!</h1>
           <Header />
           <Footer />
       </div>
    </template>
    
    <script>
    import Header from './components/Header.vue';
    import Footer from './components/Footer.vue';
    
    export default {
       name: 'App',
       components: {
           Header,
           Footer
       }
    };
    </script>
    
    <style>
    /* 全局样式 */
    </style>
    <template>
       <header>我是头部</header>
    </template>
    
    <script>
    export default {
       name: 'Header'
    };
    </script>
    
    <style scoped>
    /* 局部样式 */
    </style>
    <template>
       <footer>我是底部</footer>
    </template>
    
    <script>
    export default {
       name: 'Footer'
    };
    </script>
    
    <style scoped>
    /* 局部样式 */
    </style>

使用状态(State)

Vue使用data函数来管理组件的状态。

<template>
    <div id="app">
        <h1>Hello, World!</h1>
        <Header />
        <Footer />
        <Counter :count="count" />
    </div>
</template>

<script>
import Header from './components/Header.vue';
import Footer from './components/Footer.vue';
import Counter from './components/Counter.vue';

export default {
    name: 'App',
    components: {
        Header,
        Footer,
        Counter
    },
    data() {
        return {
            count: 0
        };
    }
};
</script>

<script>
export default {
    name: 'Counter',
    props: ['count'],
    template: `
        <div>
            <p>当前计数:{{ count }}</p>
            <button @click="increment">增加</button>
            <button @click="decrement">减少</button>
        </div>
    `,
    methods: {
        increment() {
            this.$emit('increment');
        },
        decrement() {
            this.$emit('decrement');
        }
    }
};
</script>

<script>
export default {
    name: 'App',
    components: {
        Header,
        Footer,
        Counter
    },
    data() {
        return {
            count: 0
        };
    },
    methods: {
        increment() {
            this.count += 1;
        },
        decrement() {
            this.count -= 1;
        }
    }
};
</script>

使用生命周期钩子

Vue组件有生命周期钩子,用于在组件的各个生命周期阶段执行特定的操作。

<template>
    <div id="app">
        <h1>Hello, World!</h1>
        <Header />
        <Footer />
    </div>
</template>

<script>
import Header from './components/Header.vue';
import Footer from './components/Footer.vue';

export default {
    name: 'App',
    components: {
        Header,
        Footer
    },
    created() {
        console.log('组件创建完成');
    },
    mounted() {
        console.log('组件挂载完成');
    },
    beforeDestroy() {
        console.log('组件将要卸载');
    }
};
</script>
Angular基础使用

Angular是由Google开发并开源的前端框架,主要用于构建复杂的Web应用。Angular的核心思想是“组件化开发”,并且提供了强大的依赖注入和模板引擎来简化开发过程。

创建Angular应用

  1. 安装Node.js和npm(如果尚未安装,请参阅“前端开发环境搭建”章节)。
  2. 安装Angular CLI,这是一个官方推荐的脚手架工具,用于快速创建Angular应用。

    npm install -g @angular/cli
    ng new my-angular-app
    cd my-angular-app
    ng serve
  3. 基本组件:Angular应用由多个组件组成,每个组件都有自己的功能和状态。

    import { Component } from '@angular/core';
    
    @Component({
       selector: 'app-root',
       templateUrl: './app.component.html',
       styleUrls: ['./app.component.css']
    })
    export class AppComponent {
       title = 'Hello, World!';
    }
    <h1>{{ title }}</h1>
    <app-header></app-header>
    <app-footer></app-footer>
    import { Component } from '@angular/core';
    
    @Component({
       selector: 'app-header',
       templateUrl: './header.component.html',
       styleUrls: ['./header.component.css']
    })
    export class HeaderComponent {}
    <header>我是头部</header>
    import { Component } from '@angular/core';
    
    @Component({
       selector: 'app-footer',
       templateUrl: './footer.component.html',
       styleUrls: ['./footer.component.css']
    })
    export class FooterComponent {}
    <footer>我是底部</footer>

使用状态(State)

Angular使用@Input装饰器来管理组件的状态。

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
    selector: 'app-counter',
    templateUrl: './counter.component.html',
    styleUrls: ['./counter.component.css']
})
export class CounterComponent {
    @Input() count: number = 0;

    @Output() increment = new EventEmitter<void>();
    @Output() decrement = new EventEmitter<void>();

    incrementCount() {
        this.increment.emit();
    }

    decrementCount() {
        this.decrement.emit();
    }
}
<div>
    <p>当前计数:{{ count }}</p>
    <button (click)="incrementCount()">增加</button>
    <button (click)="decrementCount()">减少</button>
</div>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    count = 0;

    increment() {
        this.count += 1;
    }

    decrement() {
        this.count -= 1;
    }
}
<app-counter [count]="count" (increment)="increment()" (decrement)="decrement()"></app-counter>

使用生命周期钩子

Angular组件有生命周期钩子,用于在组件的各个生命周期阶段执行特定的操作。

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
    ngOnInit() {
        console.log('组件创建完成');
    }

    ngOnDestroy() {
        console.log('组件将要卸载');
    }
}

通过上述内容,你已经掌握了React、Vue和Angular的基础知识,可以根据项目需求选择合适的框架进行开发。

实战项目:构建个人博客

在本节中,我们将通过实际项目来巩固前面所学的知识,构建一个简单的个人博客。项目将包括以下几个部分:项目需求分析、页面设计与布局、实现功能(如文章列表与详情页)。

项目需求分析

功能需求

  1. 文章列表页:展示所有文章的标题、摘要和发布时间。
  2. 文章详情页:展示单篇文章的详细内容。
  3. 文章管理后台:管理员可以添加、编辑和删除文章。

技术选型

  • 前端框架:React、Vue或Angular均可,这里以React为例进行演示。
  • 后端框架:RESTful API,可以使用Node.js和Express。
  • 数据库:MySQL或MongoDB,这里使用MongoDB。

技术栈

  • 前端:React + Axios(用于HTTP请求)
  • 后端:Node.js + Express + MongoDB
  • 构建工具:Create React App
页面设计与布局

文章列表页

文章列表页将展示所有文章的基本信息,包括标题、摘要和发布时间。我们使用React组件来实现这个功能。

import React, { useEffect, useState } from 'react';
import axios from 'axios';

function ArticleList() {
    const [articles, setArticles] = useState([]);

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

    const fetchArticles = async () => {
        const response = await axios.get('/api/articles');
        setArticles(response.data);
    };

    return (
        <div>
            <h1>文章列表</h1>
            <ul>
                {articles.map(article => (
                    <li key={article._id}>
                        <h2>{article.title}</h2>
                        <p>{article.summary}</p>
                        <p>{new Date(article.created_at).toLocaleDateString()}</p>
                        <a href={`/articles/${article._id}`}>查看详情</a>
                    </li>
                ))}
            </ul>
        </div>
    );
}

export default ArticleList;

文章详情页

文章详情页将展示单篇文章的详细内容,包括标题、内容和发布时间。我们同样使用React组件来实现这个功能。

import React, { useEffect, useState } from 'react';
import axios from 'axios';

function ArticleDetail({ id }) {
    const [article, setArticle] = useState(null);

    useEffect(() => {
        fetchArticle(id);
    }, [id]);

    const fetchArticle = async (id) => {
        const response = await axios.get(`/api/articles/${id}`);
        setArticle(response.data);
    };

    return (
        <div>
            {article ? (
                <div>
                    <h1>{article.title}</h1>
                    <p>{article.content}</p>
                    <p>{new Date(article.created_at).toLocaleDateString()}</p>
                </div>
            ) : (
                <p>加载中...</p>
            )}
        </div>
    );
}

export default ArticleDetail;

文章管理后台

文章管理后台用于管理员添加、编辑和删除文章。我们将使用React表单组件来实现这个功能。

import React, { useState } from 'react';
import axios from 'axios';

function ArticleForm({ id, onSubmit }) {
    const [title, setTitle] = useState('');
    const [content, setContent] = useState('');
    const [summary, setSummary] = useState('');
    const [created_at, setCreated_at] = useState(new Date().toISOString());

    const handleSubmit = async (e) => {
        e.preventDefault();
        await onSubmit({ title, content, summary, created_at });
        setTitle('');
        setContent('');
        setSummary('');
        setCreated_at(new Date().toISOString());
    };

    return (
        <form onSubmit={handleSubmit}>
            <label>
                标题:
                <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
            </label>
            <label>
                内容:
                <textarea value={content} onChange={(e) => setContent(e.target.value)} />
            </label>
            <label>
                摘要:
                <input type="text" value={summary} onChange={(e) => setSummary(e.target.value)} />
            </label>
            <label>
                创建时间:
                <input type="datetime-local" value={created_at} onChange={(e) => setCreated_at(e.target.value)} />
            </label>
            <button type="submit">保存</button>
        </form>
    );
}

export default ArticleForm;
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import ArticleForm from './ArticleForm';

function ArticleEdit() {
    const { id } = useParams();
    const [article, setArticle] = useState(null);

    useEffect(() => {
        fetchArticle(id);
    }, [id]);

    const fetchArticle = async (id) => {
        const response = await axios.get(`/api/articles/${id}`);
        setArticle(response.data);
    };

    const handleSubmit = async (articleData) => {
        if (id) {
            await axios.put(`/api/articles/${id}`, articleData);
        } else {
            await axios.post('/api/articles', articleData);
        }
    };

    return (
        <div>
            {article ? (
                <ArticleForm id={id} onSubmit={handleSubmit} />
            ) : (
                <p>加载中...</p>
            )}
        </div>
    );
}

export default ArticleEdit;
实现功能(如文章列表与详情页)

文章列表页实现

import React, { useEffect, useState } from 'react';
import axios from 'axios';

function ArticleList() {
    const [articles, setArticles] = useState([]);

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

    const fetchArticles = async () => {
        const response = await axios.get('/api/articles');
        setArticles(response.data);
    };

    return (
        <div>
            <h1>文章列表</h1>
            <ul>
                {articles.map(article => (
                    <li key={article._id}>
                        <h2>{article.title}</h2>
                        <p>{article.summary}</p>
                        <p>{new Date(article.created_at).toLocaleDateString()}</p>
                        <a href={`/articles/${article._id}`}>查看详情</a>
                    </li>
                ))}
            </ul>
        </div>
    );
}

export default ArticleList;

文章详情页实现

import React, { useEffect, useState } from 'react';
import axios from 'axios';

function ArticleDetail({ id }) {
    const [article, setArticle] = useState(null);

    useEffect(() => {
        fetchArticle(id);
    }, [id]);

    const fetchArticle = async (id) => {
        const response = await axios.get(`/api/articles/${id}`);
        setArticle(response.data);
    };

    return (
        <div>
            {article ? (
                <div>
                    <h1>{article.title}</h1>
                    <p>{article.content}</p>
                    <p>{new Date(article.created_at).toLocaleDateString()}</p>
                </div>
            ) : (
                <p>加载中...</p>
            )}
        </div>
    );
}

export default ArticleDetail;

文章管理后台实现

import React, { useState } from 'react';
import axios from 'axios';

function ArticleForm({ id, onSubmit }) {
    const [title, setTitle] = useState('');
    const [content, setContent] = useState('');
    const [summary, setSummary] = useState('');
    const [created_at, setCreated_at] = useState(new Date().toISOString());

    const handleSubmit = async (e) => {
        e.preventDefault();
        await onSubmit({ title, content, summary, created_at });
        setTitle('');
        setContent('');
        setSummary('');
        setCreated_at(new Date().toISOString());
    };

    return (
        <form onSubmit={handleSubmit}>
            <label>
                标题:
                <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} />
            </label>
            <label>
                内容:
                <textarea value={content} onChange={(e) => setContent(e.target.value)} />
            </label>
            <label>
                摘要:
                <input type="text" value={summary} onChange={(e) => setSummary(e.target.value)} />
            </label>
            <label>
                创建时间:
                <input type="datetime-local" value={created_at} onChange={(e) => setCreated_at(e.target.value)} />
            </label>
            <button type="submit">保存</button>
        </form>
    );
}

export default ArticleForm;
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import ArticleForm from './ArticleForm';

function ArticleEdit() {
    const { id } = useParams();
    const [article, setArticle] = useState(null);

    useEffect(() => {
        fetchArticle(id);
    }, [id]);

    const fetchArticle = async (id) => {
        const response = await axios.get(`/api/articles/${id}`);
        setArticle(response.data);
    };

    const handleSubmit = async (articleData) => {
        if (id) {
            await axios.put(`/api/articles/${id}`, articleData);
        } else {
            await axios.post('/api/articles', articleData);
        }
    };

    return (
        <div>
            {article ? (
                <ArticleForm id={id} onSubmit={handleSubmit} />
            ) : (
                <p>加载中...</p>
            )}
        </div>
    );
}

export default ArticleEdit;

通过上述代码实现,你已经构建了一个简单的个人博客系统,包括文章列表页、文章详情页和文章管理后台。

项目上线与部署

在完成前端开发后,下一步是将项目部署到线上服务器。本节将介绍如何使用GitHub或GitLab托管代码,部署到线上服务器,以及使用CDN来加快静态资源加载速度。

使用GitHub或GitLab托管代码

创建仓库

  1. 登录GitHub或GitLab(如果尚未注册,请先注册账号)。
  2. 创建新仓库:选择“新建仓库”。
  3. 初始化仓库:选择“初始化仓库”。

推送代码

  1. 将本地代码添加到Git仓库

    git init
    git add .
    git commit -m "Initial commit"
  2. 关联远程仓库

    git remote add origin https://github.com/yourusername/your-repo.git
    git push -u origin master
部署到线上服务器

准备服务器

你需要一个可以运行Node.js和Express的服务器。这里以Ubuntu服务器为例。

  1. 安装Node.js和npm

    curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
    sudo apt-get install -y nodejs
  2. 安装其他依赖
    sudo apt-get install -y build-essential

构建和部署项目

  1. 克隆仓库到服务器

    git clone https://github.com/yourusername/your-repo.git
    cd your-repo
  2. 安装项目依赖

    npm install
  3. 构建前端代码

    npm run build
  4. 启动应用
    npm start

配置环境变量

你需要配置环境变量来连接MongoDB数据库。

export MONGO_URI=mongodb://localhost:27017/your-database
export PORT=3000
export NODE_ENV=production

使用PM2管理进程

使用PM2来管理应用进程,确保应用在服务器重启后可以自动启动。

npm install pm2 -g
pm2 start npm --name "your-app" -- start
pm2 save
pm2 startup
pm2 start ecosystem.config.js
使用CDN加快静态资源加载速度

配置CDN

使用CDN可以加快静态资源的加载速度。你可以将项目中的静态文件(如图片、CSS和JavaScript文件)上传到CDN,然后在HTML中引用这些文件。

  1. 注册CDN服务:选择一个CDN服务提供商(如阿里云CDN、腾讯云CDN)。
  2. 上传静态文件:将项目中的静态文件上传到CDN服务提供商的控制台。
  3. 修改引用路径:在HTML中修改静态文件的引用路径,使用CDN提供的域名。
<link rel="stylesheet" href="https://your-cdn-domain/styles.css">
<script src="https://your-cdn-domain/scripts.js"></script>
<img src="https://your-cdn-domain/images/example.jpg" alt="示例图像">

通过上述步骤,你已经完成了一个前端项目的部署和上线。你可以访问服务器的公网IP地址来查看你的项目是否正常运行。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP