要求:输入xxx.xx元,后台存xxxxx分。并添加表单验证。以上描述中的基本思想包括两种价格,一种是输入价格,即我们能看到的价格;另一个是实际传递给后台的价格。当输入价格时,订单会监测价格变化,然后将输入的价格乘以100,将人民币换算成元器件。根据要求,首先必须绑定的数据是ng-model中的值,也就是最后传递给后台的数据。另外需要实现表单验证,所以required属性是必须的,有时候我们要给用户一些提示信息,提示这是必填项,所以name也是必须的。scope:{ngModel:'=',//绑定价格(以`cent`为单位)name:'@?',//输入框name属性,使用'@'获取需要的name属性的值:“=?”//表单验证,默认为true;如果不想验证,就设置为false}由于name和required不是必须设置的属性,所以用?.要实现主要功能,首先我们需要初始化一个显示在输入框的价格:scope.price=undefined;但是考虑到在编辑的时候,我们会从后台获取一个已有的价格,这个时候我们要显示出来,所以修改一下:scope.price=scope.ngModel/100接下来就是监控我们刚才的价格定义,当它发生变化时,对其进行单位换算处理。//监控价格scope.$watch('price',function(newValue){if(newValue){scope.ngModel=newValue*100;//将'yuan'转换为'fen'}});由于监控的时候,当所有input都被删除的时候,price的值是undefined,也就是newValue是undefined,所以此时ngModel中的值还是上次的。所以做一些清理工作。scope.$watch('price',function(newValue){if(newValue){scope.ngModel=newValue*100;//Convert'Yuan'to'Centre'}//防止删除所有输入,ngModel还有一个值if(typeof(scope.price)==='undefined'){scope.ngModel=0;}});这时候我们的效果是这样的:再测试一下编辑的效果:出错了,实际有传给后台的价格,但是没有以元显示,也就是说我们设置的初始值还没有生效。初始化前打印ngModel:这是因为Angular渲染速度非常快。我们在定义price的时候,ngModel的值还没有绑定,所以这里是undefined。解决办法就是让他延迟初始化一段时间。$timeout(function(){scope.price=scope.ngModel/100;//实际显示价格(元)},100);再来看看编辑的效果:验证的实现一开始我们在绑定的时候,选择两个属性:name和required,然后我们绑定到输入框:在command中使用:然后看验证效果:功能补充从上面的效果可以看出,并没有真正达到我们对价格输入的预期:1.控制两位小数2.不要输入多个小数点。所以,为了让用户体验更好,我们需要在这里做一些改进,格式化价格。格式化显示价格,首先我们要控制价格显示两位小数。应该按照下面的思路来处理:1.获取小数点的位置2.获取小数点后的部分。如果小数点后面没有部分,则补00,如果后面的部分只有一位,则补0。如果后面有两位及以上的部分,则截取两位数部分。那么按照上面的思路,我们就可以实现钱币展示的一般效果了。然后考虑小数点的问题。因为为了让用户在进入的时候能显示出xx.00的样子,我们必须在前台显示的时候把price的类型改成字符串,一旦我们的类型是字符串,就说明用户可以enter多了一位小数,我们要做的就是禁止用户输入多位小数。那么上面的思路继续:3、从第一个小数点后面的部分得到第二个小数点的位置。如果位置下标为负数,则表示第一位小数点后的部分为整数,没有第二位小数点。如果下标不是负数,则表示第一个小数点后的部分还有第二个小数点。我们只保留到小数点后第二位之前的部分根据这个思路,我们可以梳理出如下代码:self.format=function(price){//获取小数点后的数字并计算长度价格.indexOf(".");//获取小数点的位置if(firstPoint>=0){varmantissa=price.slice(firstPoint+1);//获取小数点后的部分varsecondPoint=mantissa.indexOf(".");//获取第二位小数的位置是为了防止输入两个或更多的小数点if(secondPoint<0){//如果有两个以上的小数位,则去掉后者if(mantissa.length>=2){退货价格。slice(0,firstPoint+3);}elseif(mantissa.length===1){返回价格+'0';}}else{//去掉第二个小数点returnprice.slice(0,firstPoint+secondPoint+1);}}else{返回价格+'.00';}};到这里,小数点的格式化就完成了,但是又出现了一个问题,就是我们调用的时候。起初,我在监听ngModel变化时调用了这个函数。大部分功能都可以,就是无法控制小数点。上面说了,输入的价格price是一个字符串,如果我们这时候连续输入两位小数。比如12..,当我们输入12时,ngModel的值为12;当我们输入12.时,ngModel仍然是12;当我们输入两个点12..时,还是12,ngModel的值不变,所以不会触发格式化功能,无法控制小数点位数。当我们在小数点后连续输入多个0时也是如此。所以在监控价格的时候,触发格式化功能。//监控价格self.watchPrice=function(newValue){if(newValue){varpoint=newValue.indexOf(".");//获取小数点的位置//防止在输入整数的时候有时候,小数点会自动补全//所以这里只有当小数点后的位数超过两位//或者有两个小数点的时候,格式化函数被触发if(point>=0){varmantissa=newValue.切片(点+1);varsecondPoint=mantissa.indexOf(".");if(mantissa.length>=2||secondPoint>=0){scope.price=self.format(newValue);}}else{scope.price=newValue;}scope.ngModel=parseFloat(scope.price)*100;//元转分}...}效果图:完整代码:angular.module('webappApp').directive('yunzhiPrice',function($timeout){return{//独立作用域scope:{ngModel:'=',//绑定价格(以`cent`为单位)name:'@?',//输入框的name属性,使用'@'获取需要的name属性的值:'=?'//表单验证,默认为true;如果不想验证,设置为false},templateUrl:'/views/directive/yunzhiPrice.html',restrict:'E',link:functionpostLink(scope){varself=this;//initializeself.init=function(){//这里是由于初始渲染时,ngModel没有值,会延迟一段时间再赋初始值$timeout(function(){scope.price=self.format((scope.ngModel/100).toString());//实际显示的价格(in'yuan')},100);scope.$watch('价格',self.watchPrice);scope.$watch('ngModel',self.watchModel);};//默认验证if(typeof(scope.required)==='undefined'){scope.required=true;}//观察价格self.watchPrice=function(newValue){if(newValue){varpoint=newValue.indexOf(".");//获取小数点的位置//出现输入时阻止输入当有整数时,小数点会自动补全//所以这里只有当小数点后位数超过两位//或者有两个小数点时,才会触发格式化函数if(point>=0){varmantissa=newValue.slice(point+1);varsecondPoint=mantissa.indexOf(".");if(mantissa.length>=2||secondPoint>=0){scope.price=self.format(newValue);}如果typeof(scope.price)==='undefined'){scope.ngModel=0;}};//监控ngModelself.watchModel=function(newValue){如果(newValue){scope.price=(newValue/100).toString();}};//价格格式化函数//整数:末尾加'.00'//小数点后一位:加0//小数点后两位:不变//多于两位数:只截取两位数self.format=function(price){//获取小数点后的数字并计算长度varfirstPoint=price.indexOf(".");//获取小数点的位置if(firstPoint>=0){varmantissa=price.slice(firstPoint+1);varsecondPoint=mantissa.indexOf(".");//获取第二个小数点的位置,防止如果输入了两个或更多的小数点if(secondPoint<0){//如果有两个以上的小数点,去掉下面的if(mantissa.length>=2){returnprice.slice(0,firstPoint+3);}elseif(mantissa.length===1){返回价格+'0';}}else{//去掉第二个小数点returnprice.slice(0,firstPoint+secondPoint+1);}}else{返回价格+'.00';}};自我初始化();}};});总结每一个复杂的问题,只要拆分成简单的小问题,就会变得简单
