vue3使用vue-count-to组件的实现


Posted in Vue.js onDecember 25, 2020

项目场景:

数据可视化大屏开发的过程中,需要实现一种滚动数字的效果,在使用vue2时,使用vue-count-to完全没有问题,功能也比较完善(滚动时长,开始值,结束值,前缀,后缀,千分隔符,小数分隔符等等),但是在vue3中使用会出现问题。

<template>
 <div id="nav">
 <router-link to="/">Home</router-link> |
 <router-link to="/about">About</router-link>
 </div>
 <count-to :startVal="0" :endVal="2045" :duration="4000"></count-to>
 <router-view/>
</template>

展示的效果

vue3使用vue-count-to组件的实现

问题描述:

出现的错误时 == Cannot read property ‘_c' of undefined== 这是一个_c的属性没有找到,具体的情况也不是很清楚。在vue-count-to打包后的源码中可以大致看出来,这是在render函数中出现的错误。但是还是没法下手。

vue3使用vue-count-to组件的实现

解决方案:

采用的方法是直接复制node_modules下vue-count-to的源文件(src下),到自己项目的components下。如图

vue3使用vue-count-to组件的实现

然后根据eslint的检查,修改代码,直到不报错,且记删除package.json下刚刚引入的vue-count-to的依赖。如图

vue3使用vue-count-to组件的实现

最后重启项目。

vue-count-to源码

let lastTime = 0
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀

let requestAnimationFrame
let cancelAnimationFrame

const isServer = typeof window === 'undefined'
if (isServer) {
 requestAnimationFrame = function () {
 }
 cancelAnimationFrame = function () {
 }
} else {
 requestAnimationFrame = window.requestAnimationFrame
 cancelAnimationFrame = window.cancelAnimationFrame
 let prefix
 // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
 for (let i = 0; i < prefixes.length; i++) {
 if (requestAnimationFrame && cancelAnimationFrame) { break }
 prefix = prefixes[i]
 requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
 cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
 }

 // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
 if (!requestAnimationFrame || !cancelAnimationFrame) {
 requestAnimationFrame = function (callback) {
 const currTime = new Date().getTime()
 // 为了使setTimteout的尽可能的接近每秒60帧的效果
 const timeToCall = Math.max(0, 16 - (currTime - lastTime))
 const id = window.setTimeout(() => {
 const time = currTime + timeToCall
 callback(time)
 }, timeToCall)
 lastTime = currTime + timeToCall
 return id
 }

 cancelAnimationFrame = function (id) {
 window.clearTimeout(id)
 }
 }
}

export { requestAnimationFrame, cancelAnimationFrame }
<template>
 <span>
 {{displayValue}}
 </span>
</template>
<script>
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
export default {
 props: {
 startVal: {
 type: Number,
 required: false,
 default: 0
 },
 endVal: {
 type: Number,
 required: false,
 default: 2017
 },
 duration: {
 type: Number,
 required: false,
 default: 3000
 },
 autoplay: {
 type: Boolean,
 required: false,
 default: true
 },
 decimals: {
 type: Number,
 required: false,
 default: 0,
 validator (value) {
 return value >= 0
 }
 },
 decimal: {
 type: String,
 required: false,
 default: '.'
 },
 separator: {
 type: String,
 required: false,
 default: ','
 },
 prefix: {
 type: String,
 required: false,
 default: ''
 },
 suffix: {
 type: String,
 required: false,
 default: ''
 },
 useEasing: {
 type: Boolean,
 required: false,
 default: true
 },
 easingFn: {
 type: Function,
 default (t, b, c, d) {
 return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b
 }
 }
 },
 data () {
 return {
 localStartVal: this.startVal,
 displayValue: this.formatNumber(this.startVal),
 printVal: null,
 paused: false,
 localDuration: this.duration,
 startTime: null,
 timestamp: null,
 remaining: null,
 rAF: null
 }
 },
 computed: {
 countDown () {
 return this.startVal > this.endVal
 }
 },
 watch: {
 startVal () {
 if (this.autoplay) {
 this.start()
 }
 },
 endVal () {
 if (this.autoplay) {
 this.start()
 }
 }
 },
 mounted () {
 if (this.autoplay) {
 this.start()
 }
 this.$emit('mountedCallback')
 },
 methods: {
 start () {
 this.localStartVal = this.startVal
 this.startTime = null
 this.localDuration = this.duration
 this.paused = false
 this.rAF = requestAnimationFrame(this.count)
 },
 pauseResume () {
 if (this.paused) {
 this.resume()
 this.paused = false
 } else {
 this.pause()
 this.paused = true
 }
 },
 pause () {
 cancelAnimationFrame(this.rAF)
 },
 resume () {
 this.startTime = null
 this.localDuration = +this.remaining
 this.localStartVal = +this.printVal
 requestAnimationFrame(this.count)
 },
 reset () {
 this.startTime = null
 cancelAnimationFrame(this.rAF)
 this.displayValue = this.formatNumber(this.startVal)
 },
 count (timestamp) {
 if (!this.startTime) this.startTime = timestamp
 this.timestamp = timestamp
 const progress = timestamp - this.startTime
 this.remaining = this.localDuration - progress

 if (this.useEasing) {
 if (this.countDown) {
 this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration)
 } else {
 this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration)
 }
 } else {
 if (this.countDown) {
 this.printVal = this.localStartVal - ((this.localStartVal - this.endVal) * (progress / this.localDuration))
 } else {
 this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration)
 }
 }
 if (this.countDown) {
 this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal
 } else {
 this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal
 }

 this.displayValue = this.formatNumber(this.printVal)
 if (progress < this.localDuration) {
 this.rAF = requestAnimationFrame(this.count)
 } else {
 this.$emit('callback')
 }
 },
 isNumber (val) {
 return !isNaN(parseFloat(val))
 },
 formatNumber (num) {
 num = num.toFixed(this.decimals)
 num += ''
 const x = num.split('.')
 let x1 = x[0]
 const x2 = x.length > 1 ? this.decimal + x[1] : ''
 const rgx = /(\d+)(\d{3})/
 if (this.separator && !this.isNumber(this.separator)) {
 while (rgx.test(x1)) {
 x1 = x1.replace(rgx, '$1' + this.separator + '$2')
 }
 }
 return this.prefix + x1 + x2 + this.suffix
 }
 },
 unmounted () {
 cancelAnimationFrame(this.rAF)
 }
}
</script>

到此这篇关于vue3使用vue-count-to组件的文章就介绍到这了,更多相关vue3 vue-count-to组件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
Vue项目如何引入bootstrap、elementUI、echarts
Nov 26 Vue.js
Vue-router中hash模式与history模式的区别详解
Dec 15 Vue.js
Vue仿百度搜索功能
Dec 28 Vue.js
Vue中ref和$refs的介绍以及使用方法示例
Jan 11 Vue.js
vue-resource 拦截器interceptors使用详解
Jan 18 Vue.js
Vue 实现可视化拖拽页面编辑器
Feb 01 Vue.js
Vue实现下拉加载更多
May 09 Vue.js
解决Vue+SpringBoot+Shiro跨域问题
Jun 09 Vue.js
vue中利用mqtt服务端实现即时通讯的步骤记录
Jul 01 Vue.js
Vue2.0搭建脚手架
Mar 13 Vue.js
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
vue3语法糖内的defineProps及defineEmits
Apr 14 Vue.js
vue+openlayers绘制省市边界线
Dec 24 #Vue.js
vue项目中openlayers绘制行政区划
Dec 24 #Vue.js
Vue+penlayers实现多边形绘制及展示
Dec 24 #Vue.js
Vue使用鼠标在Canvas上绘制矩形
Dec 24 #Vue.js
vue绑定class的三种方法
Dec 24 #Vue.js
全面解析Vue中的$nextTick
Dec 24 #Vue.js
vue实现登录、注册、退出、跳转等功能
Dec 23 #Vue.js
You might like
php常用hash加密函数
2014/11/22 PHP
php+mysql删除指定编号员工信息的方法
2015/01/14 PHP
PHP5.2中PDO的简单使用方法
2016/03/25 PHP
php反射类ReflectionClass用法分析
2016/05/12 PHP
Save a File Using a File Save Dialog Box
2007/06/18 Javascript
什么是DOM(Document Object Model)文档对象模型
2012/03/05 Javascript
javascript打印大全(打印页面设置/打印预览代码)
2013/03/29 Javascript
将nodejs打包工具整合到鼠标右键的方法
2013/05/11 NodeJs
原生javascript和jquery判断浏览器版本等信息
2013/07/04 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
js使用Array.prototype.sort()对数组对象排序的方法
2015/01/28 Javascript
JS利用cookie记忆当前位置的防刷新导航效果
2015/10/15 Javascript
Node.js中process模块常用的属性和方法
2016/12/13 Javascript
H5图片压缩与上传实例
2017/04/21 Javascript
深究AngularJS中$sce的使用
2017/06/12 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
2017/06/26 Javascript
javascript设计模式 ? 职责链模式原理与用法实例分析
2020/04/16 Javascript
js动态生成表格(节点操作)
2021/01/12 Javascript
[07:43]《辉夜杯》公开赛晋级外卡赛战队—TRG训练生活探秘
2015/12/11 DOTA
[33:42]LGD vs OG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python修改操作系统时间的方法
2015/05/18 Python
Python正则表达式常用函数总结
2017/06/24 Python
python实现ID3决策树算法
2017/12/20 Python
Pycharm 设置自定义背景颜色的图文教程
2018/05/23 Python
对python操作kafka写入json数据的简单demo分享
2018/12/27 Python
Python基于WordCloud制作词云图
2019/11/29 Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
2019/12/12 Python
Python跑循环时内存泄露的解决方法
2020/01/13 Python
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
介绍一下grep命令的使用
2012/06/28 面试题
园长自我鉴定
2013/10/06 职场文书
英文版销售经理个人求职信
2013/11/20 职场文书
中学教师自我鉴定
2014/02/07 职场文书
教师自我剖析材料(群众路线)
2014/09/29 职场文书
考研英语复习计划
2015/01/19 职场文书
初中班主任工作随笔
2015/08/15 职场文书