vue3使用vue-count-to組件的實現(xiàn)
項目場景:
數(shù)據(jù)可視化大屏開發(fā)的過程中,需要實現(xiàn)一種滾動數(shù)字的效果,在使用vue2時,使用vue-count-to完全沒有問題,功能也比較完善(滾動時長,開始值,結(jié)束值,前綴,后綴,千分隔符,小數(shù)分隔符等等),但是在vue3中使用會出現(xiàn)問題。
<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>
展示的效果

問題描述:
出現(xiàn)的錯誤時 == Cannot read property ‘_c' of undefined== 這是一個_c的屬性沒有找到,具體的情況也不是很清楚。在vue-count-to打包后的源碼中可以大致看出來,這是在render函數(shù)中出現(xiàn)的錯誤。但是還是沒法下手。

解決方案:
采用的方法是直接復(fù)制node_modules下vue-count-to的源文件(src下),到自己項目的components下。如圖

然后根據(jù)eslint的檢查,修改代碼,直到不報錯,且記刪除package.json下剛剛引入的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在當(dāng)前瀏覽器的實現(xiàn)形式
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']
}
// 如果當(dāng)前瀏覽器不支持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>
到此這篇關(guān)于vue3使用vue-count-to組件的文章就介紹到這了,更多相關(guān)vue3 vue-count-to組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 使用vant插件做tabs切換和無限加載功能的實現(xiàn)
這篇文章主要介紹了vue 使用vant插件做tabs切換和無限加載功能的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
vue實現(xiàn)把頁面導(dǎo)出成word文件的方法
這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)把頁面導(dǎo)出成word文件的方法,文中的實現(xiàn)步驟講解詳細(xì),并且有詳細(xì)的代碼示例,需要的小伙伴可以參考一下2023-10-10
vue中vite.config.js配置跨域以及環(huán)境配置方式
這篇文章主要介紹了vue中vite.config.js配置跨域以及環(huán)境配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
vue+elementUi中的table實現(xiàn)跨頁多選功能(示例詳解)
最近在開發(fā)工業(yè)品超市的后臺系統(tǒng),遇到一個需求,就是實現(xiàn)在一個table表格中多選數(shù)據(jù),在網(wǎng)上查了好多,有些方法真的是無語,下面通過本文給大家分享vue+elementUi中的table實現(xiàn)跨頁多選功能,感興趣的朋友跟隨小編一起看看吧2024-05-05

