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动态合并单元格并添加小计合计功能示例
Nov 26 Vue.js
使用vue编写h5公众号跳转小程序的实现代码
Nov 27 Vue.js
vue+openlayers绘制省市边界线
Dec 24 Vue.js
详解实现vue的数据响应式原理
Jan 20 Vue.js
Vue中的nextTick作用和几个简单的使用场景
Jan 25 Vue.js
Vue中避免滥用this去读取data中数据
Mar 02 Vue.js
vue 数据双向绑定的实现方法
Mar 04 Vue.js
vue-cropper组件实现图片切割上传
May 27 Vue.js
vue3使用vue-router的完整步骤记录
Jun 20 Vue.js
详细聊聊vue中组件的props属性
Nov 02 Vue.js
三种方式清除vue路由跳转router-link的历史记录
Apr 10 Vue.js
VUE递归树形实现多级列表
Jul 15 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实现下载CSS文件中的图片
2015/12/06 PHP
jquery 常用操作方法
2010/01/28 Javascript
让mayfish支持mysqli数据库驱动的实现方法
2010/05/22 Javascript
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
侧栏跟随滚动的简单实现代码
2013/03/18 Javascript
Extjs grid添加一个图片状态或者按钮的方法
2014/04/03 Javascript
javascript实现框架高度随内容改变的方法
2015/07/23 Javascript
JavaScript获取当前cpu使用率的方法
2015/12/15 Javascript
JavaScript核心语法总结(推荐)
2016/06/02 Javascript
详解使用JS如何制作简单的ASCII图与单极图
2017/03/31 Javascript
JS将unicode码转中文方法
2017/05/08 Javascript
ionic3 懒加载
2017/08/16 Javascript
Vue+Vux项目实践完整代码
2017/11/30 Javascript
利用Javascript获取选择文本所在的句子详解
2017/12/03 Javascript
vue实现导航栏效果(选中状态刷新不消失)
2017/12/13 Javascript
基于AngularJs select绑定数字类型的问题
2018/10/08 Javascript
VUE项目中加载已保存的笔记实例方法
2019/09/14 Javascript
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
python机器学习之决策树分类详解
2017/12/20 Python
numpy 进行数组拼接,分别在行和列上合并的实例
2018/05/08 Python
pandas DataFrame实现几列数据合并成为新的一列方法
2018/06/08 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
Python3.5实现的罗马数字转换成整数功能示例
2019/02/25 Python
Django框架之DRF 基于mixins来封装的视图详解
2019/07/23 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
2020/05/19 Python
Python数据分析库pandas高级接口dt的使用详解
2020/12/11 Python
Python操作PostgreSql数据库的方法(基本的增删改查)
2020/12/29 Python
个性化皮包、小袋、生活配件:Mon Purse
2019/03/26 全球购物
SneakerStudio英国:最佳运动鞋商店
2019/05/22 全球购物
大二学生学习个人自我评价
2014/01/19 职场文书
机械设计毕业生自荐信
2014/02/02 职场文书
小学生检讨书大全
2014/02/06 职场文书
同学聚会策划方案
2014/06/06 职场文书
我们的节日元宵活动方案
2014/08/23 职场文书
运动会100米加油稿
2015/07/21 职场文书
MySQL 常见存储引擎的优劣
2021/06/02 MySQL