完成该案例需要用到的知识点有:
一、HTML基础
1. 语义化标签使用: textarea 多行输入框、 ul/li 列表承载动态内容、 span 行内元素展示字数/操作按钮
2. 表单属性: maxlength 限制输入框最大字符数、 placeholder 输入提示
3. 元素标识: id 用于精准获取DOM元素, class 用于样式控制和类名判断
二、CSS基础&布局
1. 通用样式重置: * {margin:0;padding:0;box-sizing:border-box;} 统一盒模型、清除默认边距
2. 布局技巧: flex 布局实现头像+内容的横向排列、 float 实现字数统计与发布按钮的右对齐; flex-shrink:0 防止头像被挤压
3. 样式控制: resize:none 禁止文本域拉伸、 cursor:pointer/not-allowed 鼠标样式交互、 disabled 状态的样式覆写
4. 辅助样式: word-break:break-all 实现长文本自动换行、 dashed 虚线边框做列表分隔、 border-radius:50% 实现圆形头像
5. 溢出处理: overflow:hidden 清除浮动带来的父元素高度塌陷问题
三、JavaScript 核心(重点)
1. DOM 元素操作
- 元素获取: document.getElementById() 根据ID获取指定DOM元素(核心获取方式)
- 元素创建: document.createElement() 动态创建节点(如li)
- 内容插入: innerHTML 为元素设置HTML结构(支持拼接标签字符串,高效创建复杂节点); insertBefore(新节点, 参考节点) 实现新内容前置插入(发布的内容显示在最顶部)
- 元素删除: parentElement.remove() 通过子元素找到父元素并删除整个节点
- 内容重置:通过修改元素 value (文本域)、 textContent (普通元素)实现内容清空/更新
2. 事件处理
- 事件绑定: addEventListener() 为元素绑定事件(推荐方式,可绑定多个同类型事件)
- 核心事件类型: input 事件(文本域实时输入监听,区别于 keyup ,兼容粘贴/输入法等场景); click 点击事件(发布、删除操作)
- 事件委托:将删除事件绑定在父元素(ul) 上,通过事件对象 e.target 判断触发源(是否为删除按钮 .the_del ),解决动态生成元素无法绑定事件的问题
- 事件对象: e.target 获取事件的实际触发元素,通过 classList.contains() 判断元素是否包含指定类名
3. 数据处理与交互
- 文本处理: trim() 去除字符串首尾空格,避免发布空内容/纯空格内容
- 状态控制:通过修改元素 disabled 属性,控制发布按钮的可用/禁用状态(无内容时禁用,有内容时启用)
- 随机数应用: Math.floor(Math.random() * 数组长度) 实现从数组中随机选取元素(随机获取用户头像和昵称)
- 日期时间格式化: new Date() 获取当前时间,通过 getFullYear()/getMonth()/getDate() 等方法获取时间分量; padStart(2, '0') 实现补零操作(如1月→01月,9分→09分),保证时间格式统一
4. 数组与对象基础
- 数组取值:通过索引获取数组中的对象元素(如 userList[索引] )
- 对象属性访问:通过 . 访问对象的属性(如 randomUser.uname / randomUser.imgSrc )
5. 页面初始化
- 初始状态设置:页面加载时,主动设置发布按钮的 disabled = true ,避免初始状态按钮可点击的不合理情况
6. 字符串拼接
- 模板字符串(隐式):通过 ${变量} 拼接HTML结构和动态数据(昵称、头像、时间、发布内容),简化字符串拼接操作
四、代码的实现
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>微博发布</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } ul { list-style: none; } .w { width: 900px; margin: 0 auto; } .controls { overflow: hidden; margin-top: 20px; } .controls p { color: #409eff; margin-bottom: 8px; font-size: 16px; } .controls textarea { width: 100%; height: 120px; resize: none; border: 1px solid #e4e7ed; border-radius: 8px; outline: none; padding: 12px; font-size: 16px; } .controls div { float: right; margin-top: 10px; } .controls div span { color: #666; font-size: 14px; } .controls div .useCount { color: red; } .controls div button { width: 80px; outline: none; border: none; background: #0088ff; height: 32px; cursor: pointer; color: #fff; font-size: 14px; border-radius: 4px; margin-left: 10px; } .controls div button:hover { background: #0066cc; } .controls div button:disabled { background: #a0cfff; cursor: not-allowed; } .contentList { margin-top: 40px; } .contentList li { padding: 16px 0; border-bottom: 1px dashed #e4e7ed; position: relative; display: flex; gap: 12px; } .contentList li .userpic { width: 48px; height: 48px; border-radius: 50%; flex-shrink: 0; } .contentList li .content-wrap { flex: 1; } .contentList li .username { font-size: 14px; font-weight: 500; color: #303133; margin-bottom: 4px; display: block; } .contentList li .send-time { font-size: 12px; color: #909399; margin-bottom: 8px; display: block; } .contentList li .content { font-size: 14px; color: #606266; line-height: 1.5; word-break: break-all; } .contentList li .the_del { position: absolute; right: 0; top: 16px; font-size: 18px; cursor: pointer; color: #909399; } </style> </head> <body> <div class="w"> <div class="controls"> <p>有什么新鲜事想告诉大家?</p> <textarea placeholder="说点什么吧..." id="area" cols="30" rows="10" maxlength="200"></textarea> <div> <span class="useCount" id="useCount">0</span> <span>/</span> <span>200</span> <button id="send">发布</button> </div> </div> <div class="contentList"> <ul id="list"></ul> </div> </div> <script> // 模拟用户数据 const userList = [ { uname: '司马懿', imgSrc: '../image/图1.png' }, { uname: '女娲', imgSrc: '../image/图2.png' }, { uname: '百里守约', imgSrc: '../image/图3.png' }, { uname: '亚瑟', imgSrc:'../image/图4.png' }, { uname: '虞姬', imgSrc: '../image/图5.png' }, { uname: '张良', imgSrc: '../image/图6.png' }, { uname: '安其拉', imgSrc: '../image/图7.png' }, { uname: '李白', imgSrc: '../image/图8.jpg' }, { uname: '阿珂', imgSrc: '../image/图9.jpg' }, { uname: '墨子', imgSrc: '../image/图10.jpg' }, ]; // DOM元素 const area = document.getElementById('area'); const useCount = document.getElementById('useCount'); const sendBtn = document.getElementById('send'); const list = document.getElementById('list'); // 1. 实时更新字数统计 area.addEventListener('input', function () { const len = this.value.trim().length; useCount.textContent = len; // 控制发布按钮状态 sendBtn.disabled = len === 0; }); // 2. 发布评论 sendBtn.addEventListener('click', function () { const content = area.value.trim(); if (!content) return; // 随机选择一个用户作为评论者 const randomUser = userList[Math.floor(Math.random() * userList.length)]; // 获取当前时间 const now = new Date(); const timeStr = `${now.getFullYear()}年${(now.getMonth() + 1).toString().padStart(2, '0')}月${now.getDate().toString().padStart(2, '0')}日 ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`; // 创建评论元素 const li = document.createElement('li'); li.innerHTML = ` <img class="userpic" src="${randomUser.imgSrc}" alt="${randomUser.uname}"> <div class="content-wrap"> <span class="username">${randomUser.uname}</span> <span class="send-time">发布于 ${timeStr}</span> <div class="content">${content}</div> </div> <span class="the_del">×</span> `; // 添加到列表最前面 list.insertBefore(li, list.firstElementChild); // 清空输入框并重置字数 area.value = ''; useCount.textContent = '0'; sendBtn.disabled = true; }); // 3. 删除评论 list.addEventListener('click', function (e) { if (e.target.classList.contains('the_del')) { e.target.parentElement.remove(); } }); // 初始化按钮状态 sendBtn.disabled = true; </script> </body> </html>五、代码效果呈现
代码效果如下图所示: