Vue组件封装之数字滚动组件

数字滚动组件:包含千分位

index.vue

<template>
    <div class="num" :style="'font-size:'+size+'px;'">
        <span v-if="minus">-</span>
        <number-son v-for="(p, i) in intArr" :key="i" :num="p" :time="time" />
        <span v-if="fixed > 0">.</span>
        <number-son v-for="(p, i) in floatArr" :key="i" :num="p" :time="time" />
    </div>
</template>
<script lang="ts">
    import { defineComponent, ref, watch, toRefs } from "vue";
    import NumberSon from "./NumberSon.vue";
    export default defineComponent({
        name: "Number",
        components: {
            NumberSon,
        },
        props: {
            num: {
                type: [Number, String],
                default: 0,
            }, //数值
            size: {
                type: Number,
                default: 28,
            }, //大小
            fixed: {
                type: Number,
                default: 0,
            }, //保留小数位,默认0
            thousands: {
                type: Boolean,
                default: false,
            }, //是否添加千分位符,默认false
            time: {
                type: Number,
                default: 400,
            }, //翻转时间,默认400
        },
        setup(props) {
            const { num } = toRefs(props);
            let fixed: number = Number(props.fixed) || 0;
            let thousands: boolean = Boolean(props.thousands) || false;
            let time: any = Number(props.time) > 0 ? ref(Number(props.time)) : 400;

            let arr: any = [];
            let floatArr: any = ref([]);
            let intArr: any = ref([]);
            let minus: any = ref(false);

            // 数据处理
            let dispose = (data: any) => {
                if (data < 0) {
                    minus = true;
                    data = -data;
                }
                let datas: any = String(data);
                // 分离整数、小数
                if (datas.indexOf(".") != -1) {
                    arr = datas.split(".");
                    floatArr.value = arr[1].split(""); //[string]
                } else {
                    arr[0] = datas;
                    arr[1] = "";
                }
                intArr.value = arr[0].split(""); // [string]

                if (thousands == true && intArr.value.length > 3) {
                    // 整数——添加千分位
                    let k = 0;
                    let b = [];
                    for (let i = 0; i < intArr.value.length; i++) {
                        // 类型转换
                        b[k] = Number(intArr.value[i]);
                        k++;
                        if (
                            i < intArr.value.length - 1 &&
                            (intArr.value.length - i - 1) % 3 == 0
                        ) {
                            b[k] = ",";
                            k++;
                        }
                    }
                    intArr.value = b;
                } else {
                    for (let i = 0; i < intArr.value.length; i++) {
                        intArr.value[i] = Number(intArr.value[i]);
                    }
                }
                // 保留小数位数
                let a = [];
                for (let i = 0; i < fixed; i++) {
                    if (floatArr.value[i]) {
                        a[i] = Number(floatArr.value[i]);
                    } else {
                        a[i] = 0;
                    }
                }
                floatArr.value = a;
            };

            // 初始化
            dispose(num.value);
            // 监听
            watch(
                num,
                (newVal, oldVal) => {
                    arr = [];
                    floatArr.value = [];
                    intArr.value = [];
                    minus = false;
                    dispose(newVal);
                },
                { deep: true }
            );
            return { minus, intArr, floatArr, fixed, time };
        },
    });
</script>

<style scoped>
.num {
    /* font-size: 28px; */
}
</style>

滚动组件number-scroll:

<template>
  {{ data }}
</template>
<script lang="ts">
import { defineComponent, ref, watch, toRefs, onMounted, onUnmounted } from "vue";

export default defineComponent({
  name: "Number",
  props: {
    num: [Number, String],
    time: Number,
  },
  setup(props) {
    const { num } = toRefs(props);
    const time: any = ref(props.time);
    let data: any = ref(0);
    let animation:any;
    let transition = (num: any) => {
      // 判断是数字、逗号
      if (typeof num == "number") {
        let lastTime = 0;
        const val = time.value / num;
        
        function transitionInt(time: number) {
          let interval = time - lastTime;
          if (interval > val) {
            lastTime = time;
            // 整数
            if (num == 0) {
              data.value = data.value;
            } else {
              data.value += 1;
            }
          }

          if (data.value < num) {
            // 形成回调
            window.requestAnimationFrame(transitionInt);
          }
        }
        // 启动动画
        animation=window.requestAnimationFrame(transitionInt);
        // 当浏览器切换到后台后,requestAnimationFrame是不会再去执行事件了
      } else {
        data.value = num;
      }
    };
    onMounted(() => {
      transition(num.value);
    });
    onUnmounted(()=>{
      window.cancelAnimationFrame(animation)
    })
    watch(
      num,
      (newVal, oldVal) => {
        data.value=0;
        transition(newVal);
      },
      { deep: true }
    );
    return { data };
  },
});
</script>
<style scoped>
.son {
  display: inline-block;
}
</style>

  

posted @ 2021-09-21 19:51  TangTaue  阅读(252)  评论(0编辑  收藏  举报