vue评论功能项目

160 阅读6分钟

实现一个评论列表:展示已发表的评论和评论人

实现用户发表评论功能:包含评论人,评论内容和发表评论按钮

实现评论列表实时更新,用localstorage进行存储和获取,获取到的数据使列表数据更新

实现防误触功能的发表评论按钮

功能展示

<template>
  <div class="container">
    <!-- 评论区容器 -->
    <div class="message-board">
      <!-- 评论区表单部分 -->
      <div class="box1">
        <!-- 评论区标题 -->
        <h1 class="h1">评论区</h1>
        <!-- 昵称输入框,使用v-model实现双向数据绑定 -->
        <input class="username-input" type="text" placeholder="请输入您的昵称" v-model="currentUsername">
        <!-- 评论内容输入框,使用v-model实现双向数据绑定 -->
        <textarea class="textbox" v-model="currentComment" placeholder="请输入评论内容"></textarea>
        <!-- 发表评论按钮容器 -->
        <div class="box2">
          <!-- 发表评论按钮,点击时触发confirmComment方法,按钮是否禁用取决于isButtonDisabled的值 -->
          <button @click="confirmComment" :disabled="isButtonDisabled">发表评论</button>
        </div>
      </div>
    </div>
    <!-- 评论列表容器 -->
    <div class="comments-list">
      <!-- 评论列表标题 -->
      <h1 class="h1">评论列表</h1>
      <!-- 清空评论列表按钮,点击时触发clearComments方法 -->
      <button class="clear-comments" @click="clearComments">清空评论列表</button>
      <!-- 评论列表头部,显示昵称和留言内容的标识 -->
      <div class="comment-row header">
        <div class="comment-username">昵称</div>
        <div class="comment-content">留言内容</div>
      </div>
      <!-- 循环显示评论列表,使用v-for指令遍历comments数组 -->
      <div v-for="(comment, index) in comments" :key="index" class="comment-row">
        <!-- 显示评论者的昵称 -->
        <div class="comment-username">{{ comment.username }}</div>
        <!-- 显示评论内容 -->
        <div class="comment-content">{{ comment.content }}</div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    // 初始化组件数据
    data() {
      return {
        // 当前用户输入的昵称
        currentUsername: '',
        // 当前用户输入的评论内容
        currentComment: '',
        // 存储所有评论的数组
        comments: [],
      };
    },
    // 组件创建后立即执行的钩子函数
    created() {
      // 加载本地存储的评论
      this.loadComments();
    },
    // 定义组件的方法
    methods: {
      // 确认发表评论的方法
      confirmComment() {
        // 弹出确认框,如果用户确认则调用saveComment方法
        if (confirm('确定要发表评论吗?')) {
          this.saveComment();
        }
      },
      // 保存评论的方法
      saveComment() {
        // 检查昵称和评论内容是否为空(去除前后空格)
        if (this.currentUsername.trim() && this.currentComment.trim()) {
          // 创建新的评论对象
          const newComment = {
            username: this.currentUsername,
            content: this.currentComment
          };
          // 将新评论添加到评论列表中
          this.comments.push(newComment);
          // 将新评论保存到本地存储
          this.saveToLocalStorage(newComment);
          // 清空昵称和评论输入框
          this.currentUsername = '';
          this.currentComment = '';
        }
      },
      // 将评论保存到本地存储的方法
      saveToLocalStorage(comment) {
        // 尝试从本地存储获取评论列表,如果不存在则初始化为空数组
        let comments = JSON.parse(localStorage.getItem('comments')) || [];
        // 将新评论添加到评论列表
        comments.push(comment);
        // 将更新后的评论列表保存到本地存储
        localStorage.setItem('comments', JSON.stringify(comments));
      },
      // 加载评论的方法
      loadComments() {
        // 从本地存储获取评论列表,如果不存在则初始化为空数组
        let comments = JSON.parse(localStorage.getItem('comments')) || [];
        // 更新组件的评论列表数据
        this.comments = comments;
      },
      // 清空评论列表的方法
      clearComments() {
        // 弹出确认框,如果用户确认则清空评论列表
        if (confirm('确定要清空评论列表吗?')) {
          // 清空评论列表
          this.comments = [];
          // 从本地存储中移除评论数据
          localStorage.removeItem('comments');
        }
      }
    },
    // 定义组件的计算属性
    computed: {
      // 计算属性,用于判断发表评论按钮是否应该被禁用
      isButtonDisabled() {
        // 如果昵称或评论内容为空(去除前后空格),则返回true,表示按钮应该被禁用
        return !this.currentUsername.trim() || !this.currentComment.trim();
      }
    }
  };
</script>

<!-- 定义一个容器样式,使其宽度为100%,最大宽度为600px,并居中显示 -->
<style>
  .container {
    width: 100%; /* 宽度为100% */
    max-width: 600px; /* 最大宽度为600px */
    margin: 0 auto; /* 水平居中 */
  }

  /* 定义留言板和评论列表的样式 */
  .message-board, .comments-list {
    width: 60vw; /* 宽度为视窗宽度的60% */
    border: 1px solid #ddd; /* 边框颜色为浅灰色 */
    border-radius: 10px; /* 边框圆角为10px */
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 盒子阴影效果 */
    padding: 15px; /* 内边距为15px */
    margin-bottom: 20px; /* 底部外边距为20px */
    background-image: url('https://img.picgo.net/2024/10/23/7a0f2116a03fee4669d4abb947cd3a2743bdfcac1e907347.jpg'); /* 背景图片 */
    background-size: cover; /* 背景图片覆盖整个元素 */
    background-position: center; /* 背景图片居中显示 */
    box-shadow: 5px 5px 5px #888888; /* 盒子阴影效果加强 */
  }

  /* 定义一个通用的盒子样式,底部外边距为2vw */
  .box1 {
    margin-bottom: 2vw; /* 底部外边距为2vw */
  }

  /* 定义标题样式 */
  .h1 {
    font-size: 24px; /* 字体大小为24px */
    margin-bottom: 1vw; /* 底部外边距为1vw */
    text-align: center; /* 文本居中显示 */
  }

  /* 定义用户名输入框样式 */
  .username-input {
    width: 100%; /* 宽度为100% */
    margin-top: 1vw; /* 顶部外边距为1vw */
    padding: 5px; /* 内边距为5px */
    border-radius: 1vw; /* 边框圆角为1vw */
    border: 1px solid #ddd; /* 边框颜色为浅灰色 */
  }

  /* 定义文本框样式 */
  .textbox {
    width: 100%; /* 宽度为100% */
    height: 20vh; /* 高度为视窗高度的20% */
    padding: 5px; /* 内边距为5px */
    margin-top: 1vw; /* 顶部外边距为1vw */
    border-radius: 1vw; /* 边框圆角为1vw */
    border: 1px solid #ddd; /* 边框颜色为浅灰色 */
  }

  /* 定义评论行的样式,使用flex布局 */
  .comment-row {
    display: flex; /* 使用flex布局 */
    width: 100%; /* 宽度为100% */
    border-bottom: 1px solid #eee; /* 底部边框颜色为更浅的灰色 */
  }

  /* 定义评论行标题的样式 */
  .comment-row.header {
    font-weight: bold; /* 字体加粗 */
    background-color: #f5f5f5; /* 背景颜色为浅灰色 */
  }

  /* 定义评论用户名和内容的样式 */
  .comment-username, .comment-content {
    word-wrap: break-word; /* 允许长单词或URL换行到下一行 */
    word-break: break-all; /* 在单词内部进行换行 */
    text-align: center; /* 文本居中显示 */
  }

  /* 定义评论用户名的样式 */
  .comment-username {
    font-weight: bold; /* 字体加粗 */
    padding: 5px; /* 内边距为5px */
    width: 20%; /* 宽度为20% */
    border-right: 1px solid #ddd; /* 右边框颜色为浅灰色 */
  }

  /* 定义评论内容的样式 */
  .comment-content {
    padding: 5px; /* 内边距为5px */
    width: 80%; /* 宽度为80% */
  }

  /* 定义清除评论按钮的样式 */
  .clear-comments {
    float: right; /* 向右浮动 */
    margin-bottom: 10px; /* 底部外边距为10px */
    padding: 10px; /* 内边距为10px */
    background-color: #007bff; /* 背景颜色为蓝色 */
    color: white; /* 文本颜色为白色 */
    border: none; /* 无边框 */
    border-radius: 5px; /* 边框圆角为5px */
    cursor: pointer; /* 鼠标悬停时显示指针样式 */
  }

  /* 定义清除评论按钮禁用时的样式 */
  .clear-comments:disabled {
    background-color: #aaa; /* 背景颜色为灰色 */
    cursor: not-allowed; /* 鼠标悬停时显示禁止样式 */
  }

  /* 定义通用按钮的样式 */
  button {
    padding: 10px; /* 内边距为10px */
    background-color: #007bff; /* 背景颜色为蓝色 */
    color: white; /* 文本颜色为白色 */
    border: none; /* 无边框 */
    border-radius: 5px; /* 边框圆角为5px */
    cursor: pointer; /* 鼠标悬停时显示指针样式 */
    width: 100%; /* 宽度为100% */
    margin-top: 1vw; /* 顶部外边距为1vw */
  }

  /* 定义通用按钮禁用时的样式 */
  button:disabled {
    background-color: #aaa; /* 背景颜色为灰色 */
    cursor: not-allowed; /* 鼠标悬停时显示禁止样式 */
  }
</style>