效果图
目录
引言:项目概述
在本教程中,我们将使用 Vue 构建一个商品评价系统,涵盖评价标签、筛选、带图片的评价、追评显示以及点赞和举报功能。该项目适合前端初学者进行实战练习,帮助你了解 Vue 的基本使用和数据绑定。
搭建 Vue 环境
在开始编码之前,确保你的 HTML 文件中引入了 Vue 的 CDN 资源。可以通过以下代码直接引入 Vue 2:
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
步骤一:创建基础 HTML 和 CSS 结构
首先,我们需要设计页面的基本结构,包括评价标题、标签筛选器、标签选择区域和评论列表。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>商品评价 - Vue 实现</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f9f9f9;
margin: 0;
padding: 20px;
}
#app {
max-width: 800px;
margin: auto;
background-color: #fff;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* 评价标题和标签样式 */
.header, .tag-container, .filter-container, .comment-list, .comment {
margin-bottom: 20px;
}
.rating-summary, .rating-percentage, .tag, .filter-tag, .comment-footer {
color: #ff4d4f;
}
</style>
</head>
<body>
<div id="app">
<!-- 评价率展示 -->
<div class="header">
<span class="rating-summary">好评率</span>
<span class="rating-percentage">96%</span>
</div>
<!-- 评论标签选择 -->
<div class="tag-container">
<span class="tag" v-for="tag in tags">{{ tag }}</span>
</div>
<!-- 评论列表(后续填充) -->
<div class="comment-list"></div>
</div>
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
</body>
</html>
在 .tag-container
和 .comment-list
中,我们将分别填充标签和评论内容。这个基础结构为我们后续动态添加内容打下了基础。
步骤二:设计数据结构和添加假数据
在 Vue 实例的 data
中,定义标签数组、筛选词数组、评论数组。每条评论包括评分、用户名称、文字内容、图片、日期等信息。
<script>
new Vue({
el: '#app',
data: {
tags: ['全部评价', '晒图(11)', '追评(3)', '好评(3200+)', '中评(80+)', '差评(40+)'],
filterTags: ['很不错', '性价比高', '物流快', '包装好'],
comments: [
{ id: 1, username: '用户1', rating: 5, text: '很不错,买值了。', date: '2024-10-29', source: '山东', likes: 0, dislikes: 0, images: [], additionalComment: null },
{ id: 2, username: '用户2', rating: 5, text: '物超所值', date: '2024-10-28', source: '内蒙古', likes: 0, dislikes: 0, images: ['https://via.placeholder.com/60'], additionalComment: '使用后效果更好' }
]
}
});
</script>
步骤三:实现标签和评价过滤功能
我们可以通过点击标签来过滤评论。在 methods
中添加 selectTag
和 applyFilter
函数,并在 computed
属性中实现 filteredComments
,根据所选标签和词语进行筛选。
methods: {
selectTag(tag) {
this.activeTag = tag;
},
applyFilter(filter) {
this.activeFilter = filter === this.activeFilter ? null : filter;
}
},
computed: {
filteredComments() {
let comments = this.comments;
if (this.activeTag === '好评(3200+)') comments = comments.filter(c => c.rating >= 4);
if (this.activeFilter) comments = comments.filter(c => c.text.includes(this.activeFilter));
return comments;
}
}
步骤四:展示带图片和追评的评论
使用 v-if
条件判断来实现是否显示评论图片和追评内容。v-for
指令用于循环展示图片。
<div class="comment-images" v-if="comment.images && comment.images.length">
<img v-for="image in comment.images" :src="image">
</div>
<div class="additional-comment" v-if="comment.additionalComment">
<strong>追评:</strong> {{ comment.additionalComment }}
</div>
步骤五:实现点赞和举报功能
添加 likeComment
和 reportComment
方法,以实现点赞和举报功能。使用 @click
绑定这些方法到按钮。
methods: {
likeComment(id) {
const comment = this.comments.find(c => c.id === id);
comment.likes++;
},
reportComment(id) {
alert(`举报评论ID: ${id}`);
}
}
在 HTML 中调用这些方法:
<div class="action-buttons">
<button @click="likeComment(comment.id)">👍 {{ comment.likes }}</button>
<button @click="reportComment(comment.id)">举报</button>
</div>
完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>商品评价 - Vue 实现</title>
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f9f9f9;
margin: 0;
padding: 20px;
}
#app {
max-width: 800px;
margin: auto;
background-color: #fff;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.header {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.rating-summary {
font-size: 24px;
color: #ff4d4f;
font-weight: bold;
margin-right: 10px;
}
.rating-percentage {
font-size: 24px;
color: #ff4d4f;
margin-right: 10px;
}
.tag-container, .filter-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.tag, .filter-tag {
padding: 5px 10px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
}
.tag.active, .filter-tag.active {
background-color: #ff4d4f;
color: #fff;
border-color: #ff4d4f;
}
.comment-list {
margin-top: 20px;
}
.comment {
display: flex;
margin-bottom: 20px;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.comment img {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 10px;
}
.comment-content {
flex: 1;
}
.username {
font-weight: bold;
margin-right: 5px;
}
.rating {
color: #f5a623;
}
.rating span {
font-size: 18px;
}
.comment-text {
margin: 10px 0;
}
.comment-footer {
font-size: 12px;
color: #999;
}
.action-buttons {
display: flex;
align-items: center;
gap: 5px;
}
.action-buttons button {
background: none;
border: none;
color: #666;
cursor: pointer;
}
.comment-images img {
width: 60px;
height: 60px;
margin-right: 5px;
border-radius: 4px;
cursor: pointer;
}
.additional-comment {
font-size: 14px;
color: #666;
margin-top: 5px;
padding-left: 60px;
}
</style>
</head>
<body>
<div id="app">
<div class="header">
<span class="rating-summary">好评率</span>
<span class="rating-percentage">96%</span>
</div>
<!-- 评价标签过滤器 -->
<div class="filter-container">
<span
class="filter-tag"
:class="{ active: activeFilter === filter }"
v-for="filter in filterTags"
@click="applyFilter(filter)">
{{ filter }}
</span>
</div>
<!-- 评论标签选择 -->
<div class="tag-container">
<span class="tag" :class="{ active: activeTag === tag }" v-for="tag in tags" @click="selectTag(tag)">
{{ tag }}
</span>
</div>
<!-- 评论列表 -->
<div class="comment-list">
<div class="comment" v-for="comment in filteredComments" :key="comment.id">
<img src="https://via.placeholder.com/50" alt="用户头像">
<div class="comment-content">
<div>
<span class="username">{{ comment.username }}</span>
<span class="rating">
<span v-for="n in comment.rating">★</span>
</span>
</div>
<div class="comment-text">{{ comment.text }}</div>
<!-- 评论图片展示 -->
<div v-if="comment.images && comment.images.length" class="comment-images">
<img v-for="image in comment.images" :src="image" :alt="`Image ${comment.id}`">
</div>
<!-- 追评 -->
<div v-if="comment.additionalComment" class="additional-comment">
<strong>追评:</strong> {{ comment.additionalComment }}
</div>
<div class="comment-footer">
<span>{{ comment.date }}</span> | <span>{{ comment.source }}</span>
<div class="action-buttons">
<button @click="reportComment(comment.id)">举报</button>
<button @click="likeComment(comment.id)">👍 {{ comment.likes }}</button>
<button @click="dislikeComment(comment.id)">👎 {{ comment.dislikes }}</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
activeTag: '全部评价',
activeFilter: null,
tags: ['全部评价', '晒图(11)', '追评(3)', '好评(3200+)', '中评(80+)', '差评(40+)'],
filterTags: ['很不错', '性价比高', '物流快', '包装好'],
comments: [
{ id: 1, username: '用户1', rating: 5, text: '很不错,买值了,以为是泡泡的。', date: '2024-10-29', source: '山东', likes: 0, dislikes: 0, images: [], additionalComment: null },
{ id: 2, username: '用户2', rating: 5, text: '物超所值,连不多说,这个冬天已经说明了一切', date: '2024-10-28', source: '内蒙古', likes: 0, dislikes: 0, images: ['https://via.placeholder.com/60'], additionalComment: '使用后效果更好' },
{ id: 3, username: '用户3', rating: 4, text: '有点贵了,很不错,不大会觉得荒谬。', date: '2024-10-28', source: '辽宁', likes: 0, dislikes: 0, images: [], additionalComment: null },
{ id: 4, username: '用户4', rating: 4, text: '很好用干净,他也优雅。包装好', date: '2024-10-28', source: '新疆', likes: 0, dislikes: 0, images: ['https://via.placeholder.com/60', 'https://via.placeholder.com/60'], additionalComment: null },
{ id: 5, username: '用户5', rating: 5, text: '快递非常快,东西很好。', date: '2024-10-28', source: '江西', likes: 0, dislikes: 0, images: [], additionalComment: '再次购买,非常满意' },
{ id: 6, username: '用户6', rating: 2, text: '看起来很不错,但是不推荐购买,使用后效果不理想', date: '2024-10-27', source: '安徽', likes: 0, dislikes: 0, images: ['https://via.placeholder.com/60'], additionalComment: null }
]
},
computed: {
filteredComments() {
let comments = this.comments;
// 按标签过滤
if (this.activeTag !== '全部评价') {
if (this.activeTag === '晒图(11)') comments = comments.filter(c => c.images && c.images.length);
if (this.activeTag === '追评(3)') comments = comments.filter(c => c.additionalComment);
if (this.activeTag === '好评(3200+)') comments = comments.filter(c => c.rating >= 4);
if (this.activeTag === '中评(80+)') comments = comments.filter(c => c.rating === 3);
if (this.activeTag === '差评(40+)') comments = comments.filter(c => c.rating < 3);
}
// 按词语过滤
if (this.activeFilter) {
comments = comments.filter(c => c.text.includes(this.activeFilter));
}
return comments;
}
},
methods: {
selectTag(tag) {
this.activeTag = tag;
},
applyFilter(filter) {
this.activeFilter = filter === this.activeFilter ? null : filter;
},
reportComment(id) {
alert(`举报评论ID: ${id}`);
},
likeComment(id) {
const comment = this.comments.find(c => c.id === id);
comment.likes++;
},
dislikeComment(id) {
const comment = this.comments.find(c => c.id === id);
comment.dislikes++;
}
}
});
</script>
</body>
</html>
总结
本教程带领你一步步构建了一个商品评价系统,通过 Vue 实现标签筛选、评论过滤、图片和追评展示、点赞和举报功能。通过本项目,你可以了解如何在实际项目中运用 Vue 的数据绑定和条件渲染。希望这篇文章对你有所帮助,进一步增强了你对 Vue 开发的信心!