Bootstrap

Vue 实现的商品评价系统:从标签筛选到图片展示,带你全面掌握前端开发 手把手教你用 Vue 创建商品评价功能,轻松实现多功能评论列表 新手友好:Vue + HTML 构建商品评价页面的完整指南 项目

效果图

在这里插入图片描述

目录
  1. 引言:项目概述
  2. 搭建 Vue 环境
  3. 步骤一:创建基础 HTML 和 CSS 结构
  4. 步骤二:设计数据结构和添加假数据
  5. 步骤三:实现标签和评价过滤功能
  6. 步骤四:展示带图片和追评的评论
  7. 步骤五:实现点赞和举报功能
  8. 总结

引言:项目概述

在本教程中,我们将使用 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 中添加 selectTagapplyFilter 函数,并在 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>
步骤五:实现点赞和举报功能

添加 likeCommentreportComment 方法,以实现点赞和举报功能。使用 @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 开发的信心!

;