使用前端三件套实现一个留言板网站

预期效果

分析需要用到哪些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` 布局。具体步骤如下:

1. 将每条留言的容器设置为 `display: flex`,使其成为一个 flex 容器。
2. 设置留言内容和时间的样式,以确保它们正确对齐。

更新后的 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——调整留言展示顺序

添加了多条留言后,我们发现,新添加的留言是展示在下面的,这不符合我们的观看习惯,我需要调换一下顺序。

思路:为了实现点击按钮后新留言立即显示在页面顶部,我们可以在表单提交处理函数中直接将新的留言添加到数组的顶部。这样,用户提交留言时,它会立即显示在最上面,而不需要刷新页面。

以下是如何实现这个功能的详细步骤:

  1. 将新留言添加到 DOM 的顶部

    • 在提交表单时,使用 prepend 方法将新留言添加到 messagesContainer 的顶部。

  2. 更新 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 属性来设置滚动区域。具体步骤如下:

  1. 设置滚动容器的高度和样式:

    • 为留言容器设置一个固定的高度,并启用垂直滚动条。

    • 确保 overflow-y 设置为 autoscroll,以便在内容超出时显示滚动条。

更新后的 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中在添加留言的时候同时添加一个删除的按钮即可。我们需要做以下几步:

  1. 在每条留言上添加一个删除按钮。

  2. 在点击删除按钮时,从 DOM 中移除该留言。

  3. 从本地存储中删除相应的留言。

更新后的 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();
});

  • 14
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值