- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563264 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174202
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效2 E5 x2 p1 O" W$ Z8 r& M
/ `! o# `* b4 p$ o- ^前言
+ I0 c' R" f' H; @8 R& b, Cvue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
5 o& O$ I5 C* `7 @; a1 TTypeError: Cannot read properties of undefined (reading '_c')- ~" ]1 h5 g; \5 Z. g; }7 Q; z
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
5 W+ R& V2 ?2 W3 h. `. e
+ R) z# Q) \& x4 c4 P& D
. P& |. p! D! G3 N思路: c; }0 x; G8 |! u' [& {5 S- h& ~0 A
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。- C v) V. N4 q. {+ s: q8 U
" j! @# u5 e& V文件目录
9 Z, c# w7 U3 K, t' e0 W- I% y7 ]3 a+ K5 B9 s% s: h
$ o- j x6 E+ \
使用示例6 O* ]1 h4 T5 S7 Z3 W' Y
<CountTo5 S7 A: i ^7 s2 M X
:start="0" // 从数字多少开始# {* U- M }0 j
:end="endCount" // 到数字多少结束
. [1 Q; O+ w7 q& ]0 _: }9 g6 v' S ^' V :autoPlay="true" // 自动播放
* X7 ]# v* P' Q) l :duration="3000" // 过渡时间
+ e) X Y/ \5 j' R prefix="¥" // 前缀符号2 g' V# F# H) q* t1 D
suffix="rmb" // 后缀符号9 y! S& b. }. g& k! m
/>
. d( I, W% S+ d" f1
1 \; \" @) a) q! F# ]: L7 Y2
1 S9 ~: N3 Y s3 g% ^3' W& B0 z" k5 U' e
4
) u9 Q$ U2 l1 r5 J5
7 W+ k w% `, q7 d `, N63 r; p1 b3 X4 W7 R- _
7- h, {2 m+ }6 p# \- B: J
8" @( o8 h1 C4 Y z. \
入口文件index.js1 o7 i; c4 |+ c7 q- Z" l. _
: }7 l$ y7 L. ~7 D
const UILib = {
& }; ?: \5 J3 b! N) [' O install(Vue) {
) \) U* v( E2 r6 i+ ] Vue.component('CountTo', CountTo)+ w6 @" K8 h, H
}& ?- c1 F) Y4 q: d$ M+ d. A/ ~
}' s" v4 w- B Z/ W
/ D$ z4 r7 J+ b6 V% J7 j
export default UILib
2 L- e/ b. i. i& ?0 N9 L' S- J, N0 Q+ q) k/ K
1
3 R6 z/ P7 g1 T! ^4 _2
" J# B: p4 l9 E' U! ~3
+ X/ T2 E4 }) {6 T1 H! n4 K/ Z47 M: G2 e* y* ]( U
5* z8 {# B5 q) b3 ?4 R$ z
6; U" ?+ Q1 N! y5 U$ S
7+ Y. m( b v& Z& d! ]" [& N
8
) |. }' W/ W8 b+ \3 n9
( s& k) p: P; I2 |- C# M& L% Q' smain.js使用
* D5 I. i: f0 gimport CountTo from './components/count-to/index';/ [1 m/ J8 z$ A! P
app.use(CountTo)
/ \( f- U E6 p+ N1 y }12 c k' L* M6 I7 S) k
23 F7 O3 \# b& r1 N* p# ]1 \: c
requestAnimationFrame.js思路5 I4 ?. H) W0 J
先判断是不是浏览器还是其他环境
* c8 M; h2 `, A& L3 ]7 X c" M如果是浏览器判断浏览器内核类型0 ]0 ]3 l N% L/ f
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器
. g) x0 v% c0 t/ O导出两个方法 requestAnimationFrame, cancelAnimationFrame& V1 Z7 u! n( S- V
各个浏览器前缀:let prefixes = 'webkit moz ms o';7 h- t0 |3 M" I# q1 f
判断是不是浏览器:let isServe = typeof window == 'undefined';9 A# ~# r6 M2 \8 ? A
增加各个浏览器前缀:
8 k; W: ]7 Z N0 [' Plet prefix;' M) p, o- @, `) E) _* x
let requestAnimationFrame;7 {# }9 @* P4 B, [- u/ T0 C2 J
let cancelAnimationFrame;
' P4 G# N" g1 b0 w: m! b// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
' d2 [3 }& f4 `" {* ~ for (let i = 0; i < prefixes.length; i++) {
9 r+ V! V* X9 g if (requestAnimationFrame && cancelAnimationFrame) { break }4 m5 O; s, `6 t* r5 d
prefix = prefixes7 E! L3 Q6 Q7 z
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
; P8 R7 S7 E4 L- V cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
1 U0 I' g$ {! _. u }
4 {: j/ e j, Y) z8 {: {5 x" x. g; T& V/ Q/ z
//不支持使用setTimeout方式替换:模拟60帧的效果) m% f9 Y+ U5 l
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout5 [1 @; D: U _7 H( Z; m* d
if (!requestAnimationFrame || !cancelAnimationFrame) {2 Y( j/ R& z7 a! ^4 h& `" j
requestAnimationFrame = function (callback) {
, @. T9 j) U4 \! I5 Y) w const currTime = new Date().getTime()
+ Y4 g3 ~" j6 J, b3 i$ B e // 为了使setTimteout的尽可能的接近每秒60帧的效果
7 ?- K& J6 ^1 X' w$ g. i5 y5 u const timeToCall = Math.max(0, 16 - (currTime - lastTime))# S2 C1 Y% }5 P$ O s
const id = window.setTimeout(() => {4 o# r- ]6 ?8 G2 _- k9 j- ?
callback(currTime + timeToCall)7 ^4 E# g9 i# n( f
}, timeToCall)9 U6 q# y/ v6 d# g/ p9 h
lastTime = currTime + timeToCall
' ^, O/ m" q% F9 [& T" M8 \' W& p return id
9 h4 @8 ?) ~9 b, F; D) p }# k! {9 ` ?! f4 I
- g( {2 ?$ \# m cancelAnimationFrame = function (id) {
8 ~: l9 `3 h' O. X( f5 O window.clearTimeout(id)3 x' v( Z h* P
}/ m& A% j! B; }: |5 @
}
" h" S, U5 z0 }2 V4 q0 g2 }9 N
* d+ d* Y5 ~+ T( Y" }1
( P s9 U" g& B* c: Y2 G% O* x2
9 f* w* h1 m) q8 |8 ~6 i. A: b& W37 x* G+ V; @2 Z4 n D! U
4
# D4 V( V7 X' v8 N( _- D5* N' n; h. S9 [3 D R# ^
6/ ~+ n- b6 d0 l% a
7
% N: |; f2 D8 h! _# K5 _# o3 r9 A8
- _0 X$ f4 X& W" R9
/ C# c# \ C3 L+ d! [10
% ~7 ]3 Q# F: L: b' g11
* A0 n5 p( u" J1 B9 B121 s4 o; z1 ^) O1 w
131 [9 g' d5 p, W9 l. a+ @
14) [) g' M' q. H% _. R; C- u
15
+ a! B6 J- w4 C/ t16( U! b" c$ R* O3 m
17+ W- A3 _& T% Q8 i8 j- U
182 Z. J! T& Z- c. {; Z
19# s! @* V! I, O$ h
20
4 ~* P c* C# ]" u) c9 G21
! R( B0 T5 P6 [5 [1 a3 A22
4 q) d4 p9 D3 c; g( n! t23 E5 b# ~5 ]$ T
244 J3 F2 h7 T& V f( D% {0 w; H
254 L. J, i- J2 L2 O( L7 x4 w
26
, d; C& t( T+ M4 E, Q5 I27, n! o, L- M# T6 P' Z) Z
28
" _0 t: u" K7 }; I! U29# e. V& D1 @6 I( y* g: A9 ^0 q1 P
30" c1 A+ O: z7 Z/ H
31$ n! q9 v+ g, m1 A" l& O N: X
322 U9 Y A8 }2 |. n1 f
完整代码:) K* F. j5 {. S
requestAnimationFrame.js/ R2 ?0 T& j& |; b
" ^# d' T- l: F# H' G& n6 Y; Y$ Mlet lastTime = 01 J) W s# }; v
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀: r" K: a* t- ?1 d. _
) @3 a5 a6 n! O" l1 W
let requestAnimationFrame
. z1 z* b ]9 s* u5 _+ flet cancelAnimationFrame* s0 S3 n1 B* r
3 v3 W2 F# z/ z% ~% A// 判断是否是服务器环境
; U" @ B" l5 O$ }const isServer = typeof window === 'undefined'' P. H/ E# g* s, a2 T" c1 j
if (isServer) {
3 J, P0 y& `" r( w8 u requestAnimationFrame = function () {
k* o& ]7 b7 D; s; N# P+ r, b return
: J. t: r/ F# y* E5 b, O. O }
! u Q2 X; g3 l& K) \1 L cancelAnimationFrame = function () {
2 f1 l1 y+ @& k, g2 K( T return
3 d! h7 t5 z' t! i }2 e" q q# @) i# {/ j* b% W
} else {) k" j/ T' d" Y+ j$ z
requestAnimationFrame = window.requestAnimationFrame$ Y! p. H1 y0 Y( R2 a* e
cancelAnimationFrame = window.cancelAnimationFrame
9 m- D1 z: [' y let prefix+ E0 u. [( g& B. g# f
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式5 h" w" P" ]5 C+ c6 n
for (let i = 0; i < prefixes.length; i++) {
+ {$ Z1 a& i9 n4 }- _/ m1 Y if (requestAnimationFrame && cancelAnimationFrame) { break }
( \# m, ^0 l/ Y) j) p, M3 ] prefix = prefixes
$ C; ]7 l, T6 j requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
* |& h/ T7 s7 D* d+ T5 E cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']# W- p4 h' ~3 s
}4 W! |$ B: G, X* K; v, O
; g, p0 @; {$ N& K% X6 q- z // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
8 u1 Q' [. `* N! f" x if (!requestAnimationFrame || !cancelAnimationFrame) {
6 l3 ]& x+ G# C1 X0 h. l/ o2 P6 u requestAnimationFrame = function (callback) {
/ K2 t) z2 p* A9 O. Z/ e4 ~& C const currTime = new Date().getTime()( |; d% L. s; }0 E/ X
// 为了使setTimteout的尽可能的接近每秒60帧的效果! h! l% J: {0 h
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
T1 J2 W$ N4 n( z$ Y const id = window.setTimeout(() => {
9 M, b9 T! c l1 Q" M/ k callback(currTime + timeToCall)6 M, Q" S- s8 a' Q2 {5 h5 h) {
}, timeToCall)6 B& \* s8 E4 p( |, s/ A
lastTime = currTime + timeToCall; ~* }( X- |0 Q. g6 v& e" J7 I/ E
return id
$ O6 W" |4 _4 N O( @ }# e/ v" p" o6 Y' J& G
& a4 c, s* {9 x% U, ?) Y cancelAnimationFrame = function (id) {; c [! M% X g
window.clearTimeout(id)
/ Z, d* D& J- b0 o# }& B# b }* }9 J+ }$ e8 }* w7 P6 ^
}- Q; l! S6 f2 z2 j7 e+ N' N. g- b
}. n: Z) q- I% t! E
6 C, S/ P/ C$ K* lexport { requestAnimationFrame, cancelAnimationFrame }) \" K. w7 L* k
5 q. N; M8 E/ ^! b
2 ^3 i! ^- l4 B# ~5 P1 V1
. h' @% C' Z9 ^# N6 j$ h% p) O& ^2
. l! |8 R i4 N36 ~9 e- \$ X0 P# }0 [8 f L! t
4( o+ `1 [# C; @8 Z# ]
5
5 Q" X5 T o8 L8 ?6
- ^0 @- G B" e& B2 c/ c+ y7
: |; v: l, s- i83 @' X9 l0 A% N" \# M& ]
97 y# V; q! G0 F) H1 `
10
* E' K4 s3 t5 T110 W" b. N2 s9 a* K4 n
12
5 c/ i' X4 t5 g/ h0 F. ?- C0 x13* m$ t5 L: [: y5 {
14- O) S/ E% `3 V/ G8 \
154 {* o8 q! U/ ] Z! {
16
! ?; O4 A" B2 Q& Q17
e- g( i, a2 _% D% z) o7 H187 T: z# r% U; H$ `0 D- P
19
! s9 y4 k) F9 t' m( L4 j4 c8 C20
6 ~7 a, U; E% ~' ?212 [2 T- e1 w. Y# J4 Y
22
) b( q5 S, \; a. G2 U C3 L7 Y' @: S23, n& \2 i8 _& `6 G6 C4 W! U
24
: T$ [9 y% ~8 |4 @25
: D$ H ^. N: j8 h7 t26
, h1 Y5 T$ v0 n27
0 e: l* R8 \' k28' Z% a* x% k) c6 z. y% c5 L+ R
297 K7 f- q4 J" O! d2 q
307 t# l7 v8 j, ~
31$ F7 N3 A: Z# t( g
32# b2 ]4 r' D/ b2 a" M2 A# K. s l
330 M, J8 X0 n d
34
4 N& G$ f2 K# v35
" S6 Q0 R7 H+ A u4 _1 g36
) ]: e2 n" W3 `$ X37
- N; r7 o# `$ ~1 M" Q/ u( `! h* O! l38
4 B# {2 q- Z* W- Y1 b( g39
1 W* ^2 y. p7 i. j40! k, t9 m1 o5 j
41$ K$ ^* U8 {& J( ?0 S
428 X" l, ]. x/ x) l: l2 x4 T, G) O
43
& F: T; J( y3 d( D1 ~0 [$ b0 x& L44
2 o& t) t4 c, d/ A3 B! i45
- n& q+ h4 C* H/ U46
9 L; j# C B( X6 N: r7 n476 f/ h$ G3 V0 O+ ~ W
48! f; U3 s, Y: w+ N% ~/ [5 [% J* D" g* k
CountTo.vue组件思路
$ n- D; I; H2 g8 Q8 ] J首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。/ n& @, G6 \6 E) t: {1 H7 C
) d, ?5 c/ c7 V
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
( S- M5 _, k" J: V8 ~# m' X$ @1
0 {3 Q2 t- p( G" f需要接受的参数:
( ?/ P) } r. P% Q3 K0 A
! t# B, w$ [/ _const props = defineProps({
, a+ P$ N' \" Q" G0 ?6 l0 \ E start: {
! I) c& m) c( P$ W8 h. p type: Number,
: w {- T* \. i! d2 [: g. V& G( X required: false,
G$ T. U0 X- ?) P' A* A- R default: 0
# P. w u/ }. q# [9 p: B- p* u- N },
# ~' z1 t) o# x- m; {; h end: {# j& Q; H0 B* i3 E
type: Number,7 t+ J: s; K5 d2 \' ~( l: H, H1 T4 A
required: false,
, ?/ C q( _$ T5 D! [2 Z7 g default: 0
( X7 l1 S1 _, H. y },
5 n. i" R) b6 `8 X1 A duration: {3 S( P" }0 P9 O- U" r/ ]( g
type: Number,* d4 w/ V) u# N# y1 b4 o. ~0 |8 m
required: false,! F) G$ ~# V0 {8 V3 L/ O+ z5 N
default: 5000" o$ {$ Q5 `% y- Z# p+ u
},4 J& L: s9 |) T* D% W
autoPlay: {
$ s# c$ L; i2 B2 D- }& m type: Boolean,
8 O% k- {4 j3 I0 M" S required: false,' l- l0 I3 W7 @2 W7 R" v
default: true
* m" l0 [; T8 c' a* N },
" w6 w+ h1 P/ H0 r9 f% ^ decimals: {
3 H* |$ h9 y7 r& A1 u1 [2 A type: Number,$ _% u& L* a1 G- s) Y/ o
required: false,& a0 s+ m; ]6 \4 X+ N7 t
default: 0,
! _* l7 k2 x! p4 E! }/ R validator (value) {
' X. N( g4 R# A! I; q* h3 N2 b return value >= 0) g. e [. Q# J1 ~7 z' `/ m
}
" F8 b$ Z* @3 Y3 ~2 ^ },
+ {- l8 V0 H4 q decimal: {
) A. _/ |0 e' ^1 D& u3 m+ Y, I- D% F' G type: String,) X: F/ G9 A, A' C( f
required: false,+ `0 J2 n4 O. B' X& ^! T* D
default: '.'$ f6 j2 _' k$ t) C0 v% F
},1 ^2 a- e9 \- P- T2 C7 l3 N
separator: {- D1 j; ?; \9 N( T/ z
type: String," Q9 ^+ y, N, m4 a# i8 d
required: false,2 m) S Y: W* F3 X5 Y
default: ','
- G9 L4 m4 B( C/ x },
4 S& i1 N, O2 [: q P- u/ z9 @" g prefix: {% N, U- Y; w P+ K: I* A Q
type: String,
s( P, t6 W, x5 f required: false,
& L# j5 Q7 q2 e2 v2 b default: ''
, J1 d" ^: u) X: _3 Y4 Y' o },9 f% X3 L5 J0 R5 x k4 J0 Q
suffix: {
1 }6 ~! _1 f9 I; Y) K1 ~8 ~7 s type: String,5 I- s6 ?$ S( U% j; M. C
required: false,7 p( d' o6 M1 N+ q# L* v
default: ''5 A; `' g! ^% j* P! E
},
% m. g7 z x) I7 x useEasing: {& j3 x1 n9 R/ D {
type: Boolean,
- E; F+ ^6 K7 A required: false,7 [* F# y1 k" F
default: true
* r" \* f: e& s7 y/ {2 a },: L x: L* Z9 M: P/ y4 k. ]4 p' T
easingFn: {+ x3 B) [ m0 t! s7 O$ n
type: Function,- Y, R; J) x; x; g5 P' V
default(t, b, c, d) {
+ ^0 ] V! ?; V4 r% C return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
1 _1 m* O2 z/ ^5 ?" @: L& n7 M }
: J y, `0 ]: z7 {- b }9 B0 U: m/ g/ y' M8 U/ d1 O4 ?" Q
})
( V+ n0 y; ?6 f$ J
+ m W: F& y# n2 D4 Z; ~1 M
8 E* K5 I: c% @ E% r- P1* ^) k& C; R X
2
$ j: T+ K, ]; E s1 ~6 A' `& S32 D: q% a; S# D! C! T
4+ K5 ^' {3 A0 V. P
5 ]9 r0 }% }5 s
6; h, m9 C: M3 J6 r W$ N7 c
7+ n7 B1 u" |# K, G* P% i/ X
8
_2 r. c) |! Z4 D t9
6 ]5 u& N! \; ?- ?$ m7 [8 @10 n4 b* p4 Z _4 {- {% l# n
11
+ v, ^6 m5 g. F12
+ h& ^8 Q% b9 B% \5 k13
3 v5 i1 _' p& U2 M5 J: O- O14
, f: Z5 X/ G* F0 D2 ?1 r15 O) @5 A5 G: |! H
165 O; X) l" R# a* `5 Z2 Z) p4 a- d
17% D2 z% Q5 B* p$ _7 q8 K8 D
18$ N, Y/ B d# `) T
19 G: P# b8 j3 O) U
20
( B0 t+ I1 E$ T! m: T D21
: S- z$ x8 D( A+ `0 g5 E225 b% }9 W8 t- z; B0 f$ s
23
B* y; a0 l- ]9 v242 _8 v e" c; x% i. A7 j' Y
25
: J% W. `) b x M26
+ P# ?% H' u3 y* }/ c2 ?5 }7 g27
* F: a+ @! R* Z0 W2 ~. d9 k8 j287 ?( A& c3 z+ t6 o. P9 ^2 B( |
29+ o& J2 N% `( ?
30
# `( K* o" p" r7 ^! Y$ H/ E+ R31) A$ V* a$ Z0 m6 P- ^0 n5 G g
32
* ]+ b( q! t; `4 `33" }2 U& V$ K6 g7 z1 I
34
. D+ e/ P6 Z$ |3 @ V35
' [% W L) q- X5 n0 p- ^3 m36
% I& e% c, O0 R3 Z8 K) Y1 |37
# \* y1 r9 K4 M. Z38
+ V) J2 x, E# Y6 \9 U: F- V; e39$ Z! P3 W3 J B
40
' b6 ^, Z6 p z ]& Q' f0 A, |. `41) h3 R {5 D, m
42
I0 o- I8 H0 D0 J43
& G _, a( C Z t: k44% G g+ J0 f+ m
45
4 R# p9 s! c6 ^0 I1 y4 J! v& N2 o46
1 R2 L. l) |& D/ i3 Q; t47
9 i6 I! C7 l4 a* }1 p481 K( E, ]9 F6 a# `2 ~/ W) W. J7 {8 W
49
1 K0 M. }8 {* b5 d2 v# t50& f$ v0 r1 C9 r% y5 {3 p- b v
51
5 Y0 |* W9 h1 w* d+ f9 z; A52. _* u+ ?3 E8 l1 u2 G/ |
53
1 @: |9 _; H: G, d+ B8 [/ z54
' j# v& Z2 S! A7 o/ b55
% g8 d) V& P: l7 p; `8 J56
' b5 @' ]' k+ d: D7 R' x* u* R576 i: X2 h, C6 [8 h1 l1 D
58- P! i& n1 d; @
590 {$ |! c0 X3 S2 z4 h
60
: ^, ?+ v/ | O$ M, b, F; Q3 d61; H% d1 t( y0 n/ s. I; ~
62( a* a) I) T8 s- |- \
启动数字动效
3 f% \5 A7 n* O& B7 a, \
0 w+ J4 u. F+ H6 econst startCount = () => {
1 H8 k, S% o: x state.localStart = props.start
/ @2 `. `/ y/ N* q' m' k state.startTime = null
9 U4 P: k0 K% w9 e: P4 R# n" ?& G; S8 a state.localDuration = props.duration/ m0 R. z. ]8 @8 _2 z
state.paused = false
* [5 m* @% Q( D% {5 ?+ O/ ] state.rAF = requestAnimationFrame(count)! ^/ r8 d, W: C* V
}# j6 S' a+ H8 { g# y$ ~ \' \
1$ x* T# B( v$ _
2
' Z* ~0 S% [' F3 K; D ]+ r5 u3
5 U) H: _% z2 B* P# P) W1 }4
" w0 P6 T/ ?7 @7 a$ ]# }, C+ g" n4 Z5
8 O. d! U8 {. U6# z$ Q) J4 x6 i7 a* {
7
. ?' }9 [" `( a. O核心函数,对数字进行转动
3 K, ^ w1 \2 W' D1 {" b* [. M& c5 r; h2 J
if (!state.startTime) state.startTime = timestamp
5 \3 D, b$ D0 R" Z8 j' W state.timestamp = timestamp; m9 p K+ i' g/ L& c' ~
const progress = timestamp - state.startTime! _2 A2 K" r+ \! `% S5 w# Y7 `
state.remaining = state.localDuration - progress: o! M3 c& |+ O
// 是否使用速度变化曲线$ K' \4 w) R! k. ]+ R
if (props.useEasing) {& H9 w' j R, }4 k& w# t7 F
if (stopCount.value) {* I# [" j- E; p
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
: A' X8 G3 P2 y+ O' ?& U' {7 } } else {5 X- Y0 x* C- ^! M+ n4 Z
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
2 I& e; R' X& W T2 A }* W8 Z& u- G _) G. {& N3 O5 T
} else {7 B- j& e& H$ d
if (stopCount.value) {. F; s! ?3 ^2 R: Y
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))1 i" j- B1 E& B) v
} else {8 \8 p/ q2 Y* y1 t
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
: U, X$ ?: }+ d1 C0 @# o }1 Q) d$ h) [" n1 t
}" o/ v' W- i: o8 g5 W0 B% i
if (stopCount.value) {
9 M& ]) r% t& q" Z6 `; [+ U state.printVal = state.printVal < props.end ? props.end : state.printVal+ `1 E. G# A3 ~- c! h$ I/ D
} else {
( \; g) K5 Q8 ^" s2 _2 p state.printVal = state.printVal > props.end ? props.end : state.printVal- |* {0 W* K. E* \# q
}, c& }! a& t) M& C: x- n
5 d8 h7 n4 Y9 W3 @ state.displayValue = formatNumber(state.printVal), l# ]: Y3 [6 a7 t$ D6 [
if (progress < state.localDuration) {$ Y4 ~. `& q8 [
state.rAF = requestAnimationFrame(count)- O" x/ N1 m! R. H! [/ P
} else {0 r' m) Y+ Z: B7 G3 {; C' H
emits('callback')
7 ]6 j& f% {/ C, `1 f! b }
2 |! S0 @ {* O+ w( O9 O# [}3 F% G4 ?7 A: [. G: z# \
. F) |$ I8 \8 L7 i8 Y+ B$ |4 Y2 W; T) o: K% @, o; F6 L
// 格式化数据,返回想要展示的数据格式
0 u, P( @1 }+ n% v. v- U5 xconst formatNumber = (val) => {
. h# U& Z! b5 `& ^6 r val = val.toFixed(props.default)
; h3 h$ D1 ~- s( @9 C val += ''
' H) I" k1 D5 g1 K: o. [! a0 D, w const x = val.split('.')1 ?+ g; J: ?2 i! \1 z% z2 Z! w! f$ q; D
let x1 = x[0]; r) L* a% Y X: K
const x2 = x.length > 1 ? props.decimal + x[1] : ''
. q. q7 O a; I" G, x5 j& m S const rgx = /(\d+)(\d{3})/+ m; p/ d5 ]% ^1 P
if (props.separator && !isNumber(props.separator)) { x q2 \3 M- n! J1 h4 M* k
while (rgx.test(x1)) {
" g7 M" |6 W% ]1 v4 I% n) t x1 = x1.replace(rgx, '$1' + props.separator + '$2')5 ^' a; U; \: c! y! m
}
4 [- j2 U. C, u1 Q/ A: D }
3 E. F# r- n7 S& }" I! Z return props.prefix + x1 + x2 + props.suffix+ \ q. g1 V4 y2 c' [
}# g) E" y: q% y& l+ @1 S6 r
i }/ B$ B3 U1- \1 P7 D' Z- E
2& i O/ r3 y; ~
3
. j2 }0 G0 ?% Y0 \: X) ?/ g4
9 X+ `. u3 _/ F r! i/ T2 P f# q5
. m# R! J. e& q4 G2 q- \0 K6( u% _; W9 d1 A7 h' @" L% z& u1 k
7
# }$ R; C/ Y9 p) g! Y6 f# ?$ q8
4 d/ Z0 }/ R8 _) H8 T+ Z4 n& L99 A% v: q3 {, v% I" O
10" R }( T7 n+ f8 o5 z7 U# ^) f
11
/ C7 E) _, D3 z12
" s y: y# O" v _* h13
& B8 z7 G/ H0 @14
, Q0 J( D1 U! N% X. U' z15
" a0 T3 _* {; S9 j5 x7 O+ K165 h+ @% G D9 P7 k+ B/ P
17
" o G3 A- b: I# P) t1 `$ h- m7 f18
9 r- c9 ^" b, J7 K1 P19% t2 J5 C& }9 M0 T
20
+ x% E& t' J9 W' D8 k2 ]. g' S21
5 k7 i( K P% u2 t229 A7 q2 L5 p, R* U7 ?
237 w4 c+ z) f7 u
24
4 _+ D# H0 F% }3 B+ ^25# F$ E; P3 I& r
26! I1 |6 O J z. z0 i
27/ l* y, r/ Y4 v# G/ Z* r
28
9 H6 v: q- x# H7 x29% k7 X7 b5 p9 A( H
30: D/ ~7 _( y/ Y
31
+ J! B+ [8 J, |$ o* b324 M9 C$ p( U$ l$ v- E3 W
33
0 `8 P+ T2 f' G) x( E0 ^* g346 Y. s* ~5 s3 \* J3 K' l
35
/ k; K0 ~# z; L- } j" ?6 Y2 n! p360 P5 ]7 n' U. U5 D3 J
37
( w* ]# N% Z _) h; ?387 D9 j' r1 {3 k% I
39
" u! D) u# w) y- R40. D% H) s+ e8 t, T4 w$ U9 v
41
) ?- h$ ]" b3 S* [9 H$ O% y) z42
+ {8 l4 U9 j; H6 I" _! `. H1 L# ?2 v* ]8 Q434 l0 s& I! i# u) ^; P8 ? o
44# A+ {6 C5 _4 D; U, u+ B
45
: b2 b6 U3 ]! m, K% b46
4 z. B! H! G, u47" |/ ]- ]3 m3 ]* p F
48- {3 E$ t( o$ A) w
取消动效
( N7 ^( ~7 u9 Z& [% Q) D0 a3 b' \( U, B- p- ~) J- h$ S
// 组件销毁时取消动画
( l7 Y4 Q* a2 N% konUnmounted(() => {! P( w, [2 [7 T3 V: `- N
cancelAnimationFrame(state.rAF)2 [) I5 i V) c
})
0 n h( a. t0 {. z* B# j; a- D1
: j) d' n5 b1 r2
# n+ }* N5 A9 b' J% q5 r3
. u: A# X) T# X6 A% u43 C1 l2 i) V, |& a, E, g4 I
完整代码
" ]: }2 x9 P: d, H2 W
8 R# E X$ {+ R' \<template>
, F7 y" J& H) s# p, V {{ state.displayValue }}
- Y8 {! n( p) d1 O</template>
" Y% o9 s" a. p, t' V; K M; `. x4 T# J/ S6 f6 s7 C
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效' o! y6 t2 C9 E3 d3 s; _5 A
import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
8 F0 g/ Y4 R j* v g" F. qimport { watch, computed } from 'vue';, M6 p8 |9 b# r3 | n) q; @0 q( f
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
' m0 l$ [; z$ I$ T% K& [// 定义父组件传递的参数
; L5 n# T+ P4 p; b$ ^0 econst props = defineProps({
% H& A; Z! a( p5 Z, o7 \& C start: {( D4 R7 y) Q; O/ C
type: Number,# l+ H( |' L- ^3 z. v( D6 O( X
required: false,
- u' a* G- p6 I8 Z& X& P5 n default: 0( \4 F5 ]: x& y1 g
},: N4 q' F1 I2 z; J
end: {0 O9 ^) P1 j4 A( H# n
type: Number,, M3 |; O) X- i: M2 N$ {
required: false,
1 z: V- y0 n8 |& A" m, S: t default: 0/ L- m) f, E% @" s/ s2 Z! a! h0 |
},
* x+ m A; B+ ~6 ~! E9 r7 o duration: {
& _' X+ e# S9 ~8 h+ N& l7 Z type: Number,2 v' ^5 ?. o0 [8 k. M
required: false,
, T! v, m4 T9 J/ e3 Z1 Y default: 5000" F' N2 B2 K: u- _- y
},# q1 b& h1 N3 k& c, G5 b1 o
autoPlay: {
Q# s" u' o! k9 b4 S. j type: Boolean,
2 u9 ]# k+ m# |( v' s required: false,4 Q# G Q& _4 K
default: true, ?2 P1 J# ]; a1 h) A' F
},+ q. B: q# e. x7 i/ \
decimals: {5 v" B3 s7 c3 M) X& V- V4 H! d# I
type: Number,( J: k! Z; Z) ^) {/ e) e1 ?) X7 G* V
required: false,0 G X- n, ?: _
default: 0,, E4 s. Y% P, B' o
validator (value) {
7 [7 L1 a+ u4 H1 r- Y% s' L4 Q( E. Z return value >= 05 j0 f$ W/ a1 v" _0 _
}5 _5 Q4 i3 A( ]- {; M/ P
},
) I( N, S! L. ] decimal: {: P1 Q K) x: g. `% J& G
type: String,
1 d& [: }# u' m+ a1 t required: false,5 t. F' m& Z' [5 i) Q
default: '.'
; m* n: m" N% g" N( N. W },
& Y# F* G" ?: f$ {: ]" `9 l separator: {
; d% h* o5 w' t# E type: String,2 C$ O& [7 z# }9 d/ }% o- q) u# h7 e
required: false,0 w5 k5 U5 p) O
default: ',', K! \, f. D& F4 C1 i7 S
},
, U& d! {4 _ u prefix: {
\/ e3 D; w" @7 K+ T type: String,
, a/ E1 T) w9 f1 u% g0 { required: false,6 L1 |/ U$ P1 G( J5 f5 s) c
default: '', E! R6 r: d9 M6 o: Z. z
},! f# A8 u5 j: f' g! z
suffix: {9 T6 J" X8 o& D) T
type: String,
4 e2 Q+ n% s& E/ @' B+ w required: false,5 S2 s& u% B1 c* I( P
default: ''
) B8 V6 d, b6 x! ~7 p },
# V6 Y# p& _7 O$ L+ ~ useEasing: {% n+ m& l; m9 O. v. k
type: Boolean,+ {4 |& ^* g# y* M& u
required: false,
! S/ {- E% q3 I- P, ^4 S6 m default: true
6 y6 U- f5 X/ u0 a },
1 k; Z( z6 l5 t easingFn: {
6 ]7 a. Q$ `2 S( n type: Function,/ ^* a: i- b9 W' `
default(t, b, c, d) {% v/ d2 q4 H; j( L- J$ _ Z8 e
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;& P c1 O, t+ r% |. A8 u
}
}0 j s& @9 R* m }* E! a/ f+ v2 }. N5 c& b6 ^7 }
})9 p* ^8 C3 }" ~/ M# `$ q! E. ]2 g
# `2 `4 g4 m* K
const isNumber = (val) => {0 ~$ H" e \+ I1 e9 r
return !isNaN(parseFloat(val))# K: [: @- p9 h
}
. |7 J- C1 `( Z3 m5 k& [2 f l6 o$ y5 |5 o
// 格式化数据,返回想要展示的数据格式7 ?! g M" V; Y4 p) d* g
const formatNumber = (val) => {
, Q6 Y- C$ K- x. S- p" m- M val = val.toFixed(props.default)$ j/ T' }( u( Y/ O( p( ^( F/ R$ R
val += '' t% z- J2 S! R) h/ Y- x
const x = val.split('.')9 O- O4 c- k6 I q4 O3 D: d
let x1 = x[0]
2 q( _$ o2 Q& a0 ^ const x2 = x.length > 1 ? props.decimal + x[1] : ''
9 V2 U4 v6 n' N2 k( Z1 ~* J7 Z const rgx = /(\d+)(\d{3})/) _2 H7 E* b& a7 j1 d
if (props.separator && !isNumber(props.separator)) {
8 [) Z- F6 s! \( ^4 u while (rgx.test(x1)) {
h, T: c5 _/ l e1 E. K6 J! [3 s' M4 M x1 = x1.replace(rgx, '$1' + props.separator + '$2')
5 T! H7 { Z6 j& T# r# B. I }
: W& h. j+ V! F }) o: [, O, J" \+ \7 N( Q2 \
return props.prefix + x1 + x2 + props.suffix
) b( i7 i! a" g0 j, s8 l}+ A1 D" ` }% }1 D
- J# F: _( z' y% v4 A, U// 相当于vue2中的data中所定义的变量部分
" L+ \% U9 V9 H& \! v) R! kconst state = reactive({/ M" X( U& K' I
localStart: props.start,! {& x0 j0 ^: t; f/ b7 ?* E1 G
displayValue: formatNumber(props.start),
, a4 G7 d. A' R% g% y! D- R printVal: null,
2 E) T. _" k( X h' p1 O% L paused: false,
?5 p% x* N% Z3 h4 R localDuration: props.duration,/ }% F4 M+ o8 f
startTime: null,6 ` Y& L, q* k
timestamp: null,) P* Z1 V3 X# F4 d2 i
remaining: null,7 @- ]0 _+ F5 X' U
rAF: null
$ R4 S: Q6 i9 G8 p* ?})2 H4 q- Z4 s1 v
; K3 Y# X w: _// 定义一个计算属性,当开始数字大于结束数字时返回true! [2 r) r+ a& d3 ~$ e% }
const stopCount = computed(() => {: L: K ]; l7 A& i( F% T
return props.start > props.end% }; S8 T' Z2 j; S- d
})* D& {- I& v) C' f. v' T4 E
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件8 I8 z. q6 O8 z, o$ X
const emits = defineEmits(['onMountedcallback', 'callback'])3 W2 S5 K q, J% o) Y9 d! f# _9 v
) ^+ W* m! B) |# r, T
const startCount = () => {
- V$ G* ^3 X: ? I n state.localStart = props.start( a3 U; @& l* y' Z4 d) p' z
state.startTime = null' f1 q; P1 T; C- `8 I9 t- A
state.localDuration = props.duration
# T5 a2 N! _( C5 a; |2 p F state.paused = false. V, V: p$ z$ n/ L
state.rAF = requestAnimationFrame(count)
$ s: d# h, p1 Y; r* b) y2 e6 L}1 `: P; Q& v2 x0 ]0 `
. I3 R, G( _0 X8 i2 pwatch(() => props.start, () => {2 j; z1 D* K$ Y0 c& t% k
if (props.autoPlay) {
: W9 w( A/ [3 l3 i3 N startCount(). ` L/ F6 Y) R( j
}
8 Q4 ^! O' Z& W, |})) P! \2 F4 k7 d3 E6 @: S' ?/ R: x$ M$ E- r
2 B/ x( z1 F) w
watch(() => props.end, () => {
M# `- T$ p# u6 M% Y! L! x$ a% n if (props.autoPlay) {
5 T/ s; a. g* g( P& w. R startCount()
' x# w+ Z* a( Y' F2 K6 K/ o }' E/ @; C% b* b6 R! v' v
})
* t1 D' b7 p# I) ~4 E7 e// dom挂在完成后执行一些操作
6 S# L) r) W/ I8 l, U9 @onMounted(() => {- d1 Y' J0 K' u: k
if (props.autoPlay) {( J, s! X0 C% @& S- _& S# W
startCount()
7 ^3 `' r9 b6 f% v- @ }
' X+ ^3 ^$ H" w. g0 d% s emits('onMountedcallback')! \2 @8 Q: `- u% m) ]
})
; G/ F' w4 d! x/ d( Z4 ~// 暂停计数
2 x' O! @4 V8 d* @7 } cconst pause = () => {
4 E8 y. C8 B: i" S5 r/ V9 H cancelAnimationFrame(state.rAF)
: e% _$ [$ o0 F7 T9 F}2 I; {8 r, c; N l& j: f
// 恢复计数3 J" o1 z6 {. K% q* T8 S! ^+ E0 x
const resume = () => {+ e6 j% e7 s% ?2 G* p$ ?5 P6 {
state.startTime = null. M' @$ ~2 M3 p( {/ I1 U7 N
state.localDuration = +state.remaining
" u2 V. G, `! I# } state.localStart = +state.printVal3 d/ p. a8 w1 E' Z2 q2 k$ n) b
requestAnimationFrame(count)
9 p! k2 x9 b1 ^% p. l( z7 C}
' U; ~2 o: K" e t# f
9 P0 M6 \! e" x( aconst pauseResume = () => {
9 ] |; L" [3 M* H: Q if (state.paused) {
4 O2 m2 E9 E) \! ?9 j$ O resume()6 O6 Y! S {! d- ^' W' K
state.paused = false1 C* ^8 n1 r: i7 l1 V" a1 D$ K
} else {9 {$ W; K* E* n# G7 l# O0 e1 Y7 u
pause()
3 e4 `) N* O* B* M9 E* h1 e, U state.paused = true" d9 e1 }7 B2 d- D
}
! |# }: M' P+ F9 o( ^7 J}
% T* V, k, f- H# i* `
8 {4 l3 z5 ?8 W7 b2 K, v% {, ?const reset = () => {* k! W4 K' G8 p5 i
state.startTime = null; R8 z7 @% _5 P0 |: o0 |
cancelAnimationFrame(state.rAF)
' G3 S ]6 Y: X state.displayValue = formatNumber(props.start)2 y5 q6 d3 s2 H+ ]
}
; Y9 D6 V5 R5 S7 u+ E) W J3 c: o" q4 U
const count = (timestamp) => {
: M. {" K6 \% i; `7 I1 ~ if (!state.startTime) state.startTime = timestamp a, P- b! y" L( W, B( w
state.timestamp = timestamp; d2 }- e# g. ~9 x3 Y) i0 x
const progress = timestamp - state.startTime. R" U; r" ~' ]9 F/ m$ V
state.remaining = state.localDuration - progress
7 C6 V" p& c# ^' l7 H // 是否使用速度变化曲线) R* J; H! P0 u" [2 K
if (props.useEasing) {3 x9 _6 t0 W0 u9 F
if (stopCount.value) {! p4 r( C/ ?( g. h0 P6 v8 V. ^8 n
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
" f7 _: J" w& d, G7 x& z+ t3 ? } else {* h0 x& k% A; j, L' [
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
& `' A) b* C/ t" @/ O }
, U6 {' B- F1 q" j } else {' M7 `/ Y" g# w4 u+ [2 V
if (stopCount.value) {
9 r* z4 ]7 c( z; r& Y0 b state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
`- d0 r. o7 R } else {
" h$ S0 @, c; C7 ?; F w state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
5 Q% N/ J7 r* W3 \# \* x! w }, K8 E1 ] z, b6 Y1 K, y
}
# M/ g) |6 W" i) |* W: W( a if (stopCount.value) {) E1 @8 N/ ~% i
state.printVal = state.printVal < props.end ? props.end : state.printVal, v7 d* {$ S# K/ X) t+ Z: U
} else {$ u( f' U+ J1 I
state.printVal = state.printVal > props.end ? props.end : state.printVal
3 j% x0 p9 z+ {+ |) ~) S }3 h( J9 r- U$ x. W; Y- ~' c
) e, E0 W7 d( w2 W1 A$ D; Y
state.displayValue = formatNumber(state.printVal)
; d l6 t8 L* q1 n8 @0 } t7 m. P- K if (progress < state.localDuration) {
7 W6 K5 g% l* [ state.rAF = requestAnimationFrame(count)6 d! m4 n k; D
} else {7 j; T1 F9 Y2 B. f3 n A, m
emits('callback')4 e# S0 M% N# j3 d/ Z5 D
}& s s5 i! t. P5 V
}- j2 t; Q- W% _, S* j* W% j
// 组件销毁时取消动画7 v/ o" i3 x( w& `
onUnmounted(() => {/ N1 D0 T$ \1 w F- u( R$ [& s
cancelAnimationFrame(state.rAF)
}3 @, [* V$ F9 D}). a: j: O- @" {* _
</script>6 z: j- i+ k/ O
/ f) y/ K4 J- u
1
. E7 R3 D. `- Y* B$ |+ y2+ s2 D5 g+ l4 @7 K
3* @, W: f8 a; Z# m7 w
4: I$ ]" e# y1 H8 Q, V
5% w/ q2 S+ S. S. N3 Q% w
65 n& O* m4 [: E
7# n0 T' @! x( A! W6 f) ]
8
1 K; E& @- H7 y, L5 Y+ D9
" `0 B4 ?" s! x& y7 C h10
/ I1 E4 D5 T1 v' \11
: x$ l k+ \2 r) M& C) O, E12$ l: F( {9 i5 B H
13! b H9 I6 I: e( o i
14/ |. H, V4 ?8 Y7 r- @# a
15: g9 O9 \: J2 {7 T1 b* g3 ^
16
9 B8 n4 Q. R, S8 ]17, A( z' ^% [4 |9 e
18& U0 x8 a6 O6 I: T# a6 G9 B
19
# s @: D# {- k3 M5 X6 Y20
; E% f. \- J/ H G6 v, z# |- Y21; R, a1 ?8 n; `2 F( P
22
- m& y* v. k8 I3 E& `" I233 \ Y! h& t/ w8 P2 t) M( z
24
+ j* Y1 B, o' _& p8 }) _254 M L r P4 M7 n
26; f: ^. `' n2 b/ H) l
27 ~; x& L9 Z7 E& f0 y& s3 }
28
8 ?: l7 x' V; [) V2 Z2 t29; w9 v3 V; C/ J: h+ d; D9 B
30
. N, G+ d/ {( |, w31" e- h6 Q" `5 D2 E+ j! h4 i" N. i
32: ]. a: a2 m8 q1 H; ~5 |6 Y# l( \
33/ S8 y E( x* G1 |" u3 ^4 ]
347 S2 H0 |& z) p l' B+ r: U& ?
35
! k8 z% n, b. ?36' H6 v1 x# ^5 Y. b `) q
37. i' m2 E. P) k5 P% U. x) P/ G. k7 W; L
38( J: ?( r' O* M. Q9 k- K
39; l0 m* ~. R5 \4 O
40
# x& e$ O+ J+ W8 E41
( t+ M0 ~. m" s y, c, S3 l42: m& e: ?. S. B) @; O! h* C* Q
43
6 k. w+ p7 s1 L3 Q4 [447 J7 d7 E% t: X2 A3 Z9 ?1 M
450 @, c1 x9 i* g n2 P7 u! p
46
% |8 W; G5 ?2 z6 O47
- q0 K+ r$ t+ W) P48
. j2 X9 l7 y) H, y" K& g5 n49; D6 o, `$ k) V, B( K3 j$ x1 E5 l
505 r6 f! n" z, L; n' X
51
( X% J' }, O" a1 {' B% G2 S/ {52/ k7 N& C1 Z. m) r ~/ k1 Z
53
. ~0 h' d4 Z7 w, f# ? d5 W8 w1 U54
% l" Y$ t" S8 i6 g% P4 {552 m1 q: H4 `7 O7 J4 x5 K
56, @7 r8 Y$ c- ~0 } s* k P
57
/ b; C. H) p9 C58
* A! r+ m9 E" O S; |1 p59# L; E: n+ ~0 H' l/ l; J, c% G; Z' ]0 p
60
9 |7 p2 A% d$ C61, Z; l( Y! M3 S& E
626 u6 N! c2 J6 e) _8 Z
63( Z; b T. q1 K* S8 `6 ]
649 U3 r M2 r6 {* J2 ~3 |( {) [
658 l- v P# k4 f( P
66
; Q6 R8 }* S0 n9 A) _! r. `67
8 I- P" A6 M- B# n' N685 k6 u6 {* P4 y
698 H6 {; |$ `0 P F# H
70
( D/ @$ S# n8 u3 e, m1 E' u' l9 m71. W0 Z' ^, o a' `
72
1 H& g i: J: L7 c, _' U: ]! m- R73
4 J- j7 D w& F/ p) u4 p74* A, s* g- M; G0 R1 G3 X
75/ P; Z. y7 O) @: s. o
763 `5 h# G* q2 {# x& p- l f" h
77* O; r, F# g: h' t
782 f R6 \% G0 U, f( x5 |, H
79, V- C I# L$ I9 {
804 f$ E) V& G! h) g: ]+ F! e4 b
817 W0 _( o" O9 ~% _, [7 e* s
82
6 ~3 ?* ~2 n0 t' S" Y/ m83
5 |$ D! }+ F4 {" b1 c! ^! T* J) K84
8 _( j1 }5 {3 k0 q: a, e! w85
2 H9 j3 {1 i( K5 a867 Z; `+ Q6 l/ S; V* t
877 ?4 Q |+ V! y0 C
88/ U# N6 |; z5 H# j
89' ?8 [( X; D# u H7 E ? c
90
- w) U* A0 [1 u& c' f91
3 t8 u( \% p6 V" @92
; }2 {. k1 Q& |( I1 T93
) p6 @7 ^$ x' R- t* }- O8 G+ a* u945 m1 B' L- K: M7 O0 J z7 u
95% ]/ I" [! j1 c/ ^! d! }: o
96
. ?2 T' V) y6 Z; z97
; S" N% K" v2 D& ^+ [% G98# H$ l2 r7 T) y3 _" J$ g
99
& B3 i# k7 F' o2 x100
v$ `1 ]4 H2 r2 d% D8 T% K1017 K+ q' ]9 M( n! w, j$ }' `
1028 R& ?/ `" j1 d% @4 e7 l
1033 @7 `' s* i6 m5 i4 C- i
104
: A% j3 _( ^% @( J1 w# g( s; g105
v9 w o8 e/ k4 r6 D y1 L106% t# A) }% F# i1 x$ a: s6 F
107
0 `# c8 K; O2 I! I2 w7 M" }$ Y108
2 t) E$ h, j8 X3 m109
3 c+ v2 r4 @0 c1 C! ~$ e+ T+ D+ }1106 s" ^# N0 Q6 R- N
111
9 I5 l4 O1 }; K112) k, C# ^1 v, z% W8 ?: c
113
' F( u) n J0 ?, e114
% A* P/ {! Z7 | N5 r. w1 h* U115* I% S1 A4 S" ?! [) {, B. r1 z
1160 I5 B& P( g# v3 H5 U! v0 \9 j
117; {. u" {& p3 o
118
% q& E) w( y B6 k0 W$ N) F$ A: E119
# T8 } X* V% M8 @( y0 d+ \2 R) [+ T120
3 U8 q! {. c0 N }' @1 ~121) N" x2 A8 h6 O0 _9 y" n$ g
122
- i* r3 Y2 g6 b3 M. X( T: W5 J123. q1 m; o5 x. L+ G4 Q( N! A( G, b
124: N4 S( I/ c0 R- G6 p: h! d
125
, W0 r6 H7 K9 i/ \7 Z% i126
+ e+ G% Z/ G8 i+ a& y# @127, q0 f' \4 a0 L3 _* P
128
7 x' }6 b& c/ p s2 Z* t" e( V129
& |: y+ X) P, {2 H* X' s130; g; ~7 L! h/ g) H
131, H5 r$ ~* H! N5 D( C( v! Q
132
4 k5 W; B, t! I133
# ~& l9 L$ I t+ i134# p( D, R1 J3 d8 g
135
/ r, D' J3 x3 M' p, g136$ w, _; E9 }5 `) p! M
137
6 k0 V: ]( f6 n, q C. X138. N4 I! w: c. K- \ i
1391 q& a: Q0 Y4 Y+ R1 b4 h
1405 x- p1 I8 h% X
141
W' ?$ @- X2 [2 C( e1429 o. n' E) U: g/ G) h
143( U* {; n: @& `. D& ^' t
144
3 i8 N- L2 B% o2 f/ C: T1451 S3 ^! } f5 z6 V4 Z) c
1462 {$ f6 b h% V8 I1 b# C( ~
147
" {- y% R6 m; ^( t3 Q148
2 R( A; @( [# B* E149
; U1 x1 [* E2 k0 k$ L& D# ^150) O O2 m; n2 F. D u, e. L9 B1 l
151/ m* r& i. F) l3 c* Z+ A# ~
152; C2 B+ [5 d& ~# s5 l
153
/ t# k% B, M* w; U g154' s( Z) M) R$ E# T+ I8 J& L
155/ W j: c, m- }! z0 C5 `$ a
156- ^4 S8 G' W- V( f
1571 v' P) C$ M% y; g) R4 j
158
6 v+ y+ _$ Y8 t+ N, k1596 s2 O! H+ o% C) e
160
V% \3 @2 V, T: @5 f% C161
% O5 ~- r* o& v162/ F$ N* n) y" @9 D7 s& G
163
+ C6 q% o2 v0 b0 k2 U; a164
" _4 e& z0 G! Q0 U8 J/ A' w. @* Q165* K, h! `6 R1 Z) F7 y |1 Y, d! A
1662 e4 I; t# V) y1 _: V
167
+ p# p! Z7 C. u: p* |+ d# t168+ E3 p1 Z; `* F' s* W1 h2 R
169; k& {3 r4 u) c2 |5 z5 K
170
+ w8 o6 _+ Z% ]. \/ ]' i6 K. P/ L171! c; {3 ]1 H& E
172( z/ L+ m. a! f& m" O
1730 ~: a2 E' q+ O7 R' n" l, v# T
174% \8 }9 {. g2 u h
175, G: m' S- y8 T5 A
176
+ X- m1 b$ O- I5 v' x) k) m& s) v; d177
$ \1 u h+ F% F ^: ?178* ]: S" m: i( c6 W: a, H% V" `
179# T+ {2 ]1 F" G' P$ H5 Y: v
180
4 b8 a" o' N, {! {1812 |; h3 z8 I1 g! X
1824 _# ~" Y5 m( g7 E+ z
183, N$ B# u+ o7 @5 ^' f4 T( F
184
; z; e/ \. F/ o) X' B$ q' Q8 a0 L185
8 k" U+ R) v* ]1 ?5 w, d: j. r, \2 ~186
! a, w, h3 y5 q5 V+ G& b8 e1873 M7 `: z! H! z7 B. R( p
1883 z e$ I; ]) a: L( A
189
9 o# x3 c8 J v5 n190
. s8 ]5 n. Z; k1 M191
; D" u$ C. l2 Z4 v! M1 n- l192
* M# X3 ]: Z j' |& N, F- Y193
7 i( w. W4 j, l A194
5 s! S7 M+ A0 _ W( |( B1959 ]8 l; F1 s( ]/ y& M: E$ N
196
! Q. P' M7 F8 q; s% w$ I1 T9 I x197
7 {; z# W7 u7 a+ f. v- ~8 U; S198
B( n5 `& [+ N) F1 f- }199
6 |/ i9 a+ T3 [5 N/ _1 S7 x200! [/ J9 o9 |) v# n
201+ c) \/ N8 ~) t, `3 u# M. ~% z: W* J
202
) I& Z, h6 O& L. j9 M$ [9 Z; P4 @7 D" A总结
% { Z! s0 u' S. Q0 {自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️, \. K8 h) n% |
4 W9 ~1 a( u2 K6 c& X
demo演示) q1 w* B. O, G7 s2 m
后续的线上demo演示会放在
" |8 a& i. f9 \- }# D$ ydemo演示
- _, P0 @+ |: H; f+ { W! b完整代码会放在
3 V) T- \# {& \/ ^- V4 ?个人主页; o- T; F# ]4 C D4 N% p J) |9 J
, {1 G( Q1 [+ w3 Z1 h
希望对vue开发者有所帮助~
+ T6 c8 K/ |; f! D) v, R8 y2 S( B; J* L8 I: N1 r8 a
个人简介:承吾
6 m. v) Z1 b" d工作年限:5年前端
, N% z' J" ?+ N* C' R! _+ n# u% E地区:上海. ^# D* Q* I( P$ A( c
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!2 e J4 z$ H8 F% p3 |
# `0 Y0 y: H3 A4 i9 l; G- [- @
' T0 ^, K! K( {( ?; d( R0 o8 b9 T/ u, r S2 _8 g; B( E
4 y3 b# S9 J5 d }
————————————————5 ?$ c+ C/ M! f5 B* h! j( b7 _
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。3 y) T0 Z) D# ^1 X4 [
原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847& P7 o1 b5 g x9 B4 u; P4 j
# m) f$ |: K+ m+ g
0 L$ z" m# _/ u8 _. Z( A5 Y6 h+ Z |
zan
|