实现一个评论列表:展示已发表的评论和评论人
实现用户发表评论功能:包含评论人,评论内容和发表评论按钮
实现评论列表实时更新,用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>