2.3 计算金额总计,显示表单输出结果
上一节用data-*属性将键/值对数据和数量字段联系起来,将< output >元素添加到每个产品的购买金额总计和整个订单金额总计上。然而,在现在的状态下,订单似乎并不关心用户在数量字段输入的值,总金额依旧是$0.00。
本节主要学习内容
- 如何使用valueAsNumber属性,以数字形式读取输入值。
- 如何从data-*属性中获取数据。
- 如何更新< output >元素。
本节将使用data-*属性与< output >元素来计算金额总计,然后把结果显示在用户的浏览器上。主要有以下4步内容。 - 第1步:添加函数来计算总数。
- 第2步:获取输入字段的数量值。
- 第3步:获取价格值并分别算出各个产品与整个订单的金额总计。
- 第4步:在订单中显示更新后的金额总计。
2.3.1 构建计算函数
下面,我们就来创建在订单中执行计算的函数。
第1步:添加函数,计算总金额
如代码清单2-7所示,从DOM中获取相关字段(quantity、item_total、order_total),在每一个数量字段中建立事件侦听器,只要用户修改了数量值,就能计算出总金额。计算代码并没有放在该代码清单中,本章稍后部分再来添加它。
打开app.js,将代码清单2-7中的代码放到init函数中,紧挨着放在代码行“saveBtn. addEventListener('click', saveForm, false);”后面。
接下来我们看一下HTML5新引入的valueAsNumber属性,它能获取input字段元素值的数字形式。
valueAsNumber属性
qtyFields[i]输入元素的value属性,用JavaScript可以读取该元素的当前值,但返回值经常是字符串。虽然用parseFloat可以将这种值转变为浮点数,但HTML5有一个新的解决方法,那就是利用valueAsNumber属性。
比如,当你读取number输入类型的valueAsNumber属性,该属性就能返回一个浮点数。如果将一个浮点数赋予number输入类型的valueAsNumber属性,该属性就会将这个浮点数转换为字符串。
在date和time字段中使用valueAsDate属性
无独有偶,在date与time字段中,同样也存在一个valueAsDate属性,它的作用类似于valueAsNumber属性。当用它获取一个日期相关字段的值时,就会返回一个Date对象。而且与valueAsNumber类似,也可以用该属性将该字段的值设为一个Date对象。
valueAsNumber属性只能用于那些支持number这种新输入类型的浏览器。如果浏览器不支持这种输入类型,要回退到一个常规的文本输入,那就只好用JavaScript的parseFloat函数来解决了。所以,对于HTML5方案和回退方案来说,下列语句都可以读取字段的浮点数:
同样,对于修改字段的浮点数值而言,下列语句也是等同的:
那为什么要使用valueAsNumber,而不继续使用parseFloat呢?
现在,你可能要问:“既然parseFloat能在所有浏览器上用,那为什么还非得要用valueAsNumber呢?”这是因为,valueAsNumber能够更简洁地实现浮点数与字符串的转换。不过,虽然使用valueAsNumber要比使用parseFloat更有效率一些,但在大多数Web应用中,这种性能的微小提升基本上显现不出来。在W3C的邮件列表上,就曾有人质疑过valueAsNumber的有效性。为此,HTML5编辑lan Hickson拿出了一个递增字段值的用例,以证明valueAsNumber的确要比parseFloat简洁,代码如下:
https://yqfile.alicdn.com/3d640c183e9d748dbace9f3d1fdc0ddd77ab9705.png" >
第2步:取回quantity输入字段的值
在订单的订单明细部分中,可以使用valueAsNumber属性来获取每种产品的quantity字段值。还记得代码清单2-7中那个空的for循环吗?现在就将代码清单2-8所示的代码加进去。
为了获取每个产品的价钱,就需要读取HTML5的data-*属性值,下面我们就来实现它。
2.3.2 获取data-*属性的值
前文介绍了在HTML5中,如何利用data-属性将键/值对数据绑定到元素上。当你想在元素上添加额外的数据,以便轻松获取或用在JavaScript代码上时,这种数据就显得非常重要了。读取data-属性的方法很简单:每个元素都有dataset属性,内含该元素所有的data-*属性。dataset属性中的每一项都有一个键名,它和该元素标签中的键名一一对应,不过没有data-前缀。代码清单2-4中用data-price属性定义出产品价格,要想取回这个价格值,就需要用下面这行代码:
警告
假如用连字符连接data-*属性名,那么dataset属性就会将它以驼峰命名法表现出来。例如,如果属性名为data-person-name,那么读取时就需要这么写:element.dataset. personName,而不能用element.dataset-name。
dataset属性是HTML5新引入的,还未能被所有浏览器所支持。幸好,有一种适用于所有浏览器的回退方案(对的,你没看错,是所有的浏览器,甚至是IE6),这就是getAttribute方法。利用它获取data-price属性值的代码为:
第3步:取回各产品价格值,计算单种产品的总金额以及订单总金额
下面,我们就获取每种产品的价格值,将它乘以产品的购买数量,来计算每种产品的总金额,继而得出订单的总金额。将代码清单2-9所示的代码添加到上一步完成的代码中,让它位于for循环的闭合花括号之前。
现在,已经计算出了每种产品的总金额以及订单的总金额,只需利用< output >元素将这些数值显示到表单中即可。对于那些支持< output >元素的浏览器来说,向该元素内写入数值,就能从表单中访问它了,比如:
https://yqfile.alicdn.com/b1fadcc4cbf0caecfa6e1977ed8798eb97e75581.png" >
为了更新< output >元素的值,可以如下设定value属性:
对于那些不支持< output >的浏览器该怎么办?
要想在不支持< output >元素的浏览器中使用该元素,需要给该元素分配一个ID,并且使用document.getElementById:
https://yqfile.alicdn.com/7ccc09c0c75a74b10bf15fe2cc8b48e9ceb32bd2.png" >
要想更新元素值,可以设定innerHTML属性:
接下来,让我们来更新订单总金额。
第4步:在订单中显示更新的订单总金额
将代码清单2-10所示的代码添加到app.js,让它紧跟步骤3完成后的代码后面,但仍在for循环的结束花括号之前。
试试看
截至目前,每种产品的总金额以及整个订单的总金额应该已经可以正常显示出来了。在现代的浏览器中加载页面,改变每种商品数量字段中的数值,你会注意到两种总金额都会相应地改变,如图2-9所示。
https://yqfile.alicdn.com/b55f177296bbcc9620d692a1835119c2dd8439ec.png" >
现在,表单可以计算总金额,并且能够验证输入的数据,但如果要添加其他能够显示自定义错误消息提示的验证功能,该怎么办呢?在下一节,我们就使用约束验证API来实现自定义验证,还要利用CSS3来格式化无效字段。