本项目工程版本以及项目工程笔记将会持续更新,欢迎关注
本次发布的项目版本为v0.0.0
版本日志如下:
本次版本为该应用的首次更新,具体更新内容如下:
1.本次新增计算器加减乘除等计算功能
2.页面设计丰富美观,使用更加流畅
3.计算过程更加符合Windows界面的操作逻辑,用户使用方便易懂可上手
4.全部的功能界面已经搭建完成,功能发布敬请期待
本次项目的版本记录侧重点在于计算器功能的界面设计已经简单加减乘除的功能实现,其他功能的实现暂不记录
项目当前实现效果如下:
版本样式图:
具体流程如下
关键词:react
redux
路由
页面及组件结构设计如下:
接下来就是关于路由的配置操作
包括定义组件、路由、导航栏的Link等各项初始化操作
具体请看, Web应用课路由章节
初始化完毕后,以下是搭建要点
1.完善首页
引入base
,将所有的页面内容放进card
卡片里
Bootstrap上相关内容
由于每个页面都是基于这个card
来放置内容,在这里我们将card抽象放置于一个组件 Base.jsx
,以简化代码,同时方便维护
import Base '/.base'
2.计算器内容设计:
观察Windows下的计算器显示结构:
我们可以有如下的一个布局:
布局:格子布局
css中有:
display grid
来规定一共几列
grid-template-column /rows
来规定一共每行的高度以及有多少列
grid-column:1/ span x
某个按键会有独占的情况,独占几个格子
gap
来写下每个按钮之间的间隔
修该整体宽度:
注:calc(x + y),中间一定要有空格否则不起效果
结果并不是很好看,他的字体是左对齐的且有点小:
font-size 3rem
让所有元素右对齐同时两行布满(flex)布局
flex - direction:column
align-items:flex-end
布满的设计布局:
justify-content:以顺着容器布满整个空间(均匀分布主轴)
justify-content: space-around;
让输入/输出的数如果超过长度就打断放到下一行:
word-break:属性
MDN官方文档介绍
word-break:break-all
鼠标移动到按键之后有高亮:
老生常谈的问题了,css项目中也有说明:
-----.hover{
}
注:记得引入bootsrap
脚本,否则在折叠页面之后没有效果
计算器功能设计:
1.第一步:输入一个数,显示框里当前数前面加一位
我们观察计算器,其输出的样式如下:
一共有如下的状态与操作:
状态:
1.当前的数:currentOperend:""
2.上一个数:lastOperand:""
3.运算符: operation:""
主要大的功能,就是,按数字加一位,按Del
,当前去掉一位
这样做的目的:同样的,也是去简化代码,实现统一管理
我们通过redux来为这三个状态定义操作,同时由于这三个状态并非完全独立,我们在reducer.js
中定义状态
创建文件,digitButton.jsx
,其中的DigitButton
来定义操作,使得点一下按钮,当前行多一位,将所有的按钮变成如下形式:
<DigitButton digit={"7"}/>
来绑定dispatch,详情见 Web应用课Redux
在last-output与current-output中,定义显示内容
{this.format(this.props.lastOperand)}{this.props.operation}
{this.format(this.props.currentOperand)}
在redux中,以保证有显示内容:
currentOperand:state.currentOperand+action.digit,
注:按0的时候会有一些特判:
1).一直按0,应该只要有一个0才对
特判
if(state.currentOperand==='0'&&action.digit==='0')
return state;
当前位为0,同时当前输入的值也为0,时,值返回一个不做修改
2).当输入0.7时,应该显示0.7,而非.7
if(state.currentOperand==='0'&&action.digit!=='.')
return {
...state,
currentOperand:action.digit
}
前一位为0且当前为不为.,将0替换
3).打点可能会有多个
if(state.currentOperand.includes('.')&&action.digit==='.')
return state;
当前是点,前面输入的那个也是点
includes('.')
判断是否包含某种东西
4).当前只输入第一个是点,前面没东西,补个0
if(state.currentOperand===""&&action.digit==='.')
return{
...state,
currentOperand:"0."
};
2.第二步,按Del,删除一位
首先要在reducer.jsx
中写特判,已经为空则不需要删除
if(state.currentOperand==="")
return state;
return {
...state,
currentOperand:state.currentOperand.slice(0,-1),
}
slice(0,-1)
作用为删除从0开始的每一个元素,也就是删除从0开始前面的元素
这次我们直接在calculator.jsx
中定义函数编写
3.操作3:运算符(加减乘除)
我们在一开始,为了方便修改,将所有的字符串定义成了常量,目的是以方便修改
首先在operationButton中添加触发
<button
onClick={()=>{
this.props.choose_operation(this.props.operation);
}}
>{this.props.operation}
</button>
然后实现:将框中符号加在显示框上:
与上面同样的方法,在redux上面写case,然后进行绑定,将所有的button
组件换成 <OperationButton>
问题:
系统按数字再按符号的话,两个都会放到上面部分:
特判:上面是空,当前是空不操作
上面是空当前不是空,放上去
上面不是空当前为空,此时可以替换运算符
上面有值,下面有值,再乘运算符,应先将运算结果放上去,再改变符号
if(state.lastOperand===""&&state.currentOperand==="")
return state;
//上面是空当前不是空
if(state.lastOperand==="")
return{
...state,
lastOperand:state.currentOperand,//将上面的值赋值成当前的值
operation:action.operation,//操作符也放上去
currentOperand:"",
}
//上面不空,当前为空,此时可以替换运算符(如果上面有值下面也有值(说明有计算结果),先计算再放上去同时改变符号)
if(state.currentOperand==="")
return{
...state,
operation:action.operation//直接替换运算符
}
//其他结果
return{
...state,
lastOperand:evaluate(state),
operation:action.operation,
currentOperand:"",//当前属性清空
}
3.第三步:编写evaluate运算:
具体方式:与redux课上的样例类似
问题:
不过在显示上有问题:无论如何计算,都会显示NaN
修改方法:在reducer定义的过程中,只能用一开始定义的原名,而不能用
state.
计算结果出现问题:
比如输入12+2,得出结果为6
原因在于:case如果不加break,在前面判成功之后,所有的都会顺次执行(与c++代码一样)
4.第四步:实现ac清空
写法同Del
在reducer.jsx
上的操作代码如下:
case ACTIONS.CLEAR:
return{
...state,//无论加多少值,都会把新值放在上面且不会有遗漏
currentOperand:"",
lastOperand:"",
operation:"",
}
以下是注意点
1.当三个状态符有一个是空的时候,则不操作
if(state.lastOperand===""||state.currentOperand===""||state.operation==="")
return state;
2.当系统计算器在得出结果进行下一次按键的时候,会把上一次的计算操作予以清空
我们用overwrite变量来判断是否应该覆盖掉
3.在Del中如果有数在结果栏应该全都删掉
if(state.overwrite)
return{
...state,
currentOperand:"",
overwrite:false,
}
4.输入一长串数字,每三位加逗号
运用的是Js库中的
formater:Intl.NumberFormat('en-us')
具体见MDN文档:
MDN官方文档Intl
后续更新计划:
1.温度转换、重量转换、汇率转换功能将开放
2.计算器App简单的平方、变负数的功能将开放
3.通过与后端接入,开放本项目的APP的登录模式
期末考试(大概率7月左右)会进行完整更新
蹲更