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实现表格合并功能
Dec 01 Vue.js
element-plus一个vue3.xUI框架(element-ui的3.x 版初体验)
Dec 02 Vue.js
vue 通过base64实现图片下载功能
Dec 19 Vue.js
vue中如何添加百度统计代码
Dec 19 Vue.js
vue中watch的用法汇总
Dec 28 Vue.js
vscode自定义vue模板的实现
Jan 27 Vue.js
Vue中使用wangeditor富文本编辑的问题
Feb 07 Vue.js
使用Vue.js和MJML创建响应式电子邮件
Mar 23 Vue.js
Vue全局事件总线你了解吗
Feb 24 Vue.js
VUE之图片Base64编码使用ElementUI组件上传
Apr 09 Vue.js
vue生命周期钩子函数以及触发时机
Apr 26 Vue.js
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
Apr 30 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加速 eAccelerator配置和使用指南
2009/06/05 PHP
PHP 读取大文件的X行到Y行内容的实现代码
2013/06/24 PHP
php使用fgetcsv读取csv文件出现乱码的解决方法
2014/11/08 PHP
php实现encode64编码类实例
2015/03/24 PHP
PHP编程获取各个时间段具体时间的方法
2017/05/26 PHP
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
Extjs 4.x 得到form CheckBox 复选框的值
2014/05/04 Javascript
javascript实现类似百度分享功能的方法
2015/07/27 Javascript
js实现文字垂直滚动和鼠标悬停效果
2015/12/31 Javascript
setTimeout学习小结
2017/02/08 Javascript
Nodejs中Express 常用中间件 body-parser 实现解析
2017/05/22 NodeJs
jQuery Collapse1.1.0折叠插件简单使用
2017/08/28 jQuery
JavaScript实现快速排序的方法分析
2018/01/10 Javascript
基于Node的Axure文件在线预览的实现代码
2019/08/28 Javascript
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
python 不关闭控制台的实现方法
2011/10/23 Python
实例讲解Python中函数的调用与定义
2016/03/14 Python
Python对文件操作知识汇总
2016/05/15 Python
Python虚拟环境virtualenv的安装与使用详解
2017/05/28 Python
基于python中staticmethod和classmethod的区别(详解)
2017/10/24 Python
Python使用try except处理程序异常的三种常用方法分析
2018/09/05 Python
使用 Python 实现简单的 switch/case 语句的方法
2018/09/17 Python
Python3 安装PyQt5及exe打包图文教程
2019/01/08 Python
5款Python程序员高频使用开发工具推荐
2019/04/10 Python
Python3.5字符串常用操作实例详解
2019/05/01 Python
使用Keras加载含有自定义层或函数的模型操作
2020/06/10 Python
新加坡交友网站:be2新加坡
2019/04/10 全球购物
学生学习总结的自我评价
2013/10/22 职场文书
毕业生自荐信
2013/12/14 职场文书
房屋改造计划书
2014/01/10 职场文书
办理生育手续介绍信
2014/01/14 职场文书
团结友爱主题班会
2015/08/13 职场文书
2016党员干部政治学习心得体会
2016/01/23 职场文书
2016中秋晚会开幕词
2016/03/03 职场文书
springboot利用redis、Redisson处理并发问题的操作
2021/06/18 Java/Android
python解析照片拍摄时间进行图片整理
2022/07/23 Python