- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563247 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174197
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效0 L) q" S3 ~( C& K
; U3 U/ P1 L3 U8 e# I1 l" }$ C/ c前言% \1 S3 Z9 ?$ @1 D i
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:6 Z7 a+ t: \' O+ w- v. S& b" R
TypeError: Cannot read properties of undefined (reading '_c')
% y- M$ e4 G* S& I的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:5 x' Z: k* H5 E. M+ [& X
' i9 u& @2 f2 @6 s2 y. ]
! [" o o( h; u0 V/ Y3 R9 |
思路
: d( t3 B; X( |- \* s使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。- V( R. @( p: F! [
# a- i9 i" O1 y" w% ~% n
文件目录
8 L: a, w1 \" I4 v; Z8 t
8 m; ^; w$ G' {; N4 F9 h
- O+ U5 d/ E' T/ u1 u0 Z& f5 q使用示例5 c' _- @9 p! q
<CountTo( F8 x( P+ B8 W* p) j0 P
:start="0" // 从数字多少开始9 @' ]& l, C2 b2 a2 j! {
:end="endCount" // 到数字多少结束* ~( _ k* H% K/ [
:autoPlay="true" // 自动播放
* \& _9 W3 ~/ { :duration="3000" // 过渡时间4 z" J( }8 ]+ A
prefix="¥" // 前缀符号
, f' z. U4 F, E9 B suffix="rmb" // 后缀符号( J2 E# x+ H! P' |9 \
/>
3 x( Y+ B8 x* C! a; A" u/ ~16 ?! Y; `9 I' N" L* z
2
! w% Z" X8 L0 M" l* T3
4 f6 S7 r1 M9 V1 j7 H' Y4: O. n+ E: k+ P- m; ^
5
0 W! y9 t g3 u& v* R' j! Y6
2 r, B' V& {$ u7
t# A Z# s: o0 [( p# J+ p8
4 D+ G& Z( V# l8 k& Z/ J0 L% B- d入口文件index.js
# _1 g2 ?" y# u) A, y( C# Z
* B/ b Z) k( yconst UILib = {
& J) K6 i& l2 S" \6 `) E/ ~" x install(Vue) {
( a( E( w, c9 u5 k( j Vue.component('CountTo', CountTo)) s+ T, C# S& S/ [! n% r
}
8 s' [7 g% \& x" r( X4 j" _8 b* h ~}2 F3 c: Y' k0 `( V; f
( p. |8 v% k- }3 Nexport default UILib
$ @% e% V+ t T' s; Y! e
|2 [7 s9 f* d+ c+ K& I! r# L19 x2 C7 `+ u$ X! m2 Q4 x
2
" i- k, A2 a: O6 G' R8 q3
' I$ u) ]: }+ _3 x4$ J- H5 U* J y! O! m) q
5, j+ @9 K) s# o& z3 h
6$ M! B; r- \3 {5 c0 u5 N* \
7: ~; `. U1 ^* p! i
8
8 z" p+ M& X/ {, V0 S9
9 w% y5 Q$ f; f/ X4 e" P3 q( {* W) @main.js使用, I! b+ L+ D! v: a4 K* G
import CountTo from './components/count-to/index';" q, C% W( U& r8 A8 s4 ^
app.use(CountTo)
( Q: |+ Y7 Q" u% ^1' k0 [# k3 T2 I% C* ?
2
+ ]. r \3 K+ |: ^ @6 mrequestAnimationFrame.js思路! P( |% d+ P: c( i8 d# g
先判断是不是浏览器还是其他环境
/ ^# m2 i# j7 J9 w如果是浏览器判断浏览器内核类型
8 i4 X! y) i+ N: z1 J9 j; t如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器4 f7 U& Z0 ~# y' B0 p# o# r
导出两个方法 requestAnimationFrame, cancelAnimationFrame
" n! w1 |, X3 G- V o# S9 f" @* G2 P各个浏览器前缀:let prefixes = 'webkit moz ms o';/ p2 c1 d& M. k9 N5 @8 v' ~- u
判断是不是浏览器:let isServe = typeof window == 'undefined';' q5 G( i& F( f9 _% ^+ ? U
增加各个浏览器前缀:
) A+ y0 [6 _# |$ U) F6 Ylet prefix;
8 h S2 V2 q+ t* U! xlet requestAnimationFrame;
5 a% ~' y5 T3 V% k# p7 N8 N. [5 Dlet cancelAnimationFrame;, u2 B4 u) P6 I3 q( Z; _/ r9 {
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式4 P4 {( A- i- O2 p2 m$ i0 B
for (let i = 0; i < prefixes.length; i++) {( e; ~& }: c3 _! F7 Z" D
if (requestAnimationFrame && cancelAnimationFrame) { break }' d- E9 s# W5 X* m" s6 i5 o z; f. r
prefix = prefixes+ F* d0 U# U4 F4 M/ J2 f
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
4 r: q/ W/ ~, Z# z9 P, d2 k cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']: ?% H1 T6 M. @3 m# c
}" z/ B6 I8 o, }8 j. r: @ Z
+ M9 W9 Q9 i& v$ i3 ] //不支持使用setTimeout方式替换:模拟60帧的效果
- N/ _3 ?% I0 c+ S7 { // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout9 G# H' a) Z/ C" Q
if (!requestAnimationFrame || !cancelAnimationFrame) {* x4 B: q1 `9 d8 k* D
requestAnimationFrame = function (callback) {
5 v9 _% a: x$ j' E; P) a const currTime = new Date().getTime()7 c# J0 G ?, p; r6 ?( R' J' e( \
// 为了使setTimteout的尽可能的接近每秒60帧的效果8 [2 Q2 t9 ~8 W
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
/ u% w" H$ m, m1 ^% z; j const id = window.setTimeout(() => {7 I$ P9 {/ c N2 d( P. i v5 w
callback(currTime + timeToCall)- D7 v& I# t! _4 p5 ^
}, timeToCall)
: ? I) U+ o5 D X1 F1 d lastTime = currTime + timeToCall7 ?' } p* ~7 ]' Y* d: N# X
return id
* ^0 D! D1 E0 O3 a$ ]2 z/ { }+ _5 t5 z) R O
/ @( u% ~. M9 o) G cancelAnimationFrame = function (id) {+ R. R& {+ O, J) |
window.clearTimeout(id) k% `+ N( E( T. |6 m
}
4 O& \9 h G4 S! k W3 D }
" ~( e- e; c1 |# t6 z6 W, \4 o% s# h; W K; D
19 Y) ?: |$ ^, _: j" o
2
9 Z$ V5 H( s$ d/ L' Q' t9 k3+ V$ r+ n* b8 q1 q5 e. q% w
4
% n/ T9 o" S6 p4 o4 t5 a5# D% q3 b. M. h' ~5 y0 Z' P% H
6! k6 m2 Q8 r& p1 D8 \& }0 H5 U
7
' [% Q7 i# k% H9 j8/ U O! I+ ^$ N. u( G0 K; x
9
8 s- ]2 ?; l" P109 _; x2 {# o9 y! E3 G Y0 r& e! ~
11' A2 O7 Z, X& _1 l
12
9 o+ C4 S! ]) ?7 c H' q13
' w7 O C: D. ]. S4 y) ^14
0 _( z/ n' @) \: c; S- M15& } ^- v9 z3 _0 C+ Z& ^$ ^
16
! j) `+ \: ~$ x9 ?172 o3 [& _) E$ N8 P g
18& \" Y% W3 X2 }$ C
19
: z0 T$ ~! E% p20" _% T+ W3 n! A" o/ t: [# ?
210 O, c; [5 D- s% e* Z
22 ^9 e; h9 A3 p& w
23# {7 ~3 u) j0 a8 r) C
240 J8 [0 F8 F4 b1 ]. S! m( j
25$ L3 u7 x! N: }* ~2 C( n
26
! w/ l3 Q6 j" v27
, y. S5 ]8 p2 q9 F' t4 l% x28
% n. m1 }7 L. w% B! Y9 W l29/ M3 e9 L( y: r" b- ^5 k5 H
30
6 R: f4 c& E; Z2 r4 M" r$ O6 I31* [5 i1 U; a7 T+ C0 @4 ^
32
; E" J+ g1 j! U0 D7 v5 v. |完整代码:; y* m, ]* [ _" I7 k9 P5 A
requestAnimationFrame.js
: ~7 }0 [' j# X: [) r& o; ^! \* z! K y" C5 a( ?; f
let lastTime = 0
; n6 ]- Q. k u) v; kconst prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀3 v% d9 u' G; T' A) d# J+ ]
/ T5 _, e" y( rlet requestAnimationFrame
0 _- L9 D& K# c+ Ylet cancelAnimationFrame
) G! `1 m! e1 a) S/ W/ W
& ]; h+ u. l z k+ {$ N// 判断是否是服务器环境4 _2 D) B- O: p. w4 B2 b2 z* P. K) _
const isServer = typeof window === 'undefined'
6 i% r2 D5 k. ?" l7 c" [if (isServer) {2 o* c, ?6 h% s2 O* H- m% |
requestAnimationFrame = function () {
- O8 ~" ]2 f- h return" N6 v0 c- ~$ s9 X. }
} i0 l' s/ P; _+ v# `2 ?# t4 o
cancelAnimationFrame = function () {+ ?0 i7 H" H3 K4 h
return
9 S; k& v$ q7 F1 A$ e; ~ }
! G& O0 T: H' N7 g} else {/ b5 a/ F; L1 H6 @
requestAnimationFrame = window.requestAnimationFrame
2 c. U+ `- o8 ]! Q( f, h0 I& }$ _4 n cancelAnimationFrame = window.cancelAnimationFrame1 {! `7 ^6 C. I1 w+ G3 G) V/ Z
let prefix
: Y+ J$ @* U' l. P // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
& k7 N; _1 O) j8 h0 T for (let i = 0; i < prefixes.length; i++) {
k: S4 U. j& F& d" A. Y; ~ if (requestAnimationFrame && cancelAnimationFrame) { break }
/ q* y( B: f# a6 Y6 K3 j5 Z1 Z& ~ prefix = prefixes* |6 x) z8 x. i7 |4 g
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']. y9 s" j$ w8 k& m. V3 `' n
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']% g% Q6 j2 U" z" G; z O; J
}
_$ M3 Q% D; i! M1 K3 Q0 Y) c$ D& g: Y7 D+ _& }# Q
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout0 E% R4 J7 x7 v2 r: Q( \
if (!requestAnimationFrame || !cancelAnimationFrame) {
% X! g' N! l8 l/ ?$ G# F requestAnimationFrame = function (callback) {
s& z3 e* h% W0 x1 y const currTime = new Date().getTime()
( |! }, B$ r# c9 T8 @& p // 为了使setTimteout的尽可能的接近每秒60帧的效果
% t8 m2 g& `( ^7 {$ D6 s: u const timeToCall = Math.max(0, 16 - (currTime - lastTime))- [9 L. e9 A* y! Y% X# w
const id = window.setTimeout(() => {
) `% r# I* ~/ Q9 u7 H1 O callback(currTime + timeToCall)7 O- e8 d7 v8 t; y) R
}, timeToCall)
! I2 d! m0 c6 u1 k/ O$ z$ w lastTime = currTime + timeToCall
. c- @4 r( P/ N5 l0 H3 |- h; u0 t5 C return id
- X0 ~+ m" }+ a: |3 o7 ?+ \ }
/ }; _. v( ^: g& G3 k4 B8 S
- c* N; I4 l7 o+ k cancelAnimationFrame = function (id) {
# X( v$ x! P: c X. _* e window.clearTimeout(id)3 Z u# O6 p# @* L/ L
}
/ w1 m' N; j e! C0 B8 s }
1 A( f4 v- |5 v$ K" M/ T4 E7 n}
" c" z+ K& i( e5 i* u
# T+ q4 X, G4 o% T* Yexport { requestAnimationFrame, cancelAnimationFrame }
# q9 ?+ x: O6 S& |
& N2 M* J3 @0 W( z6 d2 p7 f
! E' m* z7 Q3 n, z0 s7 V1 p3 v1' n) h$ U9 x$ Y+ C. D
2
) }% U* _' \9 j) u' [3/ `* U" S* G* P5 @/ _
4" u/ `) v+ t8 s7 ^; e6 ?$ Y
50 n2 h4 `' K9 r* y' w8 r
69 N4 O) B+ o, p, Y& O5 J
7
2 y0 e8 r- m9 o7 {1 Z, \5 S3 R/ z8
. m4 P# g" y3 r96 t8 m' x8 Y' C$ S
109 X+ y- W' s `' b |2 z# ]# R
11
' S' d) r4 Q% d( n3 @12' [+ p t5 }& p. T
13
, M! }7 X! p8 Z0 \' v14
6 a* t3 n. L) \15
# L" `5 w* W. F2 j" Q16& }* Y, W& \0 L$ g
17
- g( u$ |6 k; D( |4 K9 T2 C18
+ F" l# C s. s* h6 s194 C4 H( ?) P2 o# q0 H* `3 f* ]6 b
209 A' z, W7 S8 u+ m9 E
21* x/ N9 d: \! U. r6 X1 |! D6 I
22* m( E, j8 O, \- G0 ?2 D( U
23$ U+ o, V/ u) p; r
240 f" l' d m$ w2 t* I$ h' e
25
- O6 u. O H4 g8 Q26% \' m) L0 t o3 L1 e+ \: x2 z
27: ]# D/ x/ r6 F+ q) f$ N. @
28+ Z I) A# Q' q" S' _' {
29
. W* F2 ?& E8 [1 d7 F9 o9 }0 b30
0 G7 i9 I' s9 Y$ v9 Q31. c5 m! S. ]+ ^/ @$ {( l
32; e I4 }. G# ?/ _( h- M- i
33* D1 O4 G% |% {9 X# X7 r: a P
346 L$ ^& W" q0 s$ n
35
" V4 M% U; J% [1 ~! s" k# H% |365 p2 r# n4 x9 z+ k% ~( C4 `
37
4 K4 }# R$ Q3 Z" t0 s38
- L. S1 Q8 p: y- O+ k39
& }4 ?& w$ ?# Q40
* E7 }7 g A8 w. G41
, k* i8 W' r* X5 l! s6 |: ]42' S# g1 o) b$ L; A9 X" Z M
43
) r3 w8 h! I* ?( h44
9 ?' K9 U) g( C8 i4 }6 x" N45
8 r. Y( @/ K) U d, O* l3 D9 ?46; h+ t ^$ P4 M4 u
47! H& d1 B" r2 {
48
4 w, G$ ~" i4 o2 F& M2 W3 gCountTo.vue组件思路: h: A4 E$ }" `; ^# _( n5 u' n
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。+ ~5 r# r K6 Y3 U1 L. B
8 y) I% E4 j& @# F
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
5 o4 o4 e% \" d& Y/ R& Z1 g T1
' e6 {- W N" |- V0 I0 H/ b B需要接受的参数:
v( P+ u: x% e; b5 N/ ~$ j( A4 G
# B& G1 A- e: U+ V, D U- Zconst props = defineProps({
, z4 }/ H3 D+ ^$ }2 G start: {
4 A# v# b# w8 m type: Number,3 Z( A o9 h; b
required: false,
, h. I- J3 i8 H default: 0
/ x5 V' G, j# g7 Q },; f9 `& e0 Y4 p. K( B) k
end: {
; O+ Q, X4 i% h( z/ V type: Number,# J) r% o. a- z8 f0 u3 X' f
required: false,
8 \9 V3 t' f; b- f0 ~ default: 0
( @- a& E* V! s3 T. |8 h2 J },
( K% x$ K7 q. S$ ? duration: {
% {4 l( p+ b1 t( e" d type: Number,# f- \1 v, F( a7 o* Z m1 h0 P
required: false,
* v9 d4 q; Q4 O$ k1 A! D default: 50000 e& ^! K7 X, e2 E& J" Q
},
- H. W$ H l, m k& P autoPlay: {
( c7 W; H; ?: @# D2 S. i: P type: Boolean,
' }; w: I5 c) U3 q1 r required: false,
) ?" @# l- x: @, P) V2 e( x- v3 k default: true
3 D* D: ~7 j( z& [: M x! k },% s4 P0 f/ e7 x& u( t* y6 f# E
decimals: {
: C0 ?7 t/ M, I; e type: Number,
- R1 J; m; G: c V" y required: false,
3 |0 s0 }+ O" u default: 0,4 y' b* a' Z2 }' E/ F) f9 W% {, K5 j
validator (value) {. `- }! X1 q; ^9 L, N
return value >= 0
! b$ _# o" Q! ?5 K/ ^ }
7 Q; P1 J, ^: ?( w$ b },
7 y: d% o. B( e" o, x# O( f decimal: {) W$ j+ P) e! Q. y
type: String,
7 L4 ?* I. `( f( ^, X. B4 T required: false,! ]+ [' @" ~4 O/ T2 v" m T) b; U3 i
default: '.'
0 J# U! E& r. T6 \( w }, q+ w6 ~2 O4 i( T! n# S( @. X
separator: {/ x0 L3 q, b! ?# k! {: n
type: String,
3 X- _* |, b$ v required: false,
9 t1 Q5 \+ b& s default: ','
4 k" P2 U. X, Z" T. S },
1 M5 Y9 _- l( q- ~& }4 @ prefix: {$ u% i( z6 O% F3 Z. A* h
type: String,
% M! q( ^. `8 X" I7 }4 [ required: false,' E; r6 F1 H$ m% e, u
default: '': B( `- M C/ Y7 M& x
},
3 ]' E5 U$ O: X suffix: {3 a& a' @9 A3 f
type: String,- @5 J5 G* J: o w! [
required: false,
( ^2 q6 O! \7 M" S; X, I default: ''$ f0 O! [! K2 g: Z! d& T4 J
},
! O" h& h" K0 a& e( u6 F useEasing: {5 Y$ ^) H9 _! w [) B, Z$ A6 t' v
type: Boolean,
/ A. V, w* W5 k. P. P required: false,
/ l* I1 Y7 s% a default: true& l, L8 e" x7 {: I* J
},. w% _* ~; J! @9 O
easingFn: {' `; O3 N) j- a/ C3 f8 S2 E
type: Function,! N1 ~# c& o% T7 G5 r! a6 f3 |
default(t, b, c, d) {
2 o5 S: K# I% y. X7 J return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;. ], Q9 d2 _ y' C" W1 ~/ d
}
, m2 r7 a2 N. r% k }, y# |& o& }$ X) s2 ?% ^ z
})" k! U% B" _8 c" ~# L9 P
7 R3 h+ d1 P- A
4 e2 K7 A/ [1 [9 V) e6 h1
% l+ d4 J' V+ }& V3 R2* b( K: v5 ?8 j' G* \# K/ ^! r
3
3 W! Y/ N* m( N( v+ A+ r! |/ ?7 f( t4
8 @2 ^& C6 A! M' n5
7 m' S# J- S+ Q! `# u6& b/ H/ |9 ]* ~! u; g" ?7 M
7$ ~1 j! q2 l1 D+ u/ R9 Q; W- R
8
+ p- ]& E9 S( _: B" S' Z9
% G1 s. j7 r4 Q4 U2 p10; H# {! c6 T4 e2 Z: C2 o
11
9 T. Q c) H- Y) \12
5 e' x0 r0 b! ]8 |13
|9 H' M9 G( h4 [7 G14
j5 X2 l, V% C- D$ D15, e$ u; W5 L6 x3 A# X- A
16$ Z. f6 X9 J9 a0 A
170 U9 J& r$ m3 \1 @2 m
18; b( { d% g+ Q# E1 T
193 E. _; N+ L9 }
20( R9 h8 Q/ x6 H& J' m7 [
21
) C; @% W* X/ H) g0 V7 K/ d8 D227 \% A8 E6 Z# c" E4 f7 a
23
, n+ r; n9 t6 o/ A# l5 k24
2 I: S: C4 q" U1 K" D25
; ?% ]: `3 e6 M/ h26
* l0 C) ?* Y/ V/ j2 e27+ Q- m" p4 J4 p& E9 M: M
28
9 z- @9 k$ y2 g) C29
4 g1 g4 g1 b x, F: x1 h- ]8 F30
5 @; X" g5 c1 N: d312 ~) v! t! a: X; |0 L- D( ?1 M4 H3 S
32
' |6 P2 Y* _! Q6 @6 y& C, R338 p8 n+ a; l: E5 r# i
344 R% Y+ o# x6 z2 ^) N1 Q6 a
35
' u! n8 A1 w4 l# A3 e363 \' i' `" F3 B$ O8 l/ v
37 e( r2 k2 _: o- E3 w/ z; V+ _
38
) f9 ~2 E! p* e) n. d! ~3 \39
8 b& ~( i! v$ \5 G: r& n5 \40! b% A% e9 F' {+ G2 G
41
% I- S9 B {1 S& S- v7 w. P42" s* I! ^) {5 l, C" F, _8 o! i
43+ p; F) e- J. d1 w% I0 ~+ r
44
; m' c4 }+ Z' V% I; ~ J45" d) M8 n$ y$ @1 f+ S+ I8 k5 P9 y6 ^
46
" o2 ?) J1 V# o( e- W47. _. q) F' i6 U+ @- e
48
1 p. Q0 \# A& c491 B5 ^) H9 y/ q' I U
50
% ^3 j/ E1 q- A6 E, s. C1 X, p51
* p8 F# J% B; x7 e2 e# ~- v E! a52
% t9 t' _1 Z7 v7 \) S, `533 p0 h6 ?$ n2 x0 k1 P9 R; Z" K
54
% W2 Z* T: c2 `- F6 b/ m5 r551 M) f. Z7 _* I n0 p# p: Z
56" y+ O9 n( u7 `
572 I( P( d: U, I
58: i1 g2 \/ z6 A# E
59
) d/ G7 D* d0 i6 l) Z60* j2 F1 H6 H+ S3 \7 \8 {3 Y
61
7 d% ^( |5 j9 Q% p8 E! E5 E1 }6 b62
6 c' `3 X! r' B, m) ^启动数字动效" Y1 B7 j$ W9 }4 f
$ I- v( T, a4 l- ^$ V0 Xconst startCount = () => {
) K2 c5 D0 z* N0 y2 z* c( p9 r state.localStart = props.start
# z; U, r0 v- a0 i state.startTime = null) g* O9 G+ v, Q1 ~8 r
state.localDuration = props.duration
: t8 p, i) X! n% Z/ { state.paused = false
* |1 y$ F) C1 O* r state.rAF = requestAnimationFrame(count)
$ w" _% J% Z$ C}
" E2 B1 f4 ]2 y: a1
8 c( L9 I4 M: ]2
6 c7 p, F+ Y2 O/ j( s1 W1 l3+ o/ a% D) j7 G1 s* G" T8 x' Z
4" o t7 {9 a* o( k$ g* \0 \
5. T, J4 y6 ^4 t& F: ]: K" j
6; @ S( o; C+ q b P1 L1 O
75 I* B) K8 ?" V
核心函数,对数字进行转动
8 ], H9 }% n( X2 o/ e* M( D4 M: h7 A" X/ o
if (!state.startTime) state.startTime = timestamp
( j7 k1 U+ x, ~9 {* b9 @ state.timestamp = timestamp
0 R1 E# o4 q/ W! _0 o const progress = timestamp - state.startTime$ ^2 D! Z: e: Z$ ^; H0 u
state.remaining = state.localDuration - progress
" D( M% N( P) s8 a$ f // 是否使用速度变化曲线, m% x% M# @1 ~: `
if (props.useEasing) {3 c, a" r9 \: I0 D5 a7 p( H9 |
if (stopCount.value) {: E X, z) s* j/ ~: w& |4 b# L- ^
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration). W6 n$ k: {* W* X- F3 i. H9 M9 }
} else {
4 q/ {- t' \7 X) Q9 t4 c' P- C0 }; s state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)( {6 G' D0 l& `( R/ V
}
& t! w, h- @. c' ~* `" {2 O } else {
' x. Q Z) X# b if (stopCount.value) {
" V$ r( K$ Z3 O( b( H0 F, @4 ` state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))4 I5 y" V k. p3 g+ `/ |: |
} else {; s1 z8 i0 ?1 q! b
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)7 @7 p0 u$ w4 E& }- s6 Z
}/ X3 D0 L# i1 O) P, [; k/ W
}
d% U1 a# ]/ i, P, j- I if (stopCount.value) {% J5 C; Q0 H& V8 A
state.printVal = state.printVal < props.end ? props.end : state.printVal! j2 @# T: x6 b( G& d. ]8 h8 x V- ]
} else {5 k% p4 m4 Y3 ?* H8 @, k
state.printVal = state.printVal > props.end ? props.end : state.printVal* c, K2 r3 C& l! s4 e3 ? ~
}
1 t+ f2 D/ d: j6 P
4 l% `% y* s. k( I# n( j state.displayValue = formatNumber(state.printVal)
( V7 E z7 N2 x( ~% e' n if (progress < state.localDuration) {
9 M, i9 u1 s+ ^3 @ state.rAF = requestAnimationFrame(count): ]- }9 N+ X' h% g4 ~! @
} else {
! A/ c1 G9 |( j' S5 N emits('callback')
9 P9 F6 F" N% N+ |( L: ` }! ~' e2 R, T% X, e+ I9 j
}
9 A3 o9 I) w) C+ M4 v4 b
) o# N. a$ x! o3 P/ c, w/ X2 H. Z9 D: M/ J
// 格式化数据,返回想要展示的数据格式9 x1 l' ^" t- e: H2 p7 B
const formatNumber = (val) => {
, k0 @( ]+ m0 h* F val = val.toFixed(props.default)7 F- j! H& C* P; ~
val += '': A$ f& ]% t( {6 l# F+ L% A
const x = val.split('.')+ f& W. U1 K7 j: c1 x
let x1 = x[0]
. ?$ V, {1 Y$ _ const x2 = x.length > 1 ? props.decimal + x[1] : ''
+ b8 F, T+ z1 e4 T/ \; B const rgx = /(\d+)(\d{3})/
! f" X$ o% B8 ?3 X5 B* g% C, \ if (props.separator && !isNumber(props.separator)) {. O& C1 ~4 T$ A
while (rgx.test(x1)) {
6 B, `6 u1 Y. l x1 = x1.replace(rgx, '$1' + props.separator + '$2')
; k9 G" D3 b- D# G }) P+ g/ [1 {5 A& J. x! P4 [ w
}5 h7 ~. i& x0 Y1 A, `2 i3 o
return props.prefix + x1 + x2 + props.suffix
7 v& }2 u& L& L _% ]}
% \* J+ { z* M1 t- ^9 G1 l! |! L
1' Q# c$ j0 r2 Q0 j$ J
2
9 |! x6 K& ]0 u4 `# V& j3
6 o( J$ K% z- j) v) q3 ~. F4
: y7 e* J% i5 ] \58 N; n7 v% u4 E' I9 p5 P7 `0 _% j3 S
6% Y/ ]% i4 t5 R% k. M+ K
77 H: R5 ^' V* s% W/ K6 U
8
; H. L$ w a6 Q# x* A6 y9
& Z' f9 n1 c. `, s6 Y10: I) b1 Y! N; C) |
11
- W4 s; s- o. a) x" Y( ^124 V+ A# U4 Q# G/ m
13
- A, @- p/ H+ P14) N; m+ t; V. F5 y
15
* e! [+ [4 f5 d- m16
2 p4 |3 A: J, U$ V# ~9 z; F17, Q/ \$ L. x/ [$ W9 S' v
182 `5 P X: X$ R1 h8 D
19' L% T, f1 P. X- U5 t t" ^
203 t' |% g9 N, `6 t6 R8 _
21% Y$ d* n! W) T- Z) c) A& b, a5 T) ?
22
* P; o7 ]) y/ Z" Q7 V( @23- \9 [* _1 D; }' c* [# g# j
24. J; O9 E b, K0 j
25
7 T* l! \7 O. v1 E8 B0 M3 _; r26
) g, M ?# { G( D0 c( t27
9 V$ J, X- z6 A# {/ u9 C1 T/ c* A% Q* ?28( _( @& c" V7 m4 L7 s
29& H$ M! j/ u& g0 h3 u
30 s& W- H) N! Z) v4 a! p4 G
31
6 c/ x5 H8 R4 k) m0 h326 u9 k0 `: W9 x/ g+ I0 Q
33
2 z: F0 L& u) ]; V34
1 w7 @* ~1 o `2 f35
" I, T# X, W9 Q" F6 h" D9 p36
4 T" N: K$ O: w9 w, D( \37
/ {1 Q t( m. V! f38
& S" d' a+ l( \( \" D39+ ^% i2 N* \0 {/ `
40# v9 O w3 }4 G1 K; d* Z/ y/ X h
41
. O, x1 C3 {5 {424 Y* d; P! h* R2 g/ ]7 m8 R$ S
43
: _- @6 u- }2 X$ o* {; [44. e. d, i0 m& L
45
7 p, `% m$ T. W6 r, t468 A, @. s& |; L# z
47$ k4 Q: K$ o! A5 W y- g
48
, H# A* H9 ]" t- I取消动效
( [, L" t: z" a$ R
4 w5 a9 S/ u! |% c4 P" O; ?8 i// 组件销毁时取消动画
5 }; @7 j b# s, a; j3 aonUnmounted(() => {# J1 n& l! T) i( a( X
cancelAnimationFrame(state.rAF)$ e2 b& `% A- P2 j& v( w
})
) E8 L; y0 a- s& \2 U1
0 d$ G/ I( t- V# N0 a, ?$ _+ }: ]. O2
$ c# _$ x- G9 p$ {" A) i3
! {) x& e9 u! n5 [% ^/ b. o6 h49 K, u. x' H' k- l" Q _" G. b
完整代码
2 ?% Z' n- N/ a' H2 {9 [4 c5 s. Y' v; r& P" c" j' W1 }
<template>
) c1 R) i! p2 Z% \, d k" j {{ state.displayValue }}
$ k6 m4 E: h, M* |7 u+ J</template># E2 d. E9 u2 @5 o1 V: v5 t; `
3 Y( a6 I: S; x3 \$ A* y$ e<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
, S# w* c9 u. h0 m3 h3 H Zimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
, P6 ~. H$ Y& limport { watch, computed } from 'vue';) z% H. Y6 p+ K* V
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
& q$ W+ F' B8 y4 d: s$ n// 定义父组件传递的参数
6 D3 B! v( Y% D8 j* g7 cconst props = defineProps({
: {7 c) \6 e3 t; S7 n( g' O start: {
4 p% y+ t3 x. m$ C0 B type: Number,
' X: Y: K+ C) F required: false,
( F0 L5 t6 ?" v5 V" `# ~ default: 04 Z8 @- }3 ~, i" @
},
! Y0 _- j: ` a, E* | end: {
P6 h) z- V+ v/ Q0 u6 F" ?* {) E type: Number,
5 j `) Q2 i2 Q( G! ~ required: false,. Y' M6 ^* F$ i& G$ W, O
default: 0- ?! O, L$ z1 r- j5 V. {# r* j
}," _2 l3 B! F1 |
duration: {% i( j& e: G5 `+ A/ {) |
type: Number,
( ?2 g8 C$ Z+ V3 L3 O required: false,7 J" D7 ~& ?4 b
default: 50001 t W2 B& a% p9 S. u, {
},
2 I! j* j: ~; M% i# [ autoPlay: {7 b% `/ Z) a; g4 ^7 F
type: Boolean,
1 B' F; w2 \7 |6 r, D! y required: false,! A4 f- k1 w. S+ X
default: true
" U/ ]1 u: u1 U },
* U4 G0 x2 }- y/ j5 U decimals: {) X. y* m$ j) M4 H' P# ~" j
type: Number,8 N1 `3 B; G* c4 s: Q# _9 s5 Z6 D
required: false,
& J6 e8 e. V7 x2 A default: 0,
4 E( L3 S# f% t O1 \) f validator (value) {
2 d$ Y0 K) u; k4 k# C* g return value >= 0* c0 o$ V& k# n" M+ \+ c0 V7 o
}
/ x8 [( O0 A6 i U+ ]. L2 @( G },8 I5 F: J; j7 L5 h. W$ D
decimal: {8 ~$ O6 v5 t& }; c6 G
type: String,$ ]. Q5 J9 X. }: U
required: false,
+ z3 n$ y1 o7 U' O+ S( Z0 D( h default: '.'
1 }$ g, v; s. i6 G8 u. W; W },7 p' [$ b/ w+ x9 g" R2 {9 G
separator: {
0 \% L1 m- i m U6 \ type: String,' I# B/ D# ~+ R9 \( G
required: false,
( f+ o* C ^* g! p default: ','& _. x+ F9 n- o' \+ I+ Y
},8 q- c/ q- p& a+ X: ^, L# B
prefix: {3 w1 j6 z. n6 v# w
type: String,; [0 c/ i& N z" k, G! }" d1 d
required: false,
4 {1 e9 _; z2 n0 V2 c% ^ default: ''
2 G) |. ~1 l$ P }% c }, S1 j; P" d! v, ?
suffix: {# A4 e" c" g- x& T7 s( Q
type: String,
3 m% N) E% ?. z; l0 R: R required: false,% Q7 f" x( c9 \! S" @' g
default: '', w* ?) ]) a% k% N' N3 U
},& g- t7 s0 n) I/ f2 j% K1 H+ S1 z
useEasing: {
6 ^9 K+ r. j! L; D& Q5 E type: Boolean,
3 ]# s" I) b8 [* s required: false,0 C2 L. ~8 }3 t$ Z% R
default: true6 [. k3 K+ e; L- c0 r
},
& [5 ^7 i" A& L y! ]% K8 F" _1 R easingFn: {+ m Q, I( J6 z7 {
type: Function,
" {' }6 ?3 O) F* B% { default(t, b, c, d) {" U! Y& C* P$ I4 X# p
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;% M8 a5 Q! l# `( _8 H
}% ?7 B1 a# Q( O# Q; d6 T) V& y! e- k/ e
}7 @9 T% c( d+ F# l
})
7 \+ X+ e0 g9 b W4 U
$ p0 k9 T: J M; k; |const isNumber = (val) => {
" U2 H* ^/ |3 d8 s: m i return !isNaN(parseFloat(val))
" J) H" Y' K @1 Z% R! o8 u# Z}% Z/ w' h: P$ g( J: P& b. N
6 U2 z( J# ]4 S: s// 格式化数据,返回想要展示的数据格式8 _! c0 U# Q( ^2 [
const formatNumber = (val) => {
6 m6 {8 r- [5 B: F1 D val = val.toFixed(props.default)
4 T$ c. o5 g6 r9 F" b# w val += ''0 O% `" z% I. i& A3 p: m# y$ W3 K
const x = val.split('.')
- c' O( b H. b ` let x1 = x[0]
9 [( l5 L$ b( V) Q$ Q8 K/ ] const x2 = x.length > 1 ? props.decimal + x[1] : ''
/ Z$ g( H6 {$ r/ G4 t, I const rgx = /(\d+)(\d{3})/
1 d: G. u9 X: r. C' }+ M( B if (props.separator && !isNumber(props.separator)) {6 `1 A( H9 n/ L4 b8 u- |/ l( W
while (rgx.test(x1)) {
; ~" X: @/ M4 j x1 = x1.replace(rgx, '$1' + props.separator + '$2')
! E" a1 O9 o' O9 K8 o }, r- h% t0 ^( L" ~9 t% J
}
& w9 p! l( K" f9 n3 n. D& I7 n/ U. y return props.prefix + x1 + x2 + props.suffix ]+ }& r t9 U* B1 r
}
/ S: ?7 R" K! a9 G8 I* P
, ~. _6 D" G- M, ^* t/ N// 相当于vue2中的data中所定义的变量部分
! d4 b6 y' Y+ n X" B5 e% @const state = reactive({5 v/ R: H7 S0 }. Z
localStart: props.start,
. \% M& T( j; d displayValue: formatNumber(props.start),
6 P% M2 M9 p! q7 R printVal: null,
7 W. Y" }* F, J$ \. g# E7 A; O paused: false,
+ N4 F+ D" R# m8 ?" e8 ?* Q" F0 G; g; g localDuration: props.duration,
* Z% e% j8 S5 a" i! r. H! H startTime: null,
( A3 `6 G' M2 W timestamp: null,
N) E! i3 s7 x. i1 ^ remaining: null,
8 U( w7 `% i2 g- n7 d) ^/ I rAF: null
5 @8 x3 M O. f& W4 l})1 J- K1 y0 d/ Z, {4 W3 C
/ G$ w. y) U! }: P3 a+ @// 定义一个计算属性,当开始数字大于结束数字时返回true
& l" t9 c7 x3 Y7 [4 }& x) U5 Kconst stopCount = computed(() => {
0 O9 w9 T4 I3 B return props.start > props.end
* w& }- |) s2 X$ Z0 o& ?})+ }. t0 u3 q$ w C
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
& \2 h+ v# @% D( j% M5 H& zconst emits = defineEmits(['onMountedcallback', 'callback'])
S' _% h' Y( c% L/ J2 I4 J
+ s5 w3 {3 e9 Nconst startCount = () => {0 z' `$ }# |% _: e2 b. M/ B
state.localStart = props.start6 e! i, E3 S$ y; z5 c% ]
state.startTime = null' c9 c+ ]; v; [. |! O v$ D; b: N
state.localDuration = props.duration' m$ I. c1 H+ t) B0 P* g6 c
state.paused = false
x4 n% @- U# H1 }$ Q' f& H; w state.rAF = requestAnimationFrame(count)
6 `/ e* x; L" O0 v. F+ G6 `: H}
9 r6 C4 O5 m2 V+ Y4 i: l" J' B) H& H5 Y3 F
watch(() => props.start, () => {% U# B* ~) N8 X8 b' d5 s
if (props.autoPlay) {+ h3 z# P% w$ |. C
startCount()& t1 t* G9 z6 n6 l# ^7 r5 e7 M( |# I1 z
} g. h# {) U/ u
})0 m' N1 B# ]+ E; [% T
6 W. d" r; f @% w7 swatch(() => props.end, () => {# @: K1 W4 k' T0 S: [. J
if (props.autoPlay) {
/ H$ Z3 R/ V! j$ [ startCount()6 O& e O) }, T" X7 ^
}
. u+ n4 J' U2 [' z) d! I! y, u})6 p" `. o* r* K3 e: v# _) n/ N
// dom挂在完成后执行一些操作
' n1 I8 k8 c, j/ A) M6 r8 IonMounted(() => {
$ j+ K# u, K* q if (props.autoPlay) {
5 ^/ ?/ q. U. z9 T startCount()8 E1 S3 }: ^+ X7 c" g
}- X( _4 X- p6 |* X- Y* y4 `8 L
emits('onMountedcallback')
( O$ k0 m) C0 Y! [3 E6 k1 V% T})0 Y$ i/ C4 c. N
// 暂停计数' R1 M! D6 D% ?9 N o
const pause = () => {! S; o/ C( F7 `9 _1 n
cancelAnimationFrame(state.rAF)
" P1 n! _, }4 d3 ^8 H+ X}
9 b2 {1 T4 o% X3 _4 h+ s* }// 恢复计数
: d1 u; I8 B- }1 V9 nconst resume = () => {$ G" [5 D+ H# T7 K3 q3 o) r, w5 v
state.startTime = null
" f7 U0 [& T" q* M9 |3 F state.localDuration = +state.remaining
6 y$ I* D+ T) |6 m& m7 }5 |* b7 n3 B state.localStart = +state.printVal
- z+ X+ g. i0 U K9 ]" j/ S4 ? requestAnimationFrame(count)
: i/ @2 x+ h% ]1 ^$ k}+ |( r" \* d9 V( f0 h3 W6 P
! c1 I( I8 T/ n0 E8 Z
const pauseResume = () => {4 u4 L4 \9 ~( ] r! v o
if (state.paused) {
, D3 x/ @* L6 o resume()
* [! n$ x) V; q w state.paused = false
% h+ |6 o" L9 T( i) P$ L: ] } else {5 k. [5 K# G# s' W( M
pause()
2 N' i2 M f. @. U state.paused = true" q# x+ Z# \. s2 I* u! ]. A
}9 Y' V$ b& z+ ^* F4 M8 f4 z
}, s& v& y$ W9 d- D$ E
( O) \ Q: `7 T% W/ p( _- x# Q% S( z
const reset = () => {# Z0 K) O! M! _1 I! }
state.startTime = null6 r1 j( s- |6 v3 Y0 w7 n( r
cancelAnimationFrame(state.rAF)
1 @/ V. W! u' c/ c- h: H state.displayValue = formatNumber(props.start)
' f+ x6 K9 Q$ x2 [/ Y( d- X}) I! e3 ~: t4 u1 i. J
/ g- r' l) I8 W1 ? P; e T
const count = (timestamp) => {
0 o8 K: c' x5 d+ K2 V K! K; {, e if (!state.startTime) state.startTime = timestamp) D& u* c9 t0 t2 ?/ X g- v% _3 A$ D1 i
state.timestamp = timestamp
; ~& |9 r& @4 o# x/ c3 @5 {6 m f const progress = timestamp - state.startTime
. c: i: I& K. @' ^) s& F5 G$ U" ? state.remaining = state.localDuration - progress
3 X: w6 d& W( { // 是否使用速度变化曲线
4 ^( p5 k* t0 Y2 `& p, H if (props.useEasing) {
' z: u( t1 f9 D2 \ if (stopCount.value) {
4 s' o0 _1 H* Y1 j9 G: H state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)6 V& E3 D( L' x2 J4 j8 X. ^2 R
} else {5 D Q. F9 P( r# t* L) a; o
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
3 r5 J9 j7 R8 |4 t! G }
/ f' W, B& `- {9 [$ y7 k& i } else {, q0 H. y$ z" X) l8 U% W, n4 v
if (stopCount.value) {' f. @4 m& B: d+ R0 V6 Z
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))1 \: D) X. ]) x" X
} else {+ a B8 N* B& i
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
6 d# M! ]2 U7 X: |; k }4 x4 u$ Z: Z5 e% ?& y. S6 X1 E
}
( f- n5 A/ g; F+ a* s! ^ if (stopCount.value) {
# O; u3 ]; y8 V9 Z+ n state.printVal = state.printVal < props.end ? props.end : state.printVal y( T5 h0 ~4 C( e
} else {
- o9 B4 y( p- M; @$ @7 Q state.printVal = state.printVal > props.end ? props.end : state.printVal2 a" I: u, ?* v4 L" m
}4 J; f5 ^5 @: F: f! \
/ B! j5 a5 z0 p# F
state.displayValue = formatNumber(state.printVal)' x G- w# X. |
if (progress < state.localDuration) {. V; C2 X8 v6 v# ]$ X8 N- N6 N
state.rAF = requestAnimationFrame(count)$ E& f1 L& v' e5 Z
} else {) b7 w, X2 e: [2 s2 L! ?, H
emits('callback')& o; x9 ], x( G, c
}
: b" {+ x- F9 y( }7 s}
. z4 x( s% V' a5 M0 T" E// 组件销毁时取消动画
/ l* \# O, U6 j: yonUnmounted(() => {
/ C1 R. }3 {, ^3 c' L* i& _ cancelAnimationFrame(state.rAF)
+ _# h7 ^* d4 [# r})8 p3 ~0 H7 [4 ?- b T( ^+ Q
</script>
6 H- b/ Y! q: X+ K4 \. M5 n$ `* k3 T9 o% i5 M% r* F
1
- ]" s" z9 V$ m) W2% X0 i6 y& ?6 s/ W
30 I" ]: \5 ?6 q1 [/ C: i1 K
48 ]% [, E. P* o5 E/ u: @
5& ^, p4 n4 e4 ]# h
6
& L" x' ~6 p, f& p) [) P7% N+ f. j' o' ?6 C: ?. L
8
# L8 t: l7 v3 h9
5 t8 p8 c% b" o' }& I10
- P- m% G$ Z) z, M! y' y7 O11
7 {4 u) {) [ r E. O, ]# h12
* |$ ^! H0 V/ m139 b2 U/ n8 ?! `: ~' O
14
, S6 Z G& ~% B* x( K% m1 f3 a154 t& E# t) C0 O4 `' ^. N& |5 r6 D
16
* L& ]/ k [3 r p6 F17
! f8 W+ p, U# z% `0 f, Y18
8 }% v+ D6 u( c2 V19
9 A1 W: O8 E6 O$ [4 P q20$ T5 t( ~( T1 x" |+ A4 Z* ?
21
) A: A8 m' V3 ?+ h7 t; i& G22
L, b: l( l) @: H23
2 ]( J" A$ q% t24
) V3 g* ~) q4 j! ?! |/ Y25$ L( n$ P( Q& A" o) k) }3 j
261 Q9 [5 [3 w0 a5 ?( T
277 u9 _' n( L3 p, t
28
) `, k9 {+ E+ y5 H29
+ Q3 c+ v @% Z* j30
9 ` p; I5 ^: l) \318 _+ z0 V: H6 S2 F" A
32
* b5 j2 M4 y& B1 ]+ S! |330 L6 Y1 d( y8 \5 B
34+ T! R& k( P. Q
35
, Z) Q. @3 V# U5 G& n1 q! [0 H) z' \36
1 u8 o. l- a* K37
) L/ N" A' l1 n; \38. ^+ b* o4 i5 j& Y2 x+ b; b
39
+ K* S& F# v* k6 J" [. v8 M40+ e8 l' M( ~5 |' b$ ^
41. z! v: L2 x& ~8 I5 i
42
5 Y- V2 [9 j; L& T436 X4 }+ f K# l# P/ _- ?/ H+ Q
44( w: ^8 X& g- P' S, `
45 g* i& S/ d$ P8 r, u8 C! L
465 f* ^ R+ ?* G
47: e6 u6 V2 B6 ?8 ]7 j1 W' N
48' x% [0 J& r1 F' t
493 B+ o0 r8 b/ C$ E: C5 l0 F
50
- ?, t7 k+ B) A, v6 P517 r5 R- o. J4 C& W; v: \" L+ ?! L
529 d2 Q: j* j0 z& X+ A2 J& o3 D
53
; q& [3 g! r% ~- ]0 P: C543 ]. H' L5 Z0 a, h( O) y1 s& Z
55- N, i& w$ Z: B2 }5 N8 H
56
3 o5 U d. u: ~6 P57
9 u7 k* K& C* R! V+ Y1 O/ D* t585 I t% g: N* j- H& _+ o4 d
59* c' ^$ N0 y! \0 `
608 K! N/ q% p# O- {
61
3 k- s( F( ~2 x; E3 Q- V" \62
! i1 {8 T# k( j' P8 Y* _3 n1 S63
' B$ ]2 c( k$ ]64
+ i& ^1 q) x" D) J. P- I( @653 M. j8 E5 h% o: x" I9 ?$ ?
66% E! @0 X6 r$ D' [0 U
67
$ c" `9 F+ P' c1 W' V4 u68
" N6 M' o/ _; K/ p) c69
5 x" Z2 A9 D, ~* A, j) P; ]; w70
3 g2 M& e' ^# R" X. ?" B71
8 A- i7 u1 o! s5 z+ y; K5 i7 j72
3 h! ~7 }1 J- A9 }1 i# ~9 b5 l3 j& a j73
( u2 F# O# h( b4 }74
& V4 }1 Z: ]8 C- k. |4 v! N756 l3 B' f3 |1 @/ ~( ^# D
76
3 E! g4 |& ^) S- m77
, q0 ^- n! O7 i6 A; f/ U' r8 x78
/ ?! m, t- _- z) y8 I; V) Q5 X- H79& \. n* ~3 }4 K* P+ ?- ~
804 c; \1 j: I* t0 d2 \, N4 J4 r
815 Y/ B+ }) e! V1 i: k" v
82
* z6 z' L& j" o, c! p E; j83$ |% X* {6 y6 H2 o
84$ ?! @. @$ c% g3 R
85
; c" }. M) H3 R) o, Z86
8 T1 |) W) x- V; J8 w87
5 }6 f3 [7 k0 N4 ^( ~4 H& W" m88. M1 y# g& h7 b' P( `' I
89
, Q1 |7 A3 w- m. l& [+ Q2 I0 _" Q90
( `+ H Q4 [0 i4 {$ F* l91+ d6 B5 G2 j$ T
92# T( c3 d* @, X0 K
93/ B& g! v! j) t! U, P& n
94
) N) \$ C$ _. ]; q% u- |95
3 ~( g6 R& S$ r1 B9 G9 ?966 _: z7 L7 {$ \
97
1 C: K" `4 B9 f9 ~, |* d98* P6 x4 k0 q. L, r
993 I$ k+ P# ]% f/ ~$ w- g5 u
100+ m- l2 e7 P* W( c5 m5 \9 h
101% V6 ^: D& v0 D4 p1 S
102
$ Z% B0 c- P' {( M# m9 P' ^" T; B103! m$ a+ @1 q6 \0 q8 ~
104
8 q( B" ?" F# D# w x3 [105! k: w" D7 {1 c/ i4 x1 z5 G
106
) n! T9 E. \6 a( q5 n107
0 H V/ q5 ]. C0 l& l. V108( f7 m& ^- k8 @. g6 f2 m6 @+ h
109+ o& {) V& Y w" O& T y9 ] J( b
110
: D% G' t+ t: F- g0 t5 y111- i; B5 J8 k' I' ?
1123 f/ a1 G; ^4 _( t$ Q( x4 P
113
# N0 T; P# j# O# q) r% I114
) d$ R' B% j v115% D6 u, |3 p8 } \" E
116
. `6 F& Y+ }1 n9 E" r. S117
1 c# j( U- Z" _8 p0 g$ `1188 ~# v& f; {- _' E4 ~
119
/ g5 {# D; I- b1209 C$ _2 s' v& P) g- ~
121
& p! N S. s' `5 T122, X* B9 C% d' A% R
123
+ ?% y7 Q, J4 f, i: V1 R7 u1245 X$ ~5 m$ S$ @: w: u
125
7 K, y0 y9 K. {" `- F126: |1 s; M4 s! w2 l. D( c& T
127; [. |9 x8 {( M# j5 e+ \* D
128) q" o" c% R2 b2 J; {. I6 B
129
& y6 ?; `7 f* P8 k1305 i; [: J0 {9 X% |
1315 @ |: k9 L) A! k" f
132. ~9 f, u- M9 c2 s `
133; c8 D0 {5 c4 w4 c$ Y1 }
134& t" q4 K/ A; j9 a: @
135
2 y! G2 r* T0 M& P$ D136
: M6 e4 J' o- `5 C% n137
1 e! i9 T, U. r0 F1 T- L O+ I138
1 L) [! B5 j) e+ b- c139
5 x! n. f+ [* K% x- s$ u9 Y140
% t+ J5 q8 q( m/ @( }1417 D' a1 D+ m+ `
142' J, r( k" ]4 G9 G1 t& u5 g
143
+ P- j; ` M# C; F144$ J4 l# p8 r0 ~2 f
145" k& t7 Y8 i. J0 V6 J; x
146' O+ D+ L5 B' u0 O/ q
147
8 J' c/ h2 U9 ^" E' q148" n# j/ g1 `7 l6 ~
149
$ w! \ a8 D) k, e4 @/ `) L150
5 a# Q( ^' H8 E" ?, o( ~1 D151
S: I/ E0 G2 |4 D152
+ j3 H6 C* }" t. l1534 a$ u* \7 Y/ J0 y/ n
154* O# V& X; d( I' |2 a
155
+ k# ]2 g# ?0 e: w) \( d. U156
/ b1 H# ?( P/ [) Q2 D157* g1 M! M! A7 P
1586 b0 g B- V9 M) `' _* D
1598 e2 n4 x$ n+ H$ l9 S5 Y7 s. c
160
7 J# ^, N, ?: b- C6 e161. r) e( }# n2 U9 T1 Y& }
162
, O& k. b* J- s5 b163( {' o4 a7 M3 z+ U' ~3 g
1646 r5 [2 t$ i+ h2 K3 O) _" F
165' G& g! w# @( u9 p
166- Y( q- k* ]# j
167
. s* d+ {& N9 }$ x1 c5 p9 }$ L$ p& {2 G1683 J+ K4 t& L* n8 h
169- U: H+ S( U1 p& \
170
6 \( }( H, [9 O9 R5 K4 N, ^; o1713 P% W# g3 R; g$ t% j# l
172
% U/ \# o) K$ y7 F1731 J$ p. C( [* z' J$ \, }8 z
174
/ a$ Y: a! R. c/ W% s/ ?8 O$ \$ s) Q175( s% ~; S/ s& p+ k# s/ R- l
176
( E! n! A# I% Q1775 I: s# P- F: @7 d( |* I3 O
178
$ `' F- s- I$ i3 z179
v( {; ^3 g! K180
6 q* e: }* L# Q181. `* Q' c, `- ^ z5 W
182
4 Z# \- |* v0 v2 |1836 a, a! U& u0 X b4 G
184
4 d6 j1 l" G Z4 ~: N& R185
( U! Z# R/ r# J, f' y' o% j186
9 y& ?0 q: l' \4 ^( K" }187) f4 c6 u4 q& D6 k* A7 |" M$ X
188
' m+ X0 P3 J' p# J+ x. f" z- Q0 A# n189
; ~) q4 m! \, H1905 ^, k4 T9 H. n7 T$ [6 ]4 n2 H+ w
191
0 Q6 x0 t7 q- {8 ~* Q192
2 {3 s. }, W2 h# ^( n; h193- [' `: G( H. ~- [
194
% w. K7 K" J/ _3 T) Z* ]# n1951 H5 H+ n8 a/ I1 \
1965 S; l6 ^4 H5 ^6 o0 K. A* H- m
197
- U/ B* ^8 S. p3 S7 E9 t7 {198. j7 q* l# `2 }8 g
199 J9 N l5 J* N$ Q
200
?: C0 P7 u2 o7 N0 m( v' ^2 C7 v3 p201- [+ {% Q- g3 D, w0 r0 |
202) }3 v4 E, i ^( n9 N
总结# c, _ ?2 C" Y4 C0 _& k
自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️( L/ n4 L, p; A- J& @! V U
. ?$ p% ]* e5 Q4 o& V% E- }demo演示
: g: B! B* a. a- @后续的线上demo演示会放在( i* z: c0 T. ~0 j
demo演示) e) z9 a& w1 ]2 i6 G* \- v3 g
完整代码会放在6 U( j. Z) Y9 U0 K4 l
个人主页0 Q/ u0 ~4 _3 Y2 J- ]
6 a: b% d4 Z4 M$ }7 [ u5 P: A: U' m. l8 J希望对vue开发者有所帮助~
z2 R6 G2 L& x; i' A+ Y1 E/ O6 d3 `( E) e0 B: I9 U' `+ d( Z
个人简介:承吾
9 G6 y% e! U% I# C+ J工作年限:5年前端; B1 C' C% Z, e7 ~, P
地区:上海" i0 ]) o, m" y i
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!- R3 Q( v0 m6 ^; D
3 n9 Q0 B0 Z3 `+ C& K( W
' A/ N. `; R) m; w+ E* J+ P1 ~" c8 S3 G( O! _
1 W7 `0 e/ [. c————————————————
: ]6 r9 T6 N' N j' m版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
0 b4 R& i0 P' v# Z' _9 F3 X原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847" h- y S/ d& g( y+ N! v2 o: o. E1 a* E
- A2 J: n( V! I
/ }* a% ?6 ^2 P5 U% V& h" k W
|
zan
|