JavaScript解决浮点数计算不准确问题的方法分析,Angular通过指令动态添加组件问题

韦德国际官网,  开始做的时候,主要是对这几个类比较懵,ViewContainerRef、ComponentRef、ComponentFactory、ComponentFactoryResolver等,看看源码,查查资料,总会梳理清楚的。

首先我们分析一下为什么会出现这个精度误差?

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
     content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>www.jb51.net 绑定事件监听器</title>
  <!-- Vue.js -->
  <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="app">
  <p v-if="show">这是一段文本</p>
  <buttton v-on:click="handleClose">点击隐藏</buttton>
</div>
</body>
</html>
<script>
  //当数据show的值为true时,p元素会被插入,为false时会被移除
  var myData = {
    show:true
  };
  var app = new Vue({
    el:'#app',
    data:myData,
    //在普通元素上,v-on可以监听原生的DOM事件,除了click外,还有dbclick、keyup、mousemove等。表达式可以是一个方法名,这些方法都写在vue实例的methods属性内,并且是函数的形式,函数内的this指向的是当前vue实例本身,因此可以直接使用this.xxx的形式来访问或者修改数据,如实例中的this.show = false;把数据show修改为了false,所以点击按钮时,文本p元素就被移除了
    methods:{
      handleClose:function () {
//        this.show = false
        //在handleClose方法内,直接通过close()调用了close函数。在示例中是多此一举的,只是用于演示它的用法
        this.close()
      },
      close:function () {
        this.show = false
      }
    }
  })
</script>
import { Input , Directive , ViewContainerRef , ComponentRef, ComponentFactory, HostListener , ComponentFactoryResolver} from '@angular/core';
import { HovertipComponent } from './hovertip.component';
@Directive({
 selector: '[appHovertip]'
})
export class HovertipDirective {
 public hovertip: ComponentRef<HovertipComponent>;
 public factory: ComponentFactory<HovertipComponent>;
 constructor(
 private viewContainer: ViewContainerRef,
 private resolver: ComponentFactoryResolver
 ) {
 // 获取对应的组件工厂
 this.factory = this.resolver.resolveComponentFactory(HovertipComponent);
 }
 @Input('appHovertip') tipText: string;
 
 // 绑定鼠标移入的事件
 @HostListener('mouseenter') onmouseenter() {
   // 清空所有的view 
   this.viewContainer.clear();
 // 创建组件
 this.hovertip = this.viewContainer.createComponent(this.factory);
 // 向组件实例传递参数
 this.hovertip.instance.tipText = this.tipText;
 }
 
 // 绑定鼠标移出时的事件
 @HostListener('mouseleave') onmouseleave() {
 if (this.hovertip) {
  // 组件销毁
 this.hovertip.destroy();
 }
 }
}

0.1+0.2=?

再来看一个例子:

知道了浮点数产生的原因,那么如何处理这个问题呢?

您可能感兴趣的文章:

  • vue监听滚动事件实现滚动监听
  • Vue.js实战之通过监听滚动事件实现动态锚点
  • 详解使用vue-router进行页面切换时滚动条位置与滚动监听事件
  • Vue.JS入门教程之事件监听
  • vue v-on监听事件详解
  • 浅谈VUE监听窗口变化事件的问题
  • vue2.x
    父组件监听子组件事件并传回信息的方法
  • 基于vue监听滚动事件实现锚点链接平滑滚动的方法
  • vue.js过滤器+ajax实现事件监听及后台php数据交互实例
  • vue的事件绑定与方法详解

  在目标元素是绑定指令,同时传递tipText即可。

/*判断obj是否为一个整数*/
function isInteger(obj){
  return Math.floor(obj) === obj;
}
/**
* 将一个浮点数转换成整数,返回整数和倍数
* 如 3.14 》》314 倍数是100
*
*/
function toInteger(floatNum){
  var ret = {times:1,num:0};
  //是整数
  if(isInteger(floatNum)){
    ret.num = floatNum;
    return ret;
  }
  var strfi = floatNum + '';
  //查找小数点的下标
  var dotPos = strfi.indexOf('.');
  console.log('dotPos===='+dotPos);
  //获取小数的位数
  var len = strfi.substr(dotPos+1).length;
  console.log('len===='+len);
  //Math.pow(10,len)指定10的len次幂。
  var time = Math.pow(10,len);
  //将浮点数转化为整数
  var intNum = parseInt(floatNum*time + 0.5,10);
  console.log('intNum===='+intNum);
  ret.times = time;
  ret.num = intNum;
  return ret;
}
/**
*进行运算
*三个参数分别是要运算的两个数和运算符
*/
function operation(a,b,op){
  var o1 = toInteger(a);
  var o2 = toInteger(b);
  var n1 = o1.num;
  var n2 = o2.num;
  var t1 = o1.times;
  var t2 = o2.times;
  var max = t1 > t2 ? t1 : t2;
  var result = null;
  switch(op){
    case 'add':
      if(t1 === t2){
        result = n1 + n2;
      }else if(t1 > t2){
        result = n1 + n2 * (t1/t2);
      }else{
        result = n1 * (t2/t1) + n2;
      }
      return result / max;
      break;
    case 'subtract':
      if(t1 === t2){
        result = n1 - n2;
      }else if(t1 > t2){
        result = n1 - n2 * (t1/t2);
      }else{
        result = n1 * (t2/t1) - n2;
      }
      return result / max;
      break;
    case 'multiply':
      result = (n1 * n2)/(t1 * t2);
      return result;
      break;
    case 'divide':
      result = (n1 / n2)/(t2 / t1);
      return result;
      break;
  }
}

使用本站HTML/CSS/JS在线运行测试工具:,可得到如下测试运行效果:

韦德国际官网 1

方法1:通过toFixed(num)方法来保留小数。因为这个方法是根据四舍五入来保留小数的,所以最后的计算结果不精确。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vue</title>
    <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
  </head>
  <body>
    <div id="test">{{msg}}
      <p v-for="val in arr">
        {{val.a}}
      </p>
      <a href="javascript:void(0)" rel="external nofollow" v-on:click="tap">点我</a>
    </div>
  </body>
</html>
<script>
  // window.onload= function(){
    var app2 = new Vue ({
      el:"#test",
      data:{
        msg:'润元装饰',
        msg1:"家装"+new Date(),
        msg2:'lianxi',
        show:true,
        arr:[
          {a:'bb'},
          {a:'cc'}
        ]
      },
      methods:{
        tap : function(){
          this.arr.unshift({a:'new'})
        }
      }
    })
  // }
</script>
<aside class="hover-tip-wrapper">
 {{tipText}}
</aside>


import { Component, OnInit } from '@angular/core';
@Component({
 selector: 'app-hovertip',
 templateUrl: './hovertip.component.html',
 styleUrls: ['./hovertip.component.scss']
})
export class HovertipComponent implements OnInit {
 public tipText: string;
 constructor() { }
 ngOnInit() {
 }
}


.hover-tip-wrapper{
 width: max-content;
 position: absolute;
 height: 30px;
 line-height: 30px;
 bottom: calc(100% + 5px);
 right: calc( -10px - 100%);
 background-color: rgba(#000000,.8);
 padding: 0 5px;
 border-radius: 3px;
 &::after{
 content: '';
 position: absolute;
 height: 0;
 width: 0;
 border: 4px solid transparent;
 border-top-color: rgba(#000000,.8);
 left: 10px;
 top: 100%;
 }
 span {
 color: #ccc;
 font-size: 12px;
 }
}

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript事件相关操作与技巧大全》、《JavaScript操作DOM技巧总结》及《JavaScript字符与字符串操作技巧总结》

韦德国际官网 2

创建组件

方法2:把要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,计算完以后再降级,推荐使用这一种方法。具体代码如下(主要有3个方法):

本文实例讲述了vue.js绑定事件监听器。分享给大家供大家参考,具体如下:

之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态、值、回调函数什么的。但是有一些场景不适合这种方式,还是动态添加组件更加好。通过写过的一个小组件来总结下。

输出结果是:0.30000000000000004。

希望本文所述对大家vue.js程序设计有所帮助。

上面我们发现0.1和0.2转化为二进制之后,变成了一个无限循环的数字,这在现实生活中,无限循环我们可以理解,但计算机是不允许无限循环的,对于无限循环的小数,计算机会进行舍入处理。进行双精度浮点数的小数部分最多支持52位,所以两者相加之后得到这么一串
0.0100110011001100110011001100110011001100110011001100
因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了
0.30000000000000004。

该示例可响应鼠标点击自动增加元素,感兴趣的朋友可以使用HTML/CSS/JS在线运行测试工具:测试一下效果。

韦德国际官网 3

为什么会这样呢?

发表评论

电子邮件地址不会被公开。 必填项已用*标注