如何用Node.js、Express、EJS在首页分区域展示分类博客文章?
Hey there! Let's walk through exactly how to get your blog homepage displaying categorized articles (like sports, fashion, news) just like The New Yorker's homepage. You've picked a solid tech stack, so we'll focus on wiring up data fetching and view rendering to make this work.
Step 1: Update Your Mongoose Article Model
First, make sure your Article schema includes a category field to tag each post. This is how we'll filter posts later.
// models/Article.js const mongoose = require('mongoose'); const articleSchema = new mongoose.Schema({ title: { type: String, required: true }, excerpt: { type: String, required: true }, content: { type: String, required: true }, category: { type: String, required: true, enum: ['sports', 'fashion', 'news', 'culture'] // Limit to your desired categories }, createdAt: { type: Date, default: Date.now } }); module.exports = mongoose.model('Article', articleSchema);
Step 2: Fetch Categorized Data in Your Express Route
Instead of fetching all articles at once, we'll fetch posts for each category separately (using Promise.all to do this efficiently) and pass them to your EJS view.
// routes/index.js const express = require('express'); const router = express.Router(); const Article = require('../models/Article'); router.get('/', async (req, res) => { try { // Fetch articles for each category in parallel const [sportsArticles, fashionArticles, newsArticles] = await Promise.all([ Article.find({ category: 'sports' }).sort({ createdAt: -1 }).limit(5), // Get latest 5 sports posts Article.find({ category: 'fashion' }).sort({ createdAt: -1 }).limit(5), Article.find({ category: 'news' }).sort({ createdAt: -1 }).limit(5) ]); // Pass all categorized data to the EJS template res.render('index', { sportsArticles, fashionArticles, newsArticles }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); module.exports = router;
Step 3: Render Categorized Sections in EJS
Now in your EJS view, create separate sections for each category and loop through the corresponding article array to display posts. You can structure this to match The New Yorker's layout (e.g., a main news section, side sports/fashion blocks).
<!-- views/index.ejs --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Blog</title> <!-- Add your CSS here to style like The New Yorker --> </head> <body> <header> <h1>My Blog</h1> </header> <!-- News Section (Main Feature) --> <section class="news-section"> <h2>Latest News</h2> <% if (newsArticles.length > 0) { %> <% newsArticles.forEach(article => { %> <article> <h3><%= article.title %></h3> <p><%= article.excerpt %></p> <small>Posted on <%= article.createdAt.toLocaleDateString() %></small> <a href="/articles/<%= article._id %>">Read More</a> </article> <% }) %> <% } else { %> <p>No news articles to display yet.</p> <% } %> </section> <!-- Sports Section --> <section class="sports-section"> <h2>Sports Updates</h2> <% if (sportsArticles.length > 0) { %> <% sportsArticles.forEach(article => { %> <article> <h3><%= article.title %></h3> <p><%= article.excerpt %></p> <small>Posted on <%= article.createdAt.toLocaleDateString() %></small> <a href="/articles/<%= article._id %>">Read More</a> </article> <% }) %> <% } else { %> <p>No sports articles to display yet.</p> <% } %> </section> <!-- Fashion Section --> <section class="fashion-section"> <h2>Fashion Trends</h2> <% if (fashionArticles.length > 0) { %> <% fashionArticles.forEach(article => { %> <article> <h3><%= article.title %></h3> <p><%= article.excerpt %></p> <small>Posted on <%= article.createdAt.toLocaleDateString() %></small> <a href="/articles/<%= article._id %>">Read More</a> </article> <% }) %> <% } else { %> <p>No fashion articles to display yet.</p> <% } %> </section> </body> </html>
Pro Tips to Polish Things Up
- Reusable Components: If you find yourself repeating the article loop code, create an EJS partial (like
partials/article-card.ejs) and include it with<%- include('partials/article-card', { article: article }) %>to keep your code DRY. - Dynamic Categories: If you plan to add more categories later, store your category list in a config file (e.g.,
config/categories.js) and loop through that to fetch and render sections automatically—no need to hardcode each category in your route and view. - Styling: Use CSS grid or flexbox to replicate The New Yorker's layout (main content column, smaller side columns for other categories).
内容的提问来源于stack exchange,提问作者AustinTNM

