(第二篇)HMTL+CSS+JS-新手小白循序渐进案例入门
前言:由于主包看见上一篇前端三件套入门点赞收藏挺多的,加之本身想继续学习入门前端,咱们就继续深入学习吧~~~^_^一边完成我们简易计算器的新功能一边学习新知识
一、新功能1描述:
-
支持键盘输入(数字/运算符/回车计算/ESC清空)---------学习事件监听
-
增加退格键功能-----------学习字符串操作
(1)代码实现:
第一部分,在script标签最前面添加这个函数(其他原有函数保持不变)
// 按键处理函数:监听键盘事件,获取按下的键,根据不同按键执行对应操作.function handleKeyPress(e) {// e.key是用户按下的键const key = e.key;// 数字和运算符直接输入if(/[0-9/./+\-/*//]/.test(key)) {appendToDisplay(key);}// 回车键计算else if (key === 'Enter') {calculate();}// 退格键删除else if (key === 'Backspace') {const display = document.getElementById('display');display.value = display.value.slice(0, -1); // 字符串截取方法,即删除最后一个字符}// ESC键清空else if (key === 'Escape') {clearDispaly();}}
第二部分:在script末尾添加事件监听
// 使用DOMContentLoaded确保 DOM 加载完成后再绑定事件document.addEventListener('DOMContentLoaded', function() {// 监听整个文档的键盘按下事件(keydown事件),调用handleKeyPress处理document.addEventListener('keydown', handleKeyPress);})
(2)代码解析:
1.e.key
的基本原理:
- 当用户按下键盘上的某个键时,浏览器会创建一个键盘事件对象(
KeyboardEvent
),并将其作为参数传递给事件处理函数(如handleKeyPress(e)
) - 而在 JavaScript 的键盘事件中,
e.key
是事件对象(e
)的一个属性,它自动包含了用户按下的物理键所对应的字符或功能描述。 - 这是浏览器原生提供的功能,无需额外配置。
-
e.key
:返回一个字符串。
例如:- 按下数字键
5
→e.key
的值是"5"
- 按下字母键
A
(无论大小写)→e.key
的值是"a"
或"A"
(取决于是否按住 Shift) - 按下功能键
Enter
→e.key
的值是"Enter"
- 按下组合键
Ctrl + S
→e.key
的值是"s"
(Ctrl
状态需通过e.ctrlKey
判断)
- 按下数字键
说这么多,我们直接来直观地查看某个按键对应的 e.key
值吧~
document.addEventListener('keydown', function(e) {console.log(`按下的键: ${e.key}`);console.log(`按键代码: ${e.code}`);console.log(`是否按住 Ctrl: ${e.ctrlKey}`);console.log(`是否按住 Shift: ${e.shiftKey}`);
});
打开浏览器控制台(F12)- Console,按下任意键,即可实时看到事件对象的属性值啦~
2.事件监听设置
使用DOMContentLoaded
事件确保在 DOM 完全加载后再绑定事件
如果直接在 script 标签中绑定事件(不使用 DOMContentLoaded),可能在 DOM 元素存在之前执行,导致错误
3.=== 比较符:
使用严格的 === 比较符不会执行类型强制转换,从而能够严格地评估两个对象之间的差别。
例子:
var zeroAsAString = "0";if (zeroAsAString == 0) {// 判断为true.....
}if (zeroAsAString === 0) {// 判断为false
}
二、新功能2描述
-
新增一个显示带时间戳的计算历史面板,显示在页面的左边,用户可以看到自己计算的历史信息。即「左侧历史面板 + 居中计算器」--------进而学习Flexbox 布局
要完成这个需求我们先学习下Flexbox 的基础知识!
一、什么是 Flexbox?
Flexbox 是 CSS3 提供的一维布局模型,专门解决元素排列、对齐和分布空间的问题。就像整理书架:
-
Flex容器(书架):设置了
display: flex
的元素(使容器成为Flex容器,子元素自动成为Flex项目) -
Flex项目(书本):容器的直接子元素
二、Flexbox核心属性:
分为两个方向,即主轴(水平)和交叉轴(垂直)方向
2. 容器属性(控制整体布局(书架))
属性 | 作用 | 示例值 |
---|---|---|
flex-direction | 主轴方向 | row /column |
justify-content | 主轴对齐 | center /space-between |
align-items | 交叉轴对齐 | center /stretch |
flex-wrap | 是否换行 | nowrap /wrap |
gap | 项目间距 | 10px |
3. 项目属性(控制单个元素(书本))
属性 | 作用 | 示例值 |
---|---|---|
flex-grow | 放大比例 | 1 /0 |
flex-shrink | 缩小比例 | 1 /0 |
flex-basis | 初始尺寸 | 300px /auto |
align-self | 单独对齐 | center |
知道了基本的概念后,我们来设计下整体的页面布局:
三、布局设计考虑点:
先划分区域,确定父子关系
识别页面中的独立功能区块----->得出:整个页面是容器,项目1是计算器,项目2是计算历史面板
控制弹性行为
固定尺寸用
flex: 0 0 <宽度>
自动填充用
flex: 1
四、修改 HTML 结构:
回到我们的代码原始结构,如果直接在body里面加入计算历史面板<div class="history-panel">...</div>
<div class="container"><div class="history-panel">...</div><!-- 计算器内容省略。。。 -->
</div>
就会存在问题:历史面板和计算器是上下堆叠关系,无法实现左右并列!
按照我们前面分析得出的解决方案:创建两个 Flex 项目:
<div class="app-container"> <!-- Flex容器 --><div class="history-panel"></div> <!-- Flex项目1(计算历史面板) --><div class="history-panel">省略...</div><div class="calculator-container"></div> <!-- Flex项目2(计算器) --><div class="calculator">省略...</div>
</div>
五、CSS 关键代码详解 :
(1)外层 app-container
成为 Flex 容器:
.app-container {display: flex; /* 启用Flex布局 */min-height: 90vh; /* 确保高度足够 */gap: 20px; /* 两个项目的间距 */flex-direction: row /* 这个可以不写,因为默认是水平/左右放置两个项目 */
}
🧩为什么用 min-height: 90vh
?
-
vh
单位表示视口高度的百分比 -
确保布局即使内容很少时也能占满大部分屏幕
-
避免历史面板高度塌陷
(2) Flex项目1(计算历史面板):
.history-panel {flex: 0 0 300px; /* 不放大/不缩小/固定300px */overflow-y: auto; /* 内容超出时滚动 */
}
flex
简写属性:flex: <flex-grow> <flex-shrink> <flex-basis>
flex: 0 0 300px
- 不放大 (
0
) - 不缩小 (
0
) - 基础宽度
300px
(类似width
但优先级更高)
(3)Flex项目2(计算器):
.calculator-container {flex: 1; /* 占据剩余所有空间 */display: flex; /* 嵌套Flex实现居中 */justify-content: center;
}
flex: 1
- 等价于
flex: 1 1 0%
- 自动填满剩余空间
calculator-container 也是Flex容器
- 外层Flex分配空间 (
flex:1
) - 内层Flex实现居中 (
justify-content: center
)
六、结合实操深入理解:
-
临时在.app-container 的CSS样式中添加
border: 1px solid red
查看容器范围:
可以看到如图,红框框起来的就是整个容器范围:
也可以打开F12检查-Elements,鼠标停在该处会显示标记区域:
三、总结:
本次学习到了 事件监听+字符串操作+Flexbox 布局逐步深入学习+实践练手。
期待我们的下一篇文章吧贝贝们,记得关注主包~
完整代码下一篇给出!(因为想把这个功能完整做完)