预期效果
分析需要用到哪些html元素:输入框、提交按钮、标题,容器div(展示留言的地方)
流程图
代码实现
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>留言板</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h1>留言板</h1>
<form id="messageForm">
<textarea id="messageInput" placeholder="请输入您的留言..." required></textarea>
<button type="submit">提交</button>
</form>
<div id="messagesContainer"></div>
</div>
<script src="scripts.js"></script>
</body>
</html>
styles.css
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.container {
background-color: #ffffff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 5px;
width: 100%;
max-width: 500px;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
form {
display: flex;
flex-direction: column;
}
textarea {
resize: none;
padding: 10px;
font-size: 16px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
button {
padding: 10px;
font-size: 16px;
color: #ffffff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
#messagesContainer {
margin-top: 20px;
}
.message {
background-color: #f9f9f9;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
}
scripts.js
document.addEventListener('DOMContentLoaded', () => {
const messageForm = document.getElementById('messageForm');
const messageInput = document.getElementById('messageInput');
const messagesContainer = document.getElementById('messagesContainer');
// 从本地存储中加载留言
const loadMessages = () => {
const messages = JSON.parse(localStorage.getItem('messages')) || [];
messages.forEach(addMessageToDOM);
};
// 向本地存储中保存留言
const saveMessage = (message) => {
const messages = JSON.parse(localStorage.getItem('messages')) || [];
messages.push(message);
localStorage.setItem('messages', JSON.stringify(messages));
};
// 向DOM中添加留言
const addMessageToDOM = (message) => {
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
messageDiv.textContent = message;
messagesContainer.appendChild(messageDiv);
};
// 表单提交事件处理
messageForm.addEventListener('submit', (event) => {
event.preventDefault();
const message = messageInput.value.trim();
if (message) {
addMessageToDOM(message);
saveMessage(message);
messageInput.value = '';
}
});
// 加载留言
loadMessages();
});
改进点1——添加时间戳
给每条留言添加时间戳,使得显示每条留言的时间。
思路:我们在js中动态添加节点即可,在添加信息时,获取当前时间点,将其转化为常见的日期形式后添加到该条留言后面,注意,为了方便,添加时是将留言和时间封装到一个对象中,然后再添加。更新后的js代码如下:
document.addEventListener('DOMContentLoaded', () => {
// 向本地存储中保存留言
.......
.......
// 向DOM中添加留言
const addMessageToDOM = (messageObj) => {
const { message, timestamp } = messageObj;
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
const messageContent = document.createElement('p');
messageContent.textContent = message;
const messageTime = document.createElement('small');
messageTime.textContent = `留言时间: ${timestamp}`;
messageDiv.appendChild(messageContent);
messageDiv.appendChild(messageTime);
messagesContainer.appendChild(messageDiv);
};
// 获取当前时间的字符串表示
const getCurrentTimestamp = () => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hour = String(now.getHours()).padStart(2, '0');
const minute = String(now.getMinutes()).padStart(2, '0');
const second = String(now.getSeconds()).padStart(2, '0');
return `${year}年${month}月${day}日 ${hour}:${minute}:${second}`;
};
// 表单提交事件处理
messageForm.addEventListener('submit', (event) => {
event.preventDefault();
const message = messageInput.value.trim();
if (message) {
const timestamp = getCurrentTimestamp();
const messageObj = { message, timestamp };
addMessageToDOM(messageObj);
saveMessage(messageObj);
messageInput.value = '';
}
});
// 加载留言
loadMessages();
});
改进点2——时间和留言显示在同一行
上面添加后的时间显示在留言的下方,我想展示在留言的右边,让它们在同一行,该怎么做呢?
思路:为了让时间展示在留言的右边并保持在同一行,我们可以使用 CSS 的 flexbox
布局。具体步骤如下:
- 将每条留言的容器设置为
display: flex
,使其成为一个 flex 容器。 - 设置留言内容和时间的样式,以确保它们正确对齐。
更新后的 CSS (styles.css
)
...................
...................
.message {
background-color: #f9f9f9;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
display: flex;//设置浮动
justify-content: space-between;//将留言和时间分隔到容器的两端。
align-items: center;
}
.message p {
margin: 0;
flex-grow: 1;//使留言内容占据剩余空间
}
.message small {
margin-left: 10px;
color: #888;
}
改进点3——调整留言展示顺序
添加了多条留言后,我们发现,新添加的留言是展示在下面的,这不符合我们的观看习惯,我需要调换一下顺序。
思路:为了实现点击按钮后新留言立即显示在页面顶部,我们可以在表单提交处理函数中直接将新的留言添加到数组的顶部。这样,用户提交留言时,它会立即显示在最上面,而不需要刷新页面。
以下是如何实现这个功能的详细步骤:
- 将新留言添加到 DOM 的顶部:- 在提交表单时,使用
prepend
方法将新留言添加到messagesContainer
的顶部。 - 更新
loadMessages
函数:- 直接遍历留言数组展示在页面上即可
**更新后的 JavaScript (
scripts.js
)**
document.addEventListener('DOMContentLoaded', () => {
....................
....................
....................
// 从本地存储中加载留言
const loadMessages = () => {
const messages = JSON.parse(localStorage.getItem('messages')) || [];
messages.forEach(addMessageToDOM); // 直接加载所有留言
};
....................
....................
// 向DOM中添加留言
const addMessageToDOM = (messageObj) => {
const { message, timestamp } = messageObj;
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
const messageContent = document.createElement('p');
messageContent.textContent = message;
const messageTime = document.createElement('small');
messageTime.textContent = `留言时间: ${timestamp}`;
messageDiv.appendChild(messageContent);
messageDiv.appendChild(messageTime);
messagesContainer.prepend(messageDiv); // 将留言添加到顶部
};
....................
....................
....................
// 加载留言
loadMessages();
});
改进点4——添加滚动条
如果留言太多,会把留言面板顶上去,这时候想要把留言信息做成一个滚动的形式,不会影响留言面板在页面的位置。
要实现留言信息的滚动显示而不影响留言板在页面上的位置,我们可以使用 CSS 的
overflow
属性来设置滚动区域。具体步骤如下:
- 设置滚动容器的高度和样式:- 为留言容器设置一个固定的高度,并启用垂直滚动条。- 确保
overflow-y
设置为auto
或scroll
,以便在内容超出时显示滚动条。
**更新后的 CSS (
styles.css
)**
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.container {
background-color: #ffffff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 5px;
width: 100%;
max-width: 500px;
position: relative; /* 设定为相对定位,以便于添加其他样式 */
}
........................
........................
button:hover {
background-color: #0056b3;
}
#messagesContainer {
margin-top: 20px;
max-height: 300px; /* 设置最大高度 */
overflow-y: auto; /* 启用垂直滚动 */
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f9f9f9;
}
........................
........................
改进点5——删除留言
添加一个删除留言的功能
思路:
为了添加删除留言的功能,我们在js中在添加留言的时候同时添加一个删除的按钮即可。我们需要做以下几步:
- 在每条留言上添加一个删除按钮。
- 在点击删除按钮时,从 DOM 中移除该留言。
- 从本地存储中删除相应的留言。
更新后的 JavaScript 和 css
scripts.js
document.addEventListener('DOMContentLoaded', () => {
....................
....................
....................
const loadMessages = () => {
const messages = JSON.parse(localStorage.getItem('messages')) || [];
messages.forEach(addMessageToDOM); // 直接加载所有留言
};
....................
....................
// 从本地存储中删除留言的方法
const deleteMessage = (timestamp) => {
let messages = JSON.parse(localStorage.getItem('messages')) || [];
messages = messages.filter(message => message.timestamp !== timestamp);
localStorage.setItem('messages', JSON.stringify(messages));
};
// 向DOM中添加留言
const addMessageToDOM = (messageObj) => {
....................
....................
....................
const messageTime = document.createElement('small');
messageTime.textContent = `留言时间: ${timestamp}`;
//添加删除功能
const deleteButton = document.createElement('button');
deleteButton.textContent = '删除';
deleteButton.classList.add('delete-button');
deleteButton.addEventListener('click', () => {
//使用 confirm 方法弹出确认对话框
const confirmDelete = confirm('你确定要删除这条留言吗?');
if (confirmDelete) {
messagesContainer.removeChild(messageDiv);
deleteMessage(timestamp);
}
});
messageDiv.appendChild(messageContent);
messageDiv.appendChild(messageTime);
messageDiv.appendChild(deleteButton);//将删除按钮添加到元素节点中
messagesContainer.prepend(messageDiv);
};
....................
....................
....................
....................
// 加载留言
loadMessages();
});
styles.css
..................
..................
..................
..................
.message small {
margin-left: 10px;
color: #888;
}
.delete-button {
background-color: #ff4d4d;
color: white;
border: none;
border-radius: 5px;
padding: 5px 10px;
cursor: pointer;
}
.delete-button:hover {
background-color: #d11a1a;
}
改进点6——回车键触发提交
目前的代码,我们需要用鼠标点击提交才会触发添加留言的事件,我想按下键盘的回车键就提交呢?怎么实现?
思路:要在按下键盘的回车键后提交留言,可以在 JavaScript 中为
textarea
元素添加一个
keydown
事件监听器。这样,当用户在
textarea
中按下回车键时,表单会自动提交。
具体步骤:
添加一个
keydown
事件监听器,当按下回车键并且没有按住 Shift 键时,阻止默认行为并调用
handleSubmit
函数。
当用户在
textarea
中按下回车键时,表单会自动提交,留言会立即显示在页面上。按下 Shift + Enter 可以在
textarea
中插入换行符。
**更新后的 JavaScript (
scripts.js
)**
......................
......................
......................
// 在 textarea 中按下回车键时提交表单
messageInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();//阻止默认的回车换行事件,换行改成了shift+Enter
messageForm.dispatchEvent(new Event("submit"));
}
});
// 加载留言
loadMessages();
最终实现效果
代码优化——封装提交方法
我们可以将改进点6的表单提交单独提取出来成一个方法,需要的时候就调用它,代码如下:
document.addEventListener('DOMContentLoaded', () => {
.................................
.................................
.................................
.................................
.................................
.................................
// 表单提交事件处理
const handleSubmit = () => {
const message = messageInput.value.trim();
if (message) {
const timestamp = getCurrentTimestamp();
const messageObj = { message, timestamp };
addMessageToDOM(messageObj); // 立即更新DOM
saveMessage(messageObj);
messageInput.value = '';
}
};
messageForm.addEventListener('submit', (event) => {
event.preventDefault();
handleSubmit();
});
// 在 textarea 中按下回车键时提交表单
messageInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
handleSubmit();
}
});
// 加载留言
loadMessages();
});
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>留言板</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
<h1>留言板</h1>
<form id="messageForm">
<textarea id="messageInput" placeholder="请输入您的留言..." required></textarea>
<button type="submit">提交</button>
</form>
<div id="messagesContainer"></div>
</div>
<script src="./scripts.js"></script>
</body>
</html>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.container {
background-color: #ffffff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 5px;
width: 100%;
max-width: 700px;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
form {
display: flex;
flex-direction: column;
}
textarea {
resize: none;
padding: 10px;
font-size: 16px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
button {
padding: 10px;
font-size: 16px;
color: #ffffff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
#messagesContainer {
margin-top: 20px;
max-height: 400px;
overflow-y: auto;
border: 1px solid #ddd;
background-color: #f9f9f9;
}
.message {
background-color: #f9f9f9;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
display: flex;
justify-content:space-between;
align-items:center;
}
.message p {
margin: 0;
flex-grow: 1;
}
.message small {
margin-left: 10px;
margin-right: 20px;
color: #888;
}
.delete-button {
background-color: #ff4d4d;
color: white;
border: 2px;
border-radius: 5px;
padding: 3px 5px;
cursor: pointer;
}
.delete-button:hover {
background-color: #d11a1a;
}
document.addEventListener("DOMContentLoaded", () => {
const messageForm = document.getElementById("messageForm");
const messageInput = document.getElementById("messageInput");
const messagesContainer = document.getElementById("messagesContainer");
// 从本地存储中加载留言
const loadMessages = () => {
const messages = JSON.parse(localStorage.getItem("messages")) || [];
messages.forEach(addMessageToDOM);
};
// 向本地存储中保存留言
const saveMessage = (message) => {
const messages = JSON.parse(localStorage.getItem("messages")) || [];
messages.push(message);
localStorage.setItem("messages", JSON.stringify(messages));
};
// 从本地存储中删除留言
const deleteMessage = (timestamp) => {
let messages = JSON.parse(localStorage.getItem("messages")) || [];
messages = messages.filter((message) => message.timestamp !== timestamp);
localStorage.setItem("messages", JSON.stringify(messages));
};
// 向DOM中添加留言
const addMessageToDOM = (messageObj) => {
const { message, timestamp } = messageObj;
const messageDiv = document.createElement("div");
messageDiv.classList.add("message");
const messageContent = document.createElement("p");
messageContent.textContent = message;
const messageTime = document.createElement("small");
messageTime.textContent = `${timestamp}`;
const deleteButton = document.createElement("button");
deleteButton.textContent = "删除";
deleteButton.classList.add("delete-button");
deleteButton.addEventListener("click", () => {
const contirmDelete = confirm("你确定要删除这条留言吗?");
if (contirmDelete) {
messagesContainer.removeChild(messageDiv);
deleteMessage(timestamp);
}
});
messageDiv.appendChild(messageContent);
messageDiv.appendChild(messageTime);
messageDiv.appendChild(deleteButton);
messagesContainer.prepend(messageDiv);
};
// 获取当前时间的字符串表示
const getCurrentTimestamp = () => {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, "0");
const day = String(now.getDate()).padStart(2, "0");
const hour = String(now.getHours()).padStart(2, "0");
const minute = String(now.getMinutes()).padStart(2, "0");
const second = String(now.getSeconds()).padStart(2, "0");
return `${year}年${month}月${day}日 ${hour}:${minute}:${second}`;
};
// 表单提交事件处理
messageForm.addEventListener("submit", (event) => {
event.preventDefault();
const message = messageInput.value.trim();
if (message) {
const timestamp = getCurrentTimestamp();
const messageObj = { message, timestamp };
addMessageToDOM(messageObj);
saveMessage(messageObj);
messageInput.value = "";
}
});
// 按下键盘回车键提交留言
messageInput.addEventListener("keydown", (event) => {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
messageForm.dispatchEvent(new Event("submit"));
}
});
// 加载留言
loadMessages();
});
版权归原作者 Vincent_TangM 所有, 如有侵权,请联系我们删除。