- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565164 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174772
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
$ j; J" R, l7 F% C
( `- D4 H: g" a3 v+ \前言7 Q- p: E3 e8 Z) m; M1 o
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
& g5 q8 ^9 ^7 J: xTypeError: Cannot read properties of undefined (reading '_c')
3 v, H7 K5 ^2 a+ v6 c5 W的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
! [0 h- `. ^( z; }2 C# E
- S/ I: Q l% M+ p7 f5 A" W/ P6 i% J$ r+ V) P$ f, i* h. e; H
思路
5 V7 t0 `- c, ]使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。9 h6 c; J' x" U: }
6 {: s$ R* O9 V
文件目录4 @; O4 B1 [6 ^% F
" j' x7 I" u% O) h7 p& a, {
4 I: H' w- t1 c3 n8 M% U使用示例
: u7 |1 C; }8 p; g5 ?4 l( l<CountTo
; ] E- Q9 G3 r4 s& P- B& m8 t :start="0" // 从数字多少开始% i V+ t7 g; K
:end="endCount" // 到数字多少结束
* V% c3 m3 v) j4 K :autoPlay="true" // 自动播放
0 Q; S2 r& O* J" T2 s! j# p7 t :duration="3000" // 过渡时间
* F7 W& N7 n! g' _' ^1 v r" z prefix="¥" // 前缀符号/ R/ ?; g" m }1 A& T
suffix="rmb" // 后缀符号; d& E/ z2 _: n' x# k7 ?. m
/>) p% S' u# _2 ?1 Z6 L
1
1 } B( n8 G+ r23 i, L9 Z y/ j$ y
31 ~9 G d! |9 S& X( v) F A6 |
40 V" A# o! V( A' Y
5
6 j) W- A3 f7 @6
( L" C: i0 B; h* ]8 N0 B7; U& T. L5 T/ B* U0 z8 x' V
8
" e3 L1 k5 x3 {7 F入口文件index.js: ?/ Q- c5 W; y
% e2 \. c! d" K( G) X" s7 {const UILib = {
1 d! ?' Y- f4 U: R" r install(Vue) {) W4 k w' ]3 X4 v9 [ H
Vue.component('CountTo', CountTo)
! j7 b% W# b. m$ n' z) q3 p }, c- y9 K: d w4 G6 n, i
}8 H) C: F5 d4 [& ?* u
; o t8 d/ B/ D1 y
export default UILib
3 t% b A, g- T5 W; n" Q P
% W$ N$ F/ Y; ]* T* i& ^4 I- F1
0 b& a' v- S7 u- v7 Y' H2
1 [3 r0 L- G7 m( p3 g: N! G4 K3- d. M0 x. k+ U, M4 `
4
$ {* d. ]0 p' J& g, X9 d) G4 b0 r55 N0 {# ~) y+ ]- ^8 O5 ]
6. ~; y9 x7 ~" L( c3 |' P
7
) ~% g( m# `9 L+ |+ w: ^8
" P& G+ |+ d9 P8 G$ x7 m- p7 ^, S9
0 m# }8 {% D5 C4 Amain.js使用. W1 F0 V& k! _
import CountTo from './components/count-to/index';1 o0 j0 S% `: y6 n4 P" q b! f
app.use(CountTo)
1 E1 {7 n2 a) V" @3 w: B( u( m" Z1
8 ?: f& r7 z: m8 {- t4 C2
. P7 m- X- S0 s4 J# _( M! j2 n8 c$ }5 SrequestAnimationFrame.js思路0 m; h9 A/ r8 ~
先判断是不是浏览器还是其他环境$ \' _8 T! ?: a* x# K' V p
如果是浏览器判断浏览器内核类型1 G$ Y7 {6 @% O3 o" l
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器- y: P5 J" \% `. C4 \3 [# d r, U" M
导出两个方法 requestAnimationFrame, cancelAnimationFrame
1 G* ]& e+ Y& h/ j( C$ d' V各个浏览器前缀:let prefixes = 'webkit moz ms o';
! B- Z, ]5 ?# x6 e) R判断是不是浏览器:let isServe = typeof window == 'undefined';
( E) S+ b* e' F; v9 m增加各个浏览器前缀:
; M" y3 F- Z Flet prefix;8 o. \' |. S4 p; c$ @: l
let requestAnimationFrame;
8 L" n1 U s5 K) s; w1 q+ {% ^let cancelAnimationFrame;
3 ]+ C+ V( \% J; T; P% x// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
$ F B5 f* N" G/ l for (let i = 0; i < prefixes.length; i++) {9 N' Z6 |- ]9 _6 u
if (requestAnimationFrame && cancelAnimationFrame) { break }
9 Q2 H; @( @; N prefix = prefixes, {* b2 T) z' g; O% [# n% S& q$ |4 C
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
3 X& A* X1 X0 _! d0 I" U% @ cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
" M4 ~& _9 h. P8 W1 c1 g2 N }
1 p3 U6 ^: e$ C
& J, n1 ^0 ]6 N; L: s* J. a3 V //不支持使用setTimeout方式替换:模拟60帧的效果, C3 M: P" Y1 h$ u" k, h' @" S
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
9 N) g' n( h1 k2 u! i/ C if (!requestAnimationFrame || !cancelAnimationFrame) {
5 j5 y. X$ H# X' N" m5 a2 Z) A ~ requestAnimationFrame = function (callback) {
8 @' V3 c5 Q7 N! L; K const currTime = new Date().getTime()
- f6 |# f! @7 R1 T5 K // 为了使setTimteout的尽可能的接近每秒60帧的效果
4 S, |! q) X4 {' R6 b5 `" Z0 q const timeToCall = Math.max(0, 16 - (currTime - lastTime))
$ v/ R0 _7 f6 T; ?/ I const id = window.setTimeout(() => {
! k8 X, R( S# q; D$ c4 r callback(currTime + timeToCall)8 [5 S% V& l8 f$ S( u3 c
}, timeToCall)
' [! q6 x/ K, l5 k5 H/ v2 j lastTime = currTime + timeToCall
2 p2 n: y& |2 g8 N$ Q return id
% j+ H+ h1 e$ a* b% b }4 B3 J E: Q# k. d0 T( R" D( X6 K
! \! {! g2 ?& H6 f: A& T
cancelAnimationFrame = function (id) {3 ^+ {) g: \' P# {* ]8 @% f4 P
window.clearTimeout(id)
% D. U, X; }$ W6 @: [ }3 v5 F6 S# R5 d0 G1 I9 ~
}, L: S/ n6 A) G6 K q+ u3 x+ `
. c7 `) b/ M3 a5 u1 ?0 H
1
! {* g2 L. I2 ~, ^, ^2+ F" @( f) f. w5 @
33 P! o% }% ]; x
4
' s% F W8 Z2 S5 s2 S56 t3 [ A p5 D$ w" n
6
& f) R( U1 b. X) X6 `: G3 V+ ]7
$ c) B6 P9 U0 [& H' m87 E; M- `2 @1 d5 x3 h& F
9
4 Z; a5 g/ P: I) Y103 q- v/ i- A# s, m+ j9 t! D: c
117 p b* p6 r7 z' h0 b s
12* p4 G& R( o3 U8 D% j
136 C: u( M6 w7 X0 U9 K' L
14
% Z3 H$ h f' w# v# l5 V, ?9 ^15
$ {! S7 k6 y% m, ~1 M16
: }- W% Q: L% H" d17
) D8 C# B( S+ [8 e: \1 o( Q+ d189 \9 r# I: I. P' ?# ^0 n# O5 u
19. h) Z+ R& [5 R$ U
206 Z0 ^$ L7 \+ A' C* K9 L3 @
21
2 f% r7 J4 V( i; m' E5 Q' K22
4 Y. m1 a1 H0 L; O' {( L1 P: l23
, x, {2 r& o) W' i1 |, y3 `4 _24
. l- C9 E# H, m& h% \25! j. V$ N5 O. W5 y
26
5 A( I4 c* h( r2 R. y; s27% e9 o! x" t5 L& c6 u
28- L, v: _6 e, P8 Z C8 ~8 S
297 Q6 K R" V" S5 ?3 R- N
30
9 { a3 M* S3 M$ B0 c: H7 N31
) n7 Q9 q: c/ g( B* W32
3 T( @, t; c2 _: Z, m* s完整代码:
: e! V$ I, H3 @! UrequestAnimationFrame.js
7 P/ V( M+ I) h4 O
/ t% T. |, ]; v. j8 Y* O% f' tlet lastTime = 01 J4 c9 U4 z& I' P2 B/ ^8 Y, Z
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
3 z5 S& t* u7 c, g+ G* S) H+ g+ v! P3 O0 p1 ^8 |0 a
let requestAnimationFrame, y; T; g! M/ g$ v5 N9 n/ W
let cancelAnimationFrame
% p3 e/ G% K4 p$ S( a+ \4 u+ z% @+ C7 |
// 判断是否是服务器环境% A9 @0 x1 r$ w$ z& K% D S2 ?% [
const isServer = typeof window === 'undefined'
! v! }3 p0 O/ P- [# s+ @, lif (isServer) {( P) b8 o: h% v; x
requestAnimationFrame = function () {
& {$ g8 ?5 E5 p5 \8 w! w return. D c# _5 Z* t* t
}" }4 k/ q* o, |% ^* @0 l
cancelAnimationFrame = function () {
0 w) H0 T" _$ p- l5 L( C- B; P return
. x/ W% h+ \* T1 x! Q& U }( ~( I9 ~4 I L
} else {
/ t4 g% ]6 V Y& k. E) l) c requestAnimationFrame = window.requestAnimationFrame/ T" Y/ L( }6 m1 X {% N
cancelAnimationFrame = window.cancelAnimationFrame
! [; l% v1 r0 k( r6 ?6 _" d let prefix
5 k& r$ ], H) T( m5 j5 z# k6 L // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式8 x" F5 M. m& m1 }0 `
for (let i = 0; i < prefixes.length; i++) {
. o7 Y& S4 |/ E2 t if (requestAnimationFrame && cancelAnimationFrame) { break }
2 l% Z: r. i# D. f7 o% [& `8 @ prefix = prefixes
! ~- P7 x& g: H y requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']: B: y. }" Q p) y( g
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
_7 I' Z7 R4 E }
r/ F" W8 s/ o, t5 F5 b' |
8 ~2 z# L9 W+ Q5 }: |3 c! T // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
4 |: ]( ~( O! h: v7 r6 a if (!requestAnimationFrame || !cancelAnimationFrame) {
1 n; H9 w- O/ D) Z+ A8 |4 y5 r% C requestAnimationFrame = function (callback) {
$ q+ N6 U& k! w! U const currTime = new Date().getTime()
% p- d4 t8 {1 d // 为了使setTimteout的尽可能的接近每秒60帧的效果
% A8 s, R6 V3 E1 v+ l1 K const timeToCall = Math.max(0, 16 - (currTime - lastTime))
8 [7 t7 y9 w2 z$ X const id = window.setTimeout(() => {
! K% f, S+ [9 G: R9 K ` callback(currTime + timeToCall)
* |# Y3 V- F' |9 ]: p- }8 H( r }, timeToCall)' Z3 d0 U0 X( z: i9 f
lastTime = currTime + timeToCall1 M# a! d! X" @5 }
return id4 Y: F: c/ X, [: Q4 a0 ?% V4 B
}" k& x" `9 Q$ `$ [; @
6 X4 g. N$ t1 O( B- v4 C- ] cancelAnimationFrame = function (id) {* |4 S& t+ d" T2 P: `/ K* t# @
window.clearTimeout(id)
+ T+ c* G0 F1 ?4 g' H }
; D( n5 _) K2 I, A1 ` }
6 d. z% }5 m) a( X3 t; o}
% V7 U% \" _+ G6 r) r- p
\1 ?6 y6 u' }2 O; w. r- s9 Vexport { requestAnimationFrame, cancelAnimationFrame }" H; |5 [9 A: N' z* H. k$ L
" o. e; Y( s9 V3 P
6 a5 j' M; u! G% m0 b9 ? {0 ^5 u
11 t* p' v3 ~! Q* I9 C
2/ r( n# D, C8 E7 A, I- p9 u1 f5 i, m
3
& K$ h$ S6 _, f f$ u4 G7 t4
, x; q+ W% b9 b- ]53 j" v! C' {! k: }
6
. q) \; S) E2 z% t- z73 n1 {$ y; v3 G0 k5 t7 f2 C
8! Z) I3 R3 y- p5 z, U
92 K& Y& e, p1 W8 B1 V# G' l6 w& E/ K
10/ A6 ?# `* s. c$ M
11
4 v [7 g ?8 l/ q3 J7 e12
# K' Q/ \6 A8 ~! E/ u13
; J' S) u& z! X0 \14
4 i$ q+ q5 D; O* D! F$ |15" j# Y A2 J% h8 z/ ~
16
3 ^# A0 U6 ~5 u ^17! }3 ?, @. E& {8 L" N
18( w/ H# s5 F6 {0 f. H* Q
19
% m$ O% r8 R4 v: v# U: }4 m201 }* g: p6 d% H- }0 H9 V
21( |, Z) N5 Q4 }) J, t, I
22
: e. _. @1 ]& g) q) F' T23 O0 o$ L0 v$ q# x/ r
24
! w' U% M3 J9 M( C25+ |6 M$ V( L% a2 ^1 m% y
26% e8 D1 [4 ^% D& V
27
7 n5 s% t( S4 I) d) j9 v0 G4 P28! s; a- m5 t4 H; `2 h# k3 p5 y( _
29
) W4 Z( N# H0 `2 @9 u! Z% R4 H% t: _30
9 m) K7 h" L: h+ x1 l3 E* }31
- D: B* b8 Q3 J7 O& ?1 o" r% ~7 d32; ~/ r( R+ k9 b/ ]& Y6 M
33
2 c ]6 f+ P$ H1 e: d340 S! a$ M4 h/ u; G1 J
35
! ^% p* J- a3 Y+ r/ b" _36* W- r8 |5 l" v* a5 j' Z+ h
37
+ f+ a+ f6 m- W38. h: N/ B; B9 p+ ^* p+ S- S. w
39
% p, U0 c7 e5 t! c7 [40
2 A( b+ |5 S( A41
- }' t7 T+ @: W8 `6 }; m( f42" a$ X* L" z+ D" p8 b
43
% K8 {( {9 A! F$ N Y44# C( x) S4 c6 B: u! R! G
45
* _ X8 J" x) d' a8 k8 B/ B/ z. ?46
5 F+ I# C4 j* i47! e3 j' d% P0 W+ i- i
484 h0 {& c' c" I$ y2 u1 l; t4 |) n
CountTo.vue组件思路
- A9 j- h$ j: w; N0 a首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
/ n; m0 Q' u$ m1 S# F1 k; d
; J1 |# o9 Q1 Z引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
g8 G# u" \. [. w11 i' N' ]% c+ W; v: K
需要接受的参数:
5 u H: S/ U. x; X# \* J3 k. _. n0 O
const props = defineProps({
5 L2 V; }% Q3 ]5 F6 O start: {* q' r- V; K6 V8 U; {
type: Number,
3 K7 D$ y; Q% _; L4 B: I required: false,
$ K! \! { {2 T: @& l; V! |4 X default: 0 T1 T0 F. E& U3 D( C
},9 M: Q; `( O7 C; @, n0 ~
end: {+ G# C" F6 A; w$ v) y% _! N3 z
type: Number,
! \ z; Y9 {2 ]/ Y- s- x required: false,: c" S" x! K3 a( K l! o* n
default: 0
) J1 y5 H- B- L7 S2 L },' X# ~" Q6 A) d$ {& G
duration: {
0 Y" n) g4 n4 m2 H7 {* x type: Number,
; Z4 U9 p) \! A7 [5 ]* M required: false,
, I' y9 a5 b y9 S) ^ default: 5000
6 M% O) g8 b1 S% R* u },
' F( A3 ? A' X1 s0 Q) j7 w autoPlay: {, v5 N. m g1 F ]: i& L: N
type: Boolean,
0 o4 Y Y5 m1 P/ N6 x required: false,) k$ p+ T" h5 q
default: true9 _' v, f: e% t
},
* x% i; z. d/ L+ B7 p decimals: {6 L2 ~3 ?( C( Y6 t1 `7 R
type: Number,
. r0 s+ K) J/ t/ w0 K! f required: false,
4 _0 g+ j: [! L2 p default: 0,) F; e' g% T# D: }; W
validator (value) {
9 r" j) Y* C9 y- i2 g; {; L return value >= 00 X% d/ _7 s+ u5 w1 n1 \' E# X
}8 W. }2 f- x/ K1 B6 ~
},
' l# K5 [9 V% f8 g$ P6 s decimal: {
% v0 M! @: l* ]0 i# w* y6 b$ _2 I type: String,, L) G$ C- R4 R. v; L- Z0 Q6 z
required: false,) l3 V) V# n$ \$ }
default: '.'3 Q: y% P8 J; _1 n0 S
},
; k: `5 J! v4 _! F7 ^% @ separator: {3 ]/ b7 h6 r& s6 d2 D" C
type: String,4 a6 k, O- l- E
required: false,
2 e' a/ q; p( y2 i2 F default: ','2 [$ W/ Y( |. e, z+ s# T
},
: f! l G+ l) S5 w i prefix: {7 M% U( ^% Z e: `2 k5 i7 `
type: String,
1 n: ^- b5 v) m/ P7 ~: H) i! p; r required: false,
, [- F* `( D1 W! C n default: ''1 y$ m! k+ f T' K
},% {9 b0 ]! \3 j
suffix: {
5 Z* {4 R9 ]4 n8 a( J type: String,
( Z/ g) M' j0 v) K2 k3 o required: false,4 }( v' c. \' h9 x2 m; t8 D0 E
default: ''
. q# _ K9 L1 {. u% e& C' V },1 K- d3 _4 R( p
useEasing: {; w- b: h* L/ @
type: Boolean,
6 | J1 w) N4 J( i3 s required: false,
2 p3 R+ E9 _+ {. [0 B( F8 o default: true5 X: j8 O m! [0 {7 `
},5 u2 e) E/ {4 h: u- v! {- F
easingFn: {$ ]8 ?: X- y" p! o, o4 y
type: Function,
* U4 F' k$ E+ f& O# I+ }# F) K4 U default(t, b, c, d) {' d5 X z# O! @
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
7 F; L- ?$ V" n4 v }. Y( T2 s3 B. j2 y, H$ l- o
}' c# T8 e: c) U% R& x
})
* X# h" P! k9 `; O: F2 Z0 u) C4 N9 D8 X+ Z& ~3 ?* h( V0 S
4 i% a& X! g3 @' z1 T- l7 v" M: P18 N# M: P7 ` s8 x
2: L1 o% ]/ g% l0 t M' v5 s, O
3
5 `9 @' u; G+ x C4
( v5 o4 [+ ]1 x! x& e6 w) Z5
0 q* X- V- k' b! l" K8 l6 g64 {$ L$ f: w* l; {/ \5 d
7
) {# [+ X! Y- X8
7 ~$ g% p1 @1 P+ E( J/ l# F; a9
2 P6 i- j7 ?4 D9 l, a8 i10
% h8 n, t: m7 Z$ o7 J! s3 Q+ w11
* f7 E7 k: j- I( Q6 G( g% w: b$ S12
, ^7 G4 M. q" g; D# I% U) L13. v) l. a# j! ^
141 E! i9 }0 Q; T7 r8 ~0 |
15- I8 z+ J# B1 N" x. Q4 n
16( ^' C9 u) ^( |9 {& G# l0 @
17
, w: W) @0 q8 j185 a# K8 K3 R# W! R- G* I
19
+ l- g s" ~: Y% e; _% U. r. a+ o5 {20: T# s t" w, l
21
) n( @5 a9 p9 h( g8 z7 c3 B7 Q223 d/ b [2 B; Z- W
23
4 V1 z5 L( v7 A- s2 C7 ~24, h0 _0 r1 f/ q. m5 V# Y( F
25" I9 `) V! R! Q& B0 O2 |% G, @* D
26
1 @! q5 R) c# N( j: \. u27
2 l& D% R1 E: Y0 Q [2 k3 F28
2 m4 i* V/ n/ ~* F8 U' b299 w& n' H, |6 B+ R* [7 d9 D
30
, o8 T) j: `( J* s+ X, X0 t! H( G31- p0 F5 `3 l$ k7 p( q2 k
32
* y2 \( {: u4 H6 d3 a( B! G33. x6 v1 s; z9 S- ?7 G
34
' _$ @0 _8 \! K35
+ b" h) i/ W- r* m# Q1 `5 @36
6 V$ e( A3 a6 V2 C370 }/ B5 C# ?2 O9 j8 l5 k+ b
38! T: a# K# y+ D5 U& p- d
39
, M- K4 d; v% u b8 V+ _40
. x, @* a7 i8 c* t6 N41, \6 b2 Z. \3 Z* K' U, `4 v; g
42+ |- G) U# C: q' k7 U1 e
43# x7 x5 l5 J; c1 l8 F5 N+ A
446 g' _* s$ S" S4 C3 M
45+ w' }; n( ?2 B$ X$ G' X
46
, \/ x; I3 O6 \! w+ K3 M47
+ q3 X, Y( o" x48
9 {: c. x0 r& K9 p49 ]8 ?3 ^: u1 C. f s, T
50
- r* s* W& L% d" T9 H51; h, S) M/ m, K) l# R' t# o, f
52
0 R. x! G1 U% }/ L0 F, @, j537 c( W& V6 l) ?$ U e
54) ^+ d7 M7 }& H" h4 C1 z; r
55
1 U. v3 E3 O4 _56
$ K u+ Y* R* x( z8 z57
- h( I) l7 P4 w4 Z8 A0 C; y# F; c58
: w% `# ]5 o2 I8 N59" w$ z+ ?/ y( ^
607 @# T, V' N |/ R) A
61
- q6 ^" p& {' q6 i62
0 L( P6 w" G2 \5 U启动数字动效
" s4 e w2 p/ k- W) K
8 S% B" q" M# Jconst startCount = () => {7 |, x0 N5 k# \" l
state.localStart = props.start$ K0 c8 K- X! |: s* r8 ~5 O* v5 F
state.startTime = null
, M U3 D0 U7 C state.localDuration = props.duration
1 U0 ?! b- l/ D7 n! ? state.paused = false
# @7 D" K, T/ U+ `: o9 j6 f! i state.rAF = requestAnimationFrame(count)
! g( g' i0 W) x}4 \! k+ t0 ~2 @% g; j
1
* G9 L( H4 `! U% v2
0 Q D/ r1 `6 a3
8 p& w2 _3 E ~+ f, \4
# e" s+ W3 d- f8 a1 J7 d5 T9 n5
/ T5 k" m3 b6 F/ ]9 H, [# w7 C6" o \5 h2 q3 ]5 S
7
8 t+ ]# f6 C0 r. H0 m核心函数,对数字进行转动. h' g$ m" @. x1 n# Z# \9 K
/ x$ ]$ H0 w+ P) { if (!state.startTime) state.startTime = timestamp2 E" ^: ^, T8 C" B7 o
state.timestamp = timestamp. P6 ?0 n7 j6 G% f
const progress = timestamp - state.startTime( Q9 }+ B! b0 v, v" P m! O
state.remaining = state.localDuration - progress4 g0 Q( x6 R; k2 k; C. E
// 是否使用速度变化曲线+ x/ r' j% J6 h
if (props.useEasing) {
- o9 q. `# ]2 }3 ]/ J+ Z if (stopCount.value) {0 P: c+ l6 K P+ d% a
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)* t! F# m; M7 c2 s* b
} else {1 v* c& U& }! @) q7 O
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration) l7 i; D( _; ~- W9 K- t0 x, g# v- v
}
9 A' ] S- A2 } } else { M* Y0 P" J6 V9 H
if (stopCount.value) {
) L4 x! L. d! J state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))9 k$ ~6 L5 f f+ Y' f; X
} else {% x1 i* ^0 m( W0 S! W, _ q( K8 a
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
0 m7 T- F* P) Y. i }7 i5 G/ `( t. K8 M% ^# ~4 f1 }
}& _. P/ x3 O | m* ?2 P
if (stopCount.value) {0 z6 f# r* U$ a9 l: f7 d) O
state.printVal = state.printVal < props.end ? props.end : state.printVal% g2 V. G6 c+ C
} else {
5 g+ J y+ o1 j. {$ \' s state.printVal = state.printVal > props.end ? props.end : state.printVal
; n Q' k5 |+ w" [" p# s }, g# D; e$ V% _! z1 U
2 o; W+ P$ g9 ^% K$ s
state.displayValue = formatNumber(state.printVal)
' ]' d/ E) n) b, Z% y if (progress < state.localDuration) {7 _% g& y# q6 p6 z3 K7 ]; f
state.rAF = requestAnimationFrame(count)& v _$ U v2 N: X! T
} else {
5 a- V* u1 p, a' g& s" g+ M3 q- h/ J0 J emits('callback')9 x1 F7 o* x& ]+ {
}% k9 B+ L& t) R; m( L- ?* `: K
}
5 ~; b3 w+ C( I. q3 N9 ?. R& q
, C0 _$ C, c8 H; q+ }0 d& q; b9 H4 ~( D8 ^0 n( ^" X# O
// 格式化数据,返回想要展示的数据格式
! M) F+ J% r6 ]) ]# @' vconst formatNumber = (val) => {
) B3 a9 y7 G) e8 n val = val.toFixed(props.default)0 Y* b; n2 q- h( | E; r
val += ''5 e r% F) T; V
const x = val.split('.')
% d2 E4 H% Q. R6 k, D* P let x1 = x[0]
* U5 i, S7 b# R4 h" j/ J const x2 = x.length > 1 ? props.decimal + x[1] : ''
p: G7 c5 E, J E const rgx = /(\d+)(\d{3})/& @+ V v+ U3 F E! c
if (props.separator && !isNumber(props.separator)) {0 u& Q! S! ?* i- o' b' v2 F9 T
while (rgx.test(x1)) {+ Z6 V( }% N, v6 U$ q- Q- Y8 w
x1 = x1.replace(rgx, '$1' + props.separator + '$2')0 W; C( t# g: [' x& X- A
}, R; L" f* I5 F2 a: L% G- z! I
}
0 c$ M( H. [) h) a return props.prefix + x1 + x2 + props.suffix
% f6 {9 c! H4 V0 V5 f6 n; @" S2 R}
: z w; F/ n1 d. }& J4 @! s8 Q/ F {. H: {4 z$ _" U, a* ~
19 p' J" @- H, i$ `& L* o% Q
2. R0 l, S! `5 d) D# X7 I8 M/ u
3
& [- G5 @, y4 ~9 k- v* L' K4
8 ~) K$ i+ v# M! m5
( }5 n3 u1 [ w( h4 M6$ o$ G: ^1 b* s: {+ S
7
1 l" G- ]3 e9 ~, n- p, Q- \8
! V( O/ n& q9 q& ~4 w6 ?/ D0 {3 J94 o# Y- x9 c+ J2 x- V
101 V4 y$ P) I7 `0 u* [
11
) O) t& A' P8 y1 u3 G12
2 M; R( W4 g- t/ D% C/ ^13
7 W, K [' F6 |; [14
0 a! f6 |7 r! ~% a15
/ X+ R8 S; u& J6 q7 A$ m16; x* H2 R2 M7 J7 C$ ?- F
17
# k6 k4 E* \ z18% f+ k/ X( K, h
19
P0 Y$ l. X& t6 ], ?2 z20% g& [ I% B; z5 U" @
21
$ Y1 a f$ Q9 L* q. n% t( q' M225 T2 ^) m2 V) H7 [, V# }
23
+ j- G0 w( d# W$ H0 Y1 _1 T24# @) H5 }6 o. x5 P- b
25) [4 v+ Y9 d8 b" H3 C& H
26" P; h* Z( h, B- v# g' T' c5 E
27
2 t# ~: [) }# i/ @28
0 q* |, B1 r* {3 a% C7 w$ a29
$ X- W" u8 s; v$ }$ J8 F6 s30* C4 {3 N0 e9 Z& `* A* Y8 Y
311 u: J- g5 d" a
32# [& s5 f' j9 c
33, k/ U6 Z9 Q [+ }7 q
34( {) H4 r/ g: w! B# u% I
351 N% }3 m! G C' m; f4 ^
36, K* l5 V* g7 z: v& a$ m$ w
37
; @6 H# e' J% [: y$ g" j( t; P5 \38/ ], e. h% C) y2 w( C$ m
39& p6 z1 @/ ~0 Q
40
- C0 f8 f1 p1 @# P2 Z2 A41
4 Y1 |5 ^2 R I/ k+ m42+ y, u( z1 k8 H4 U% s& u
43
& I7 v0 k( ?9 C, j" K2 t! r/ {5 x44
* X: n7 ]# P. l5 P6 C* e9 y" h( @+ G0 G45 e6 z( V- H/ l7 |
465 v3 a) u# _& f3 X! Y# S0 y
47
) y, s- W% Z* H9 S/ o! r48
; J8 b0 O" e H取消动效: b g' I# I' U2 A1 f0 }. l
2 G; R. @/ ~( M9 v* J# `+ j
// 组件销毁时取消动画- |6 [# s! n/ } s, I9 m
onUnmounted(() => {
2 |; c! U0 n$ d+ L4 c7 M) f cancelAnimationFrame(state.rAF)
, k# T5 I; w7 e2 |% q/ r4 ~})0 z3 y x+ ?7 `- b5 ~. ^
1
' l' s# X# c0 \5 v/ R* m1 e. |2 _2
* w; a" A" G1 V- C( Q32 w- c& ~: o) g' y9 v+ W
4
4 W) M7 D5 \' F完整代码
0 {# ?1 X, x+ m7 x) ^4 {2 ^! r6 e' f- f; B
<template>
) m1 I0 {, s4 U, h1 S% ]# w& k {{ state.displayValue }}
1 F+ H" v3 v3 P. D5 g: e F</template>6 y1 \6 e4 e. V; I9 E' l- @; U
3 l0 D5 J- ~2 M# t4 Q
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
( \ Y2 ~6 v/ v2 q0 ?import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";& `$ j: P+ H5 C# O, s
import { watch, computed } from 'vue';
9 F1 ^& |8 Z7 uimport { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
1 D* N* a9 q# g/ u' `// 定义父组件传递的参数6 e: T. S% k1 C9 `; Q
const props = defineProps({
2 x8 E! H R5 e- l% A& b! ^ start: {) h& A+ F7 d4 ^9 f
type: Number,
6 l |/ a1 {# i required: false,9 M1 b0 n; N H. ^2 e+ s2 `2 x
default: 00 ^# {* N+ w# y/ O1 t9 y& R$ @/ V9 ?9 T
},9 F2 n1 U8 `( w- C- m, ?
end: {
. f; R/ u3 O7 u) Y, n type: Number,% a! |: C# W- N4 {" b
required: false,0 n$ f6 B3 x9 S& {
default: 0
% b& n7 J% {9 r% U7 `! s6 q% ^ },
( A |5 i% C3 `/ L duration: {
; w* @& X: m% Q4 E type: Number,) z, p& s8 h" m- e
required: false,. `8 l. ]" P0 B3 b
default: 5000
; n% b# L- A6 H; G },
" M2 i/ _. f+ l0 F autoPlay: {
7 G% o( K- |7 g type: Boolean,
, G# p# j: n& G: w required: false,9 P% ~5 s2 r( P) o: |" \
default: true) d, ?/ C; _# z& k" |( _4 N3 a
},) B. s( n* Q7 Y. Q- k
decimals: {% J; D* z! I, G: o1 p
type: Number,
; V0 m. l+ u0 N3 G; Q required: false,1 [$ s" `0 @5 v* B" S8 m; f1 }
default: 0,
$ O. Z. W* S4 c9 C' Y+ y validator (value) {6 }, f( t; i, s# ~
return value >= 0. }% S& @7 F; t0 |$ ]4 _/ j# U' B1 v" g
}
( ?9 z& N% V! Y- M0 A* M2 j, X },8 O u( y: r6 Y0 m2 w) {
decimal: {
" S2 y( t, a1 _. k9 d& F9 C, b type: String,& ]8 M4 a/ s! }& o
required: false,
& z$ Z6 g) Q1 Z0 C6 q/ m5 u: ]& M default: '.'1 d1 \' N5 e0 {: E
},
+ u, {( [) L* f; z8 ? separator: {
& {" k: M) h) c type: String,
3 b$ \; w" {( V' W$ U) v+ B; P required: false,
4 U. U# T$ r9 d$ x8 L" i( U default: ','# ?" d3 w0 l0 ~* ]: J8 Z
},9 f0 W) \$ \2 i8 s* }: t" c7 y
prefix: {
" H6 y5 K ~: b" L type: String,' a1 H2 w' z% v5 j, ?
required: false,
/ n# n% Y7 W6 u% R) J( E( P! ~+ M default: ''
& _1 f) |' N: b% z+ o' O },8 w* w7 C: x* |, K0 p5 {
suffix: {
: G2 {4 R- w4 r. G( c type: String,
8 [, ~- v- E7 R2 m1 m0 d$ w required: false,
+ k9 U! C; p7 _( Y default: ''
- ^& i/ T' f, O2 J* p }, q* S7 C# |! l- @( v! f
useEasing: {
( b; _$ q3 H0 ~) l2 ?6 S. f4 N9 ]0 ? type: Boolean,
) v0 c5 B" b0 g, a- g. Y! S" f required: false,! T# j. V2 }7 Q1 D/ r
default: true* U8 ~# Y' R1 t. B) a# l
},
+ E5 Q$ H4 @8 S- T% ?& W easingFn: {% i4 v/ o7 ]. N
type: Function,
' l! p ~# \; y& l1 d2 m/ S8 P default(t, b, c, d) {9 x% p8 n! ]2 s
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;( W3 Z' z/ B) J: ^6 Q
}
# H8 S% j1 { e }4 s1 L7 r8 q, O& a: S5 m' _0 e
})+ O+ N3 Y" x/ d! ^, e5 L, Q
; j. g& F9 d( Y! G
const isNumber = (val) => { X* [" C6 ?' @, M1 u- Q. t
return !isNaN(parseFloat(val))
4 ~9 @" ~+ p6 U o4 o}
: D$ U7 T& d+ {# H4 Z0 [8 o3 p i4 q) @" ]7 \* L( s
// 格式化数据,返回想要展示的数据格式
- d6 z( D8 u8 \4 Y6 p3 V. D% Econst formatNumber = (val) => {
# w; G! ]" D) G/ l val = val.toFixed(props.default)8 v7 Z) s( ~; F, ]( |
val += ''+ }! o. @7 d9 i& s$ Y
const x = val.split('.')
: B* l/ o. y! N' r% e let x1 = x[0]
& S+ _& R w& Q H7 c { const x2 = x.length > 1 ? props.decimal + x[1] : ''
( S9 G, h# e) E V I$ e2 I _ const rgx = /(\d+)(\d{3})/
) @+ ~, P9 ` ^; A* A7 _+ c if (props.separator && !isNumber(props.separator)) {2 h e o& h) _3 g$ w
while (rgx.test(x1)) {. _( k3 R9 K/ O+ M& y
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
% [ m; ?8 C S0 k! K4 J) o }* Q$ M3 g1 P/ H" T% D
}
# J& J- ^. d3 J! X4 Y5 [ return props.prefix + x1 + x2 + props.suffix: w/ F' a& B/ F; ]4 U2 B) l6 D
}' q3 s8 k) c6 @9 B9 Q
! d4 V: R5 O% }1 D) R( i; D- y4 Q// 相当于vue2中的data中所定义的变量部分
* n0 ]: f+ c* H# D( p2 Z7 G" j3 ~: qconst state = reactive({9 m7 U4 G& C9 Y! N% _% H
localStart: props.start,5 V8 W2 y- ?: \+ f
displayValue: formatNumber(props.start),
$ J% {4 c& I7 t, y" @ printVal: null,# N( V, `8 l. k$ x. m
paused: false,7 Y5 q+ l6 C6 l% h
localDuration: props.duration,
8 ~8 G/ P" ?- D" E4 p6 m. S startTime: null,6 O. M6 U) J) D d3 v9 e
timestamp: null,
" h8 F) B0 j; P! H remaining: null,
+ j M0 ?" b( @, C. r4 O" b rAF: null- O1 G9 i e0 D7 v& y+ v
})/ z0 c- a1 {6 J: ~, z: u5 h
5 ]1 z( T9 w8 L6 l) j, Q& J// 定义一个计算属性,当开始数字大于结束数字时返回true
, A9 j$ X! D/ \1 \8 A5 G' r- kconst stopCount = computed(() => {
0 Y5 m* ]9 d( o- J/ I; c: Y return props.start > props.end8 R4 K7 H8 ^) H S0 g
})3 I$ ?& b8 K( |3 E4 l- m
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
1 `% r+ P& E. }const emits = defineEmits(['onMountedcallback', 'callback'])
. N/ w8 u( J0 R2 Y
1 I. M" N4 y/ d2 i3 [ c3 Wconst startCount = () => {
9 `: j. |$ Y% ~! n8 A state.localStart = props.start
0 j* _' ^* Y# K- b" H B state.startTime = null
8 H6 b2 V* E3 K6 S+ ^( K+ ?/ p ? state.localDuration = props.duration% R* P. b7 i/ h5 T( x
state.paused = false
5 K; U( @& J4 q, j2 s state.rAF = requestAnimationFrame(count)
2 Z: ^' G, {5 K9 `9 K. V}: ^; h P' ^' j6 F" H; a
. J! O4 n: j5 {4 C2 W
watch(() => props.start, () => {& ~. R* C( b/ L8 y9 M8 k6 z
if (props.autoPlay) {
1 l2 W) l8 \+ \! H$ n, r8 d9 }$ q startCount()
* t0 h- I+ e& j) _7 X$ X }, a& k1 w1 L, W! V2 L
})3 V4 l2 H( H6 a/ I/ `
% c4 l+ \' o/ Dwatch(() => props.end, () => {# x3 Y, V9 ]4 |$ C9 p2 g
if (props.autoPlay) {+ }# I- A5 b, z8 r9 c9 h) ]
startCount()
% e9 x6 b2 _% b4 s, _ }
- C% _& d" O/ y6 \})9 m. t% R" ]+ t3 `
// dom挂在完成后执行一些操作
% G& x& d4 D4 xonMounted(() => {
3 E, W+ x6 ~" S; H) L if (props.autoPlay) {
5 q. D) w) z! i startCount()
5 J6 \% J6 \' a% G& n. b( l5 D; w }$ x, P8 a" d! j+ z8 K
emits('onMountedcallback')
8 h, U2 P$ u2 [+ t' W})
( ?& E7 h2 O/ ]& @+ c- l8 Q// 暂停计数6 ^- k: _, M# ~8 d
const pause = () => {; S/ w4 Z& c5 M& S% t
cancelAnimationFrame(state.rAF)' Q) [3 r8 K7 i+ |* E$ x( v
}! u7 u$ `* {3 O3 d! \
// 恢复计数, [+ E. N, v: [! I2 c; J" n
const resume = () => {; |1 R, W/ C+ s6 @, J
state.startTime = null5 Z I9 ]: E; w1 m1 y+ I; A0 o9 v) X
state.localDuration = +state.remaining
$ z+ ^) K9 Y& }& n! } state.localStart = +state.printVal
' ~1 b& | L: s7 s6 d requestAnimationFrame(count)
5 g. W p9 }5 S. j! o: {- T}
. b/ w3 d. e3 u7 I- ]% z- a! T' [9 [6 X1 `% Q
const pauseResume = () => {1 n m" d4 P0 `' E. A( i2 ]5 F
if (state.paused) {5 {1 h% S& z: X; |8 b/ q2 a! @1 x. P
resume()
0 Z: b' O' S! J! F' h state.paused = false0 b& z! V3 T, b- y$ w
} else {
7 h7 o7 O+ I: G+ y) T; u, m pause()
" q O a5 N5 \+ h/ R1 z1 ^# a state.paused = true; C) y0 z6 O" F, D
}
5 h* D g* h. _}/ F5 x4 d; t4 R
8 G$ j% z% ?; a" O1 Mconst reset = () => {: t1 b- n8 v$ n5 ^4 i) R! f
state.startTime = null$ q" \! J/ U0 s) K
cancelAnimationFrame(state.rAF)
1 w. W# P f5 [" H# v1 \& @ state.displayValue = formatNumber(props.start)
5 p9 Z! a4 p1 `$ ^}: V6 M3 @) q8 j0 J% c$ h/ z' Y
$ l- j3 k3 L: nconst count = (timestamp) => {
4 z/ t, @- d7 u) A: h if (!state.startTime) state.startTime = timestamp
9 q$ ?8 T4 \3 u; T state.timestamp = timestamp
- @) F3 C$ h( l. R+ y4 C const progress = timestamp - state.startTime
% g/ `- ?5 K6 a) U. k* r0 @/ D1 u state.remaining = state.localDuration - progress
2 D/ @: ?/ F+ r, Y: j // 是否使用速度变化曲线2 ?2 r) B) J& u, p" w+ B9 ]- }
if (props.useEasing) {
9 ~. {8 F: M: H) j0 ], U) X7 x if (stopCount.value) {
& g9 H1 v7 ^! y6 H( t( l4 r5 B state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
0 Q3 R6 ]) Y, c" e% | } else {" k. z. P4 ^) m; S
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)2 ]# P( n; r% H
}
4 W$ w. l& E# ^% _$ O( L9 O } else {
1 i4 C% L- `$ u }0 x- j4 R if (stopCount.value) {
" f$ ^, r- d( [9 B state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
4 t+ N2 W3 n& F& P } else {- z. l1 G# t& u( ?4 B
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)! X' Q5 l" e8 N; z' d
}
* D5 Y; ?: G) {( x' G: e }
7 A- g: r. ^/ K if (stopCount.value) {
8 ?& C9 a3 k2 e- H state.printVal = state.printVal < props.end ? props.end : state.printVal
8 B: C" G8 y8 n8 @ } else {$ N& U9 @+ z8 c+ f& n
state.printVal = state.printVal > props.end ? props.end : state.printVal( V7 `" z- ?4 c6 I d! |+ E
}* A; c4 n5 X6 Q% x. A3 C
$ {, |# l# t9 d ` state.displayValue = formatNumber(state.printVal)1 X6 j% w" t; k t: E; e" h
if (progress < state.localDuration) {
( a2 }5 K* J# f' t& l, D9 C state.rAF = requestAnimationFrame(count)
4 U( j2 C8 N( A } else {
/ }5 U5 J4 `6 T3 j# E1 a/ u emits('callback')
* q9 ]. ~, y( d4 |: Z% Y }
3 l) `+ J2 K( `6 Y; H7 Y" O}) X# N( s$ p0 E f. q0 i
// 组件销毁时取消动画1 k! z8 r5 m! _9 u/ }
onUnmounted(() => {8 r8 q/ p; Z9 v* t$ P) K' j
cancelAnimationFrame(state.rAF)7 R; Q0 O4 b/ m. R6 M
})
6 R* B) a# x/ G9 q! D( i</script>! V4 V3 k& N# }7 ]/ m! |
' n% }' r! I$ p* I( s) i% T M1
8 Y9 i/ V. K" \2( m0 y" X* c0 o# w7 Z1 N
3$ A8 h; F9 X2 ?! b; E+ y' k! j- `, T
4
- ~ n6 M8 G' n- V; Y- O5( f; l) _" G! v* H! L
6! z, e1 T7 Z0 l2 ^( L9 e ?& q
7! }; F3 i, A" o0 \
8# M5 V! x' l0 T$ o
9
" p. C( M8 X2 [, ^3 P106 a7 [" S* q+ n
111 n$ K3 B; F; O5 q. i V
12
, K) M; F6 E% O1 v13
* |$ F3 E! P/ F14
3 L7 R1 q' G# \: l) i- U15! p2 |* Z e, j7 F; M* \ B* s9 n
163 z5 D9 K" K" M
17. h8 T; n. g% ]
18
! z0 Y, ]% y. `8 a) h+ f19# p+ a6 W: h) b, m) |4 D+ V% z1 R
20' W# Y# J/ ^ X9 }7 r+ u0 p' N: n
21
( R' ]5 k6 {: x3 D! d4 m22# h' Y+ o( W8 Z1 `
23
/ v/ d" Y/ C# ^* Q5 ~1 m243 f0 T4 }( L6 k6 q
25* ?" i' O- N" F7 ^
26
, {+ J5 p7 r W+ s6 H. h27" C1 Q/ |" w. s: p: |: B: o* A" g
28
$ f" k/ Z# H1 \8 v4 q) `4 K29( o1 E0 C1 [, o: u+ q8 x& d
30
8 z/ S4 y6 Y6 ^; f31
7 E+ @& d" P, v- K0 S* P; U+ m6 X32
( N2 S" M3 ^+ o( A33. L o0 \: C" U: N% B0 b; z
34
- S$ {" w7 M0 r4 S35
4 @9 O+ L2 ?+ x0 z6 h# C36
5 j6 c( @# V4 ~7 H4 R$ V/ l37
( ]+ e6 c. g9 |3 |, T& n L38) Z" `; T" R8 B5 M
39& x$ X3 Y/ @- N# {( r, j
40 l3 t5 F0 K5 u( L$ w" _9 C* C5 `
41
/ v& n; t0 s5 r# Z0 w6 F, _. M42. P, }# f" c6 G F2 [, B; j* I
43- |4 h5 {$ H( u
44. C" h0 t4 S9 ] H* _- g6 n
453 J" L+ i- h6 D7 n7 S; }5 J
46
0 J3 w7 t( V; V. r* I47
( x; _- }9 D3 [5 N4 y% h48
. H0 W) `5 v q49
1 ?, S+ ]9 m" j" e& I509 O. s" d3 `3 ]4 G" F) v* r* V9 l. r
517 h" S* T8 K& m" I( J
52
' Y: g# `. n7 q* h* G* Q- G535 j* P8 o/ A. H- b* c
541 Y* q* b1 B4 y5 k b! L! }
555 f2 E1 x( I& [1 J
56) O# u! X" f" p$ ~
570 V; l! U7 ]+ |' c9 u" V* j
58" q, F! Z+ f1 O* \
59
% p* u. j2 k* b! m1 z* u. p: F60
], K! S/ h2 p, z61! Q7 Y$ n( ]( _$ d! i
62# M: e: L5 _5 M- Q
63/ s+ ^ B# O9 V. ]6 ~% D( }
64$ Z2 h! [% b: o: o7 Y3 |' H5 b
65
: @: v- d5 J! B5 T66
8 O# }" s! T7 B* _679 J, \8 t2 z& a. `* L
68
! i9 l( c9 C( o. T+ J8 J1 B: c69' r$ X. E9 b# p- G/ J t
704 s1 q+ F2 K5 m/ M+ {2 s% Z+ C7 G
71
% H6 f% b9 Z8 C8 F. V! b72+ k" T4 S) ~5 B& M" w
73$ S Y4 Y _+ ]" h" I
74
8 k( _9 }( O# j) ^75
# {2 Q$ a Q6 Z76
* [1 d' D" }, w* }772 }8 ?, W- s2 a
78( J' J" A* w+ G m) L8 {* p
79
3 T9 h3 f1 i; s9 f) H80" r. H' p' Z+ n6 E
81
3 S2 v6 X' g& U. k5 C" `. I82
7 ]: a. U( S/ }6 L8 o% n$ y# }83
8 J0 m. f6 m6 p# W4 D+ Z4 }84: t: y% A" ^6 I7 l& z# n
85
: G h9 A5 B6 v5 D+ ]- ^/ F( P o86
3 ]) z9 p/ R1 K; ?4 p87% G6 ^* U$ e# x( _- T1 ^
88
" W+ ?) P- l. K1 a# X) j! I89 \8 }% y' T" j
90
, A0 L! l9 G) y# c1 e3 ~8 q91( j- w6 k+ X4 ?1 }: r" g$ V, D
92
5 ?, c# u) p# k& h93
) j2 d* W4 }* j- T2 {+ E+ F94( L( h. V' d1 C. m: p. `7 ?+ a
959 l3 ^$ G! _0 [. h; ~
96% M& D9 H; b4 y# l* d2 G
97
& `5 W$ H/ j% z- K ]) c& x98. `/ B1 k! v1 l1 k) D! \( Q1 Q; O9 O
99: ^8 k$ `- N: m8 L: G0 m
100* \1 U" h5 n, |% _( Z1 J! z: s; `
101
4 [+ ^) v! J! N( K) ]& s1029 {6 `8 E6 y/ q1 J* ~2 S# \' K/ ?7 \
1036 ]/ J" [7 a' Z3 g$ [+ u
104
5 O0 b. P2 F! ~( e. Y7 |105, m1 l0 O& f6 }
106
5 Q8 E2 Z& ?9 Q1 }107
* N% |: j4 V% h( X108% X' u3 r+ _, U
1096 I* ?$ C+ B! _ d0 T% u! R
110
& b( n7 Z# M+ P& v% s7 a0 ~111) ?+ C8 \- _$ a9 `
112* [! M7 `. f" H3 O. g8 y: V8 M
113
! C& ^) z* U( ^3 j114. C9 I! L! C3 V6 x
115
4 s+ d( f! {' b# `' ]0 W S9 ^( S116( ]; o% j# f0 R2 n% h
117
/ y& u5 ^- b7 G' ~3 A" F- {1188 k0 R9 p3 N9 J& d$ v
1194 S( |# e m# J6 n# A
120
, G2 `: ]. b5 |121+ t) F" a% I" T% W- J
122
9 K$ V8 |3 N/ M6 g6 A123 I v/ F5 [0 F; e: |% n. i6 z
124- h3 S; Z& r2 q( w3 P- @* L
125
X _* P6 O: \ k% x0 M" w126# X" ~& N% ^) v3 V+ w( K3 A
1276 R: s9 v8 r1 u1 g( {( Z
1285 h) x3 K+ m D8 o# w' T5 r& R
129/ X) C) i3 b+ R
130: _3 j' D/ o6 b+ Z
131
) T% w: ^) e2 W; K6 @, E, H( [8 E132
. y: I2 V9 Q4 ~. ]" a6 t133
. x8 }9 D# u6 D! {- V0 s3 t134
& i# g! d3 j; C M- ^7 G9 V135
3 f. z% F/ o# Y @+ C8 G136
9 m$ F2 U7 U+ `3 n137
0 H$ n6 }$ t0 j3 n3 v2 w138
l) Q0 L4 Q. K' s139
1 Z7 l/ u# X- d l H0 U140
; }9 A2 _$ R7 F, I141
0 n+ m l8 y; v. h0 i142# S9 u* H6 l5 [
143; e' t7 o1 S; l: p( s) ^
1444 ?. a: y* K6 X4 v3 M! l' [/ I
145
; _0 o: o% M Q2 N. R% [4 j7 D146. l" _( M3 U) o. R7 j
147/ @; s' m! h; a* [
148
; N( f6 {4 o' o; c$ g5 J$ c149
# i: F- ?9 B0 M150. b! e6 }: b/ W) C$ u1 I$ f# n* F
151
5 W/ k6 `+ U7 U, ]& Y$ x152* o+ ~* E. {1 p9 F
153. R/ S, w5 P& u$ q
154
5 j. I4 O, G% ^7 y" D2 v7 z0 D: ^: L155' c" p3 Y+ ?3 i6 v- z4 b$ B
1569 q. h& M) t, ] r$ p
157# o e! c" C7 j" {
1582 m+ z+ ]) {; A* U! g6 V* T
159
" {' c' h {" f4 C; L6 o) k160
9 C% [' d/ f- U7 A$ ]9 m161# M4 @" f# @: n* ~' o, w
162
}6 V# q5 @) v, p163( ?0 u# n6 r* ~0 ^9 |- C
164# j; h" B5 X/ |; N8 x. K
165
5 e. ~2 m `5 }9 I+ ?% n* Q2 ~166, d" {- {! M. u% l5 B" a# E+ }/ e
1678 {, f+ x) _1 W8 }
168
; j: s n7 Q! N169
Q( H! P r: n1 g7 L2 M170
3 v( k, u6 Q' W* g" s1712 `! P. ~! N3 z
172" o9 T7 r H5 g7 n1 {. A* F% l
173
) n% D1 h6 g) H: ?* f+ @' ~7 \6 a174
, D0 ^0 t6 r7 a3 s% L175/ F2 Q0 [* P* N, i8 k4 h
176
$ j2 C+ P f: {5 G177
1 r5 I+ A1 [# W4 k6 d% x178
- u+ y3 e$ h' N; k2 n, K) q2 p179
6 r/ q2 X' r) r" z! `% P" q180
/ t" A3 X5 }0 N0 \" I9 D181
$ V: X: ~0 J. a6 D* ^( J* C, U7 ^182% G5 S* S) u* _' v1 e/ H
183
9 d& P% o* P, V( K+ d3 S, E( h184
& M% ]. h! d$ _) I185
3 ]1 j. Y% x! L# q1861 ?6 [4 C4 E! f, D3 `( p
187% j" u: ]' [6 U' O$ i' |
188
% I0 @, u B5 t4 i3 i189
' k- s# q* W9 j0 a190$ K& C6 w8 L9 E/ W8 K" A
191
- e7 t! b, F$ i9 d/ E2 s192' a* \. x0 Q |, l
1933 E* s) E) y# x* O
194
3 K5 G( d* q; f* v5 x; I# Z* G& K195" Q+ h9 Z9 X: v5 G2 [) x
196- _+ E2 B/ G1 N# t% ?# v4 n4 S
197
9 h; f$ o4 l1 I6 d/ t J198. w9 ]2 |9 \2 ?- J% ~' H
1997 F5 I/ V4 ]1 [+ d% N
200
+ B8 `% g3 p1 o# ^* i: p# N201. i0 ]; t O% I$ l
202% w* w% x3 g) N6 g
总结
$ e! Q/ K& V$ B' p% B自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
7 W$ V8 d! E3 J/ E# ?5 w& l/ b* _( M$ d, t& ?3 h% i. w3 Y; S3 Q V( M
demo演示
, S1 S4 q" m5 U+ n# ]/ R后续的线上demo演示会放在
4 F1 {3 B' r9 a5 ` C! Sdemo演示) F. F- A' j" H* T- ]5 }: N& q
完整代码会放在0 l6 }# V+ P' @) A9 _
个人主页- c: M# q7 p" F8 f# k( ?; ^& k
9 C3 X' R* X" k6 y( Z" F( M希望对vue开发者有所帮助~' N$ a" k1 @2 n9 [' e7 i( R+ Z+ R
- J. m- M, F. [3 O
个人简介:承吾
( O) C/ _% D1 D: x1 g5 G9 D工作年限:5年前端
& K4 w2 h- d: L) `% D' t地区:上海
3 A z; D7 }- ], s个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!9 L) m& ~4 Y2 X! o; T6 g+ c+ Y. [
! d5 j k5 s8 O$ _" @
+ q' j4 e C; I E# d4 _$ ^3 ~; a. B/ S7 P& [2 p8 x! s2 e2 h
/ U8 m0 j% ^: R6 q0 u————————————————
' `6 f' [6 N) z! L* _8 x版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
% f) [( c1 S. R原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
% x& O9 t, n4 n$ ~
" V8 h6 Q. n% U0 U% J( @' M7 t$ _1 D+ `0 d3 E
|
zan
|