Vue3 学习教程,从入门到精通,基于 Vue3 + Element Plus + ECharts + JavaScript 开发图片素材库网站(46)
基于 Vue3 + Element Plus + ECharts + JavaScript 开发图片素材库网站
单元导学
本单元将指导你如何使用 Vue3、Element Plus、ECharts 和 JavaScript 开发一个功能完善的图片素材库网站。通过本单元的学习,你将掌握前端和后端的基本开发流程,理解项目设计、功能模块的实现思路,并了解项目工程化规范。
学习目标
- 掌握 Vue3 的基本用法和组件化开发
- 熟悉 Element Plus 组件库的使用
- 学会使用 ECharts 进行数据可视化
- 理解前后端分离的开发模式
- 掌握 Express 框架的基本用法
- 学会使用 Axios 进行数据请求
- 了解项目工程化规范和代码管理
项目设计
-
需求分析
- 用户可以浏览、搜索、下载图片素材
- 用户可以上传、分享自己的图片素材
- 用户可以登录、注册,管理个人信息
- 管理员可以管理图片素材和用户
-
功能模块
- 网站首页:展示热门图片、推荐图片、分类导航
- 用户登录/注册:用户身份验证
- 图片展示与操作:图片列表展示、详情查看、下载、收藏
- 图片分享:用户上传、分享图片
- 后台管理:图片管理、用户管理
项目实现思路
-
前端开发
- 使用 Vue3 进行组件化开发
- 使用 Element Plus 提供 UI 组件
- 使用 ECharts 进行数据可视化展示(如用户访问量统计)
- 使用 Axios 进行数据请求
- 使用 Vue Router 进行路由管理
- 使用 Vuex 进行状态管理
-
后端开发
- 使用 Express 框架搭建服务器
- 使用 MongoDB 数据库存储用户和图片数据
- 实现用户认证和授权(JWT)
- 提供 RESTful API 接口供前端调用
-
前后端交互
- 前端通过 Axios 调用后端 API 进行数据交互
- 后端处理请求,返回数据给前端
项目工程化规范
-
代码规范
- 使用 ESLint 进行代码风格检查
- 使用 Prettier 进行代码格式化
-
版本控制
- 使用 Git 进行版本控制
- 使用 GitHub 进行代码托管
-
构建工具
- 使用 Vite 作为构建工具
- 使用 Webpack 进行打包优化
-
测试
- 使用 Jest 进行单元测试
- 使用 Cypress 进行端到端测试
前端项目——构建项目
-
创建 Vue 工程
npm init vite@latest image-library -- --template vue cd image-library npm install
-
配置路由
npm install vue-router@4
在
src/router/index.js
中配置路由 -
配置 Vuex
npm install vuex@4
在
src/store/index.js
中配置 Vuex -
配置 Axios
npm install axios
在
src/utils/request.js
中配置 Axios -
项目入口
在src/main.js
中引入路由和 Vuex
前端项目——公共组件
- Header 组件:网站头部导航
- Footer 组件:网站底部信息
- Sidebar 组件:侧边栏导航
- Pagination 组件:分页组件
- Loading 组件:加载动画
前端项目——网站首页
-
整体布局
- 使用 Element Plus 的布局组件进行页面布局
- 包含 Header、Footer、Sidebar 和主要内容区域
-
轮播图
- 使用 Element Plus 的 Carousel 组件
- 展示热门图片或推荐图片
<template><el-carousel :interval="4000" arrow="always"><el-carousel-item v-for="item in bannerList" :key="item.id"><img :src="item.imageUrl" alt="" /></el-carousel-item></el-carousel> </template><script> export default {data() {return {bannerList: []}},mounted() {this.getBannerList()},methods: {getBannerList() {// 调用后端 API 获取轮播图数据}} } </script>
前端项目——用户登录
- 使用 Element Plus 的 Form 组件创建登录表单
- 使用 Axios 发送登录请求
- 使用 Vuex 管理用户状态
前端项目——图片展示与操作
- 使用 Element Plus 的 Grid 组件展示图片列表
- 使用 ECharts 展示图片访问量统计
- 实现图片详情查看、下载、收藏等功能
前端项目——图片分享
- 使用 Element Plus 的 Upload 组件实现图片上传
- 实现图片描述填写、分类选择等功能
- 使用 Axios 发送上传请求
后端项目——构建项目
-
认识 Express 框架
- 学习 Express 的基本用法
- 了解中间件的概念
-
搭建后端项目
mkdir backend cd backend npm init -y npm install express mongoose cors
后端项目——用户登录合法性验证
- 实现用户注册、登录接口
- 使用 JWT 进行身份验证
- 保护需要授权的 API 接口
单元小结
通过本单元的学习,你将能够:
- 搭建一个基于 Vue3 和 Element Plus 的前端项目
- 搭建一个基于 Express 的后端项目
- 实现用户登录、图片展示与操作、图片分享等基本功能
- 了解项目工程化规范和代码管理
前端项目——深入实现细节
1. 网站首页
1.1 整体布局
- Header 组件:包含网站logo、导航菜单、搜索栏和用户登录/注册入口。
- Sidebar 组件:包含分类导航、热门标签等。
- Main 区域:展示轮播图、热门图片、最新上传等。
- Footer 组件:包含版权信息、联系方式等。
关键代码示例:
<template><el-container><el-header><Header /></el-header><el-container><el-aside width="200px"><Sidebar /></el-aside><el-main><el-carousel :interval="4000" arrow="always"><el-carousel-item v-for="item in bannerList" :key="item.id"><img :src="item.imageUrl" alt="" /></el-carousel-item></el-carousel><div class="image-list"><el-row :gutter="20"><el-col :span="6" v-for="item in imageList" :key="item.id"><el-card :body-style="{ padding: '10px' }"><img :src="item.thumbnail" class="image" @click="goToDetail(item.id)" /><div style="padding: 14px;"><span>{{ item.title }}</span><div class="bottom clearfix"><time class="time">{{ item.uploadTime }}</time><el-button type="text" class="button" @click="downloadImage(item.id)">下载</el-button></div></div></el-card></el-col></el-row></div></el-main></el-container><el-footer><Footer /></el-footer></el-container>
</template><script>
import Header from '@/components/Header.vue'
import Sidebar from '@/components/Sidebar.vue'
import Footer from '@/components/Footer.vue'
import axios from '@/utils/request'export default {components: {Header,Sidebar,Footer},data() {return {bannerList: [],imageList: []}},mounted() {this.getBannerList()this.getImageList()},methods: {getBannerList() {axios.get('/api/banner').then(response => {this.bannerList = response.data})},getImageList() {axios.get('/api/images').then(response => {this.imageList = response.data})},goToDetail(id) {this.$router.push(`/image/${id}`)},downloadImage(id) {axios.get(`/api/images/${id}/download`, { responseType: 'blob' }).then(response => {const url = window.URL.createObjectURL(new Blob([response.data]))const link = document.createElement('a')link.href = urllink.setAttribute('download', 'image.jpg') // 动态获取文件名document.body.appendChild(link)link.click()})}}
}
</script><style>
.image {width: 100%;height: 200px;object-fit: cover;
}
.bottom {margin-top: 13px;line-height: 12px;
}
.button {padding: 0;float: right;
}
</style>
2. 用户登录
2.1 登录表单
- 使用 Element Plus 的 Form 组件创建登录表单,包括用户名和密码输入框。
- 使用 Vuex 管理用户状态。
关键代码示例:
<template><el-form :model="loginForm" @submit.prevent="handleLogin"><el-form-item label="用户名"><el-input v-model="loginForm.username"></el-input></el-form-item><el-form-item label="密码"><el-input type="password" v-model="loginForm.password"></el-input></el-form-item><el-form-item><el-button type="primary" @click="handleLogin">登录</el-button></el-form-item></el-form>
</template><script>
import { mapActions } from 'vuex'
import axios from '@/utils/request'export default {data() {return {loginForm: {username: '',password: ''}}},methods: {...mapActions(['login']),handleLogin() {axios.post('/api/login', this.loginForm).then(response => {this.login(response.data.token)this.$router.push('/')}).catch(error => {this.$message.error('登录失败')})}}
}
</script>
3. 图片展示与操作
3.1 图片列表
- 使用 Element Plus 的 Grid 组件展示图片列表。
- 实现图片详情查看、下载、收藏等功能。
关键代码示例:
<template><div class="image-list"><el-row :gutter="20"><el-col :span="6" v-for="item in imageList" :key="item.id"><el-card :body-style="{ padding: '10px' }"><img :src="item.thumbnail" class="image" @click="goToDetail(item.id)" /><div style="padding: 14px;"><span>{{ item.title }}</span><div class="bottom clearfix"><time class="time">{{ item.uploadTime }}</time><el-button type="text" class="button" @click="downloadImage(item.id)">下载</el-button><el-button type="text" class="button" @click="collectImage(item.id)">收藏</el-button></div></div></el-card></el-col></el-row></div>
</template><script>
import axios from '@/utils/request'export default {data() {return {imageList: []}},mounted() {this.getImageList()},methods: {getImageList() {axios.get('/api/images').then(response => {this.imageList = response.data})},goToDetail(id) {this.$router.push(`/image/${id}`)},downloadImage(id) {axios.get(`/api/images/${id}/download`, { responseType: 'blob' }).then(response => {const url = window.URL.createObjectURL(new Blob([response.data]))const link = document.createElement('a')link.href = urllink.setAttribute('download', 'image.jpg') // 动态获取文件名document.body.appendChild(link)link.click()})},collectImage(id) {axios.post(`/api/images/${id}/collect`).then(response => {this.$message.success('收藏成功')}).catch(error => {this.$message.error('收藏失败')}}}
}
</script><style>
.image {width: 100%;height: 200px;object-fit: cover;
}
.bottom {margin-top: 13px;line-height: 12px;
}
.button {padding: 0;float: right;
}
</style>
4. 图片分享
4.1 上传图片
- 使用 Element Plus 的 Upload 组件实现图片上传。
- 上传成功后,将图片信息发送到后端。
关键代码示例:
<template><el-uploadclass="upload-demo"action="/api/images/upload":on-success="handleSuccess":on-error="handleError":before-upload="beforeUpload"multiple><el-button type="primary">点击上传</el-button></el-upload>
</template><script>
import axios from '@/utils/request'export default {methods: {beforeUpload(file) {const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'const isLt2M = file.size / 1024 / 1024 < 2if (!isJPG) {this.$message.error('上传图片只能是 JPG 或 PNG 格式!')}if (!isLt2M) {this.$message.error('上传图片大小不能超过 2MB!')}return isJPG && isLt2M},handleSuccess(response, file, fileList) {this.$message.success('上传成功')},handleError(err, file, fileList) {this.$message.error('上传失败')}}
}
</script>
后端项目——深入实现细节
1. 用户登录合法性验证
1.1 用户注册
- 使用 Mongoose 创建用户模型。
- 实现用户注册接口,密码使用 bcrypt 进行加密。
关键代码示例:
const express = require('express')
const mongoose = require('mongoose')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
const router = express.Router()const User = mongoose.model('User', new mongoose.Schema({username: { type: String, unique: true },password: String,// 其他用户信息
}))router.post('/register', async (req, res) => {const { username, password } = req.bodyconst hashedPassword = await bcrypt.hash(password, 10)try {const user = new User({ username, password: hashedPassword })await user.save()res.status(201).send('用户注册成功')} catch (error) {res.status(400).send('用户注册失败')}
})module.exports = router
1.2 用户登录
- 实现用户登录接口,验证用户名和密码。
- 生成 JWT token 并返回给前端。
关键代码示例:
router.post('/login', async (req, res) => {const { username, password } = req.bodyconst user = await User.findOne({ username })if (!user) {return res.status(400).send('用户不存在')}const isMatch = await bcrypt.compare(password, user.password)if (!isMatch) {return res.status(400).send('密码错误')}const token = jwt.sign({ id: user._id }, 'secret', { expiresIn: '1h' })res.send({ token })
})
1.3 身份验证中间件
- 实现身份验证中间件,保护需要授权的 API 接口。
关键代码示例:
const auth = (req, res, next) => {const token = req.header('Authorization')if (!token) {return res.status(401).send('没有权限')}try {const decoded = jwt.verify(token, 'secret')req.user = decodednext()} catch (error) {res.status(401).send('Token 无效')}
}
2. 图片上传与下载
2.1 图片上传
- 实现图片上传接口,保存图片到服务器。
- 将图片信息存储到数据库。
关键代码示例:
const fs = require('fs')
const path = require('path')router.post('/upload', auth, (req, res) => {const file = req.files.fileconst uploadPath = path.join(__dirname, '../public/images', file.name)file.mv(uploadPath, (err) => {if (err) {return res.status(500).send('上传失败')}const image = new Image({title: req.body.title,description: req.body.description,filename: file.name,uploadTime: new Date()})image.save()res.status(201).send('上传成功')})
})
2.2 图片下载
- 实现图片下载接口,提供图片下载链接。
关键代码示例:
router.get('/images/:id/download', auth, async (req, res) => {const image = await Image.findById(req.params.id)const filePath = path.join(__dirname, '../public/images', image.filename)res.sendFile(filePath)
})
3. 图片展示与操作
3.1 图片列表
- 实现图片列表接口,返回图片信息。
关键代码示例:
router.get('/images', auth, async (req, res) => {const images = await Image.find()res.send(images)
})
3.2 图片收藏
- 实现图片收藏接口,更新用户收藏信息。
关键代码示例:
router.post('/images/:id/collect', auth, async (req, res) => {const user = await User.findById(req.user.id)user.favorites.push(req.params.id)await user.save()res.send('收藏成功')
})
总结
通过以上深入的实现细节,你已经了解了如何在前端和后端实现各个功能模块。接下来,你可以根据具体需求,进一步优化和扩展这些功能,例如:
-
前端优化:
- 使用 Vue Router 的懒加载功能,提升页面加载速度。
- 使用 Vuex 的模块化管理状态。
- 使用 Element Plus 的更多组件,丰富页面功能。
-
后端优化:
- 使用 Redis 缓存,提高 API 响应速度。
- 实现分页查询,优化数据库查询性能。
- 使用 Nginx 作为反向代理服务器,提升服务器性能。
-
安全性:
- 实现更完善的权限控制。
- 使用 HTTPS 加密通信。
- 防止常见的 Web 攻击,如 SQL 注入、XSS 等。