- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566251 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175098
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
* c; q0 t4 u$ ~( x1 Y0 v% S. Y h! Y p- v
前言
n: y3 A, {8 a4 a8 ?& ^1 _$ X0 wvue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:% \# l `3 T U# F
TypeError: Cannot read properties of undefined (reading '_c')
- A/ R e) J: h4 v的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:4 k* L! R E6 l4 g
& `) I! g' C3 ?
1 V! d5 \% B2 ^: C+ q( F' ^
思路- s3 X9 M% C. {9 R: a H8 H
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
% H: ^. p- F; o- O0 ~
# F, |3 i/ ~9 O0 }8 l3 Y4 s9 ]2 y文件目录" W% R2 L3 ]3 y+ V! T0 i
3 M4 k& W/ U* G: }: N6 T4 f0 h
4 N# \6 Q# b0 G2 g( `3 |6 |使用示例5 R: _5 M: q* b
<CountTo. j+ k2 ^. a/ _3 ~$ S# S2 @. f
:start="0" // 从数字多少开始
# v) x$ i5 d2 j+ ^2 d :end="endCount" // 到数字多少结束
' N8 n4 K7 r" W( s% d5 }! e- m6 R W :autoPlay="true" // 自动播放0 k! X, P/ G9 }# k) W) g: n, S+ l
:duration="3000" // 过渡时间
( F2 e; i, d s# _, S prefix="¥" // 前缀符号, \1 D. B4 m0 }; E8 H, A* s
suffix="rmb" // 后缀符号
4 R$ C' y0 d$ K2 y, H; z$ f& \* w />+ ~( E$ ]/ M7 X; `6 h
1
0 \ r" C0 w9 K1 U! H, v2$ v+ h3 B. C0 q- l* N- B. S( L4 F! f
3
$ h# ~. x, U9 T9 u+ U Z% X0 z! W46 ?( R0 k0 P9 {# ~* s" z& v
5
! H8 L) l; j7 [4 w+ E1 |! c67 d! Q" E4 D& \9 v, {6 w# v! x
70 Q/ H6 J' d2 Q- t# W
86 b4 ^% H$ |# c
入口文件index.js0 v3 t: X: B i* b* D: K0 U
( _0 K" ^% {3 c. Xconst UILib = {
+ G* W1 Q( ~* P" D* A install(Vue) {
0 o6 _; M! N; E1 ?& g Vue.component('CountTo', CountTo), n2 N. E4 Q8 x
}( N) a# H/ }# t5 f+ n+ L
}' X7 C9 r5 v2 M) F9 {1 _, @. s# V
& N! e3 }, j& ]export default UILib7 o0 E0 _! S: l7 X: a: |' i5 }1 Y
" d; a. _' N: [) _$ A
1
5 r4 F1 a& I- ]; h2
' G3 B4 W$ q3 v4 Q3
5 G# x& Y* r; C4/ X; C' b5 ~: T! C
5. z$ v0 A. _; Y! F) P0 e
6
0 {0 g7 A2 E+ Q& V4 E: q7
& }6 d* z8 t- G) w [) {8
" x! L5 n |% L+ Z. L4 F9- M0 T1 w% n t: B
main.js使用
, a& X* f7 |5 F* K; ?3 {: ximport CountTo from './components/count-to/index';! \1 y `8 X" @) i0 t4 e) `. m
app.use(CountTo)
; X* G: W# Y9 G9 f. c1/ } m5 m- S) p1 q; y
2
- ~9 N* `3 O) P6 y, S' x1 UrequestAnimationFrame.js思路8 A8 R% [8 Z& Y, T3 `+ M2 W+ X
先判断是不是浏览器还是其他环境
& i9 V$ d9 q$ v. }, A如果是浏览器判断浏览器内核类型8 y$ Q5 I# B* @$ e" v
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器 ] H9 ~( \" E3 r
导出两个方法 requestAnimationFrame, cancelAnimationFrame
. s% [8 \) O9 [2 @% ~, f; P1 c各个浏览器前缀:let prefixes = 'webkit moz ms o';
! }! w. ]8 Z3 r$ y& s: m判断是不是浏览器:let isServe = typeof window == 'undefined';4 x+ o# @9 Q$ H- u7 t
增加各个浏览器前缀: 5 l; c3 S2 [( F; H8 U; H: }
let prefix;% a$ V0 |9 |% u. H4 u6 q
let requestAnimationFrame;
4 q/ [' U2 a. R) D- F+ a4 Ulet cancelAnimationFrame;
' ~7 c+ n. m$ Y: o" \// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
}: b# ?/ n5 { for (let i = 0; i < prefixes.length; i++) {
9 V4 r1 y: {7 t8 ^4 o if (requestAnimationFrame && cancelAnimationFrame) { break }
7 l+ p) S8 W, P9 d1 p# {6 E prefix = prefixes
0 p" _9 T) y- E4 D requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']* O7 b* w6 j3 k- ^
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
$ H$ C4 g, S5 _3 L7 g }; A. m" s& n2 }/ k) U! Y8 Y
* j, B7 y$ c8 a
//不支持使用setTimeout方式替换:模拟60帧的效果
( d& J6 b0 t: L1 B, O% P // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
4 l- F o5 r) r" q- X" j; E4 A: y# @ if (!requestAnimationFrame || !cancelAnimationFrame) {3 V/ c# N( B$ w; \
requestAnimationFrame = function (callback) {
+ l" Q, T+ f# b) _) }* ] const currTime = new Date().getTime()5 H0 k: c" U5 i, _/ Y; \0 o% V
// 为了使setTimteout的尽可能的接近每秒60帧的效果! L" D {! s X6 O" Y$ G
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
% q& q3 D! d- k% x* r# m const id = window.setTimeout(() => {
2 K$ m% j$ u1 S2 f# X0 p callback(currTime + timeToCall)6 D7 e& W V) T: g
}, timeToCall)8 ?, m! w) U- h9 [
lastTime = currTime + timeToCall
+ Y! t) { V3 q return id$ H! N" G0 H2 k; E W
}6 _# x3 `% J8 @9 x! C" h3 \' n
3 N0 ]9 H! s: a5 g+ |
cancelAnimationFrame = function (id) {
/ w: }/ M2 {3 { @8 [9 I9 U7 f window.clearTimeout(id)
" E+ I$ e4 y1 M }( f. [8 O1 C# A% U ~4 E
}9 R( v3 N# d) g! Q. {
0 j- ?2 {0 E( n. R1 n9 H
1% E6 l* a5 Q2 o( f( S
2) V K3 Q1 u7 z( }. I; g- M
3
8 X0 @1 A1 e3 h2 f- a47 T) ^/ L% G0 S
5
& K# C7 u: R0 Y, Z6
( a) |$ K4 y- ?7 j8 n7 y D# K7
* s. Z$ Z3 p7 Z8
6 r1 u, w0 t, v7 R3 q8 ~96 S2 n3 t {" P: P
109 S0 q1 r+ z- N
11( M5 _8 ]3 w3 G# p0 D
12
; F. K" I6 z/ U4 _7 t2 f13
' U1 n/ @, c' ]' _9 d14
4 f9 |+ D# S8 N6 y2 {0 t15
: w) c8 g" e& v2 M+ L16, A3 a3 U7 G. f
17" t& R& T# W. U$ B
188 Y3 M! h& p; y
191 y0 B+ e! n2 }
20
. l4 J5 E! @. o w21# k8 c, \8 v( j7 i7 Y0 A2 I
22
# ?7 Q9 d- O4 A7 ?$ u |23
8 I- b' I0 G6 {0 r2 q- o7 H/ R% I: O24* d. @7 D2 E& C7 P- k
25
. V: D! R1 t& Z" t26
7 R: f! Y5 x5 ~276 \ X/ |0 U6 e3 f8 x3 P4 Z
28
% F: P% }: ]& T% D5 _1 ~$ W297 E8 V) n2 o9 l$ B5 ^6 Q/ C1 i1 k3 |
30
5 F7 T+ d/ `- y% G5 Q31" g( _. j5 p4 y; k* s
32
) C6 [) e! P. {. ^7 m完整代码:
5 e: G+ _5 c" |( z9 X {! lrequestAnimationFrame.js
0 _1 s7 ^8 k- r1 P# K( U7 D/ C
" e) m v: m# D& ]! ?+ {" Qlet lastTime = 0* a5 G) _4 ~) Q% ~2 C
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀/ x# U- d# l4 e- c4 f( s
2 a4 i5 Q6 E$ k, l: U5 K; l, z) ulet requestAnimationFrame
" o( L( C4 \" r( n( y( L5 slet cancelAnimationFrame
7 E( d2 q8 t, v, H& S+ M; W- C$ H
// 判断是否是服务器环境
; w& a3 A" x: R& ]! Econst isServer = typeof window === 'undefined'
" P3 X, Y7 M7 ~! Vif (isServer) {- O( C% _& X3 q, O
requestAnimationFrame = function () {
0 ?- ]! c; G2 R+ j: z- ^6 S+ u return
* t5 b0 l3 X- L; m& d }
2 a y) G9 P' Q l5 P+ I7 A cancelAnimationFrame = function () {4 K3 | t3 I0 F. H
return
# D4 J5 {% O5 Z! j: k } E2 r0 ]/ ?' [5 t0 A
} else {. N& t" w! [* n! N1 ~+ J
requestAnimationFrame = window.requestAnimationFrame
/ `1 a, g6 S" G) p( t) ] cancelAnimationFrame = window.cancelAnimationFrame* s9 V- y! Y7 Y5 T9 }
let prefix
, p/ i$ E% ?; C1 S' o // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
% n4 w' Q8 Q; G1 R, D for (let i = 0; i < prefixes.length; i++) {
/ D8 J) o) }. {- e- T3 B" g if (requestAnimationFrame && cancelAnimationFrame) { break }
* @2 Q8 g' q' q7 [$ Y& ] prefix = prefixes
9 p! u& ^3 X2 q" t: g requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']$ ` z2 h- \8 C
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']7 r) C2 \0 m8 c: V4 S- `
}
! R" k0 A- I! H1 i j. n5 g
1 J0 X R n7 S( a) A // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
9 e7 G6 y. ~0 }) W5 S" Z if (!requestAnimationFrame || !cancelAnimationFrame) {
" A- x7 q* a" }" u! n+ v requestAnimationFrame = function (callback) {
& j8 b7 T0 H, J' R- A9 k' C" U } const currTime = new Date().getTime()
0 x1 v; W3 _; E7 j // 为了使setTimteout的尽可能的接近每秒60帧的效果- W l3 C6 ?) v3 `9 `- h
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
7 w3 N8 P. C3 h const id = window.setTimeout(() => {5 r& g" P. T. s% c% E: @
callback(currTime + timeToCall)+ z' w! y8 ]5 @- S6 {
}, timeToCall)
* t% ]! ^/ s0 \" E: z lastTime = currTime + timeToCall
$ ?# x1 W, Y" v, u; o3 n return id. p( e" ~/ g2 j3 W$ Y
}( x7 V! I! d" A7 M2 A
1 p! l0 j' _" B4 M4 _7 l0 U cancelAnimationFrame = function (id) {
& N) Y$ Y0 \5 u0 W W( ` window.clearTimeout(id)
" m) l5 _- L; }, w8 ? }
. @7 E U4 \% a0 v" N }% S; _7 l0 t. f6 ^, o6 E
}
* ~# S8 R: K0 }( k, w0 p/ M7 M( j# U w2 C! x- _
export { requestAnimationFrame, cancelAnimationFrame }
& \ W# e+ O1 J9 p, H" | z- W C% Y4 L# n0 B4 l- Q' w
" Y, h Z% }. N2 ^1
) k" d5 F- n) y0 X7 }( q26 @/ v0 i9 o3 Y! z8 q
3
+ G2 J% g0 H! I( K! w42 d# @6 a$ U6 [7 x2 l
5
& K/ s1 n! ]( L. k" T0 T* w9 _6
. w, r" f; b. |$ ~74 l9 y+ R* W! N& r% e, L% y
8
+ [4 ~3 y7 l' G4 `9/ y9 `/ s, o- G+ `; F3 W$ z
10% t5 |- d1 v: E n
11
6 {8 {* x* y+ F12% @9 @0 b$ ^. Z# `6 Y3 J" d
13
6 Y& e: n: H+ W/ R' T- b8 b145 k- u* _+ j* F3 r+ K8 q, D, h
15
) k2 ~# y( A' E/ i" ]; S& P16
8 T& k3 C1 C: g2 V17
& ^# u' y8 _; T- P# J18, T3 H: R7 n% ]
19
3 A; s, Q! v5 a: ]3 y200 G* H9 P: r! [, X4 W
212 a9 ?0 P# u, \, s* h7 R. {' C
22$ n) U# @) A. T0 ~# X/ z
23/ d$ U# N" j( ]- W* ~7 V7 M
247 s; r& E, U2 D
25$ g2 f" v: j- B$ u' Y9 U: a, O
26
& J, Y/ c; b2 C# \( N' r0 v* y; K27
4 `% |3 ~2 L9 i p0 [0 T9 S28$ n+ s' j$ H5 M5 d$ A+ q, k
29' K- m# d8 {. ^6 i- O
30
. j* R" [! j% H" F31" o- S2 g" e* w- r# z+ f! u3 T
32
% j* [! _; F7 Q6 G8 ~! X339 z( n" N* L$ ]8 a5 u& [$ f5 h
343 l; u5 ^3 J5 L2 I- Q# z
355 _ g- t/ o2 D( K% m- `! ^
36
: s! J* Z+ U# }6 v3 m3 P37
1 F5 A8 D1 L% i0 {, D* `2 v38
+ V' L2 ]1 q! f$ o/ l" b39
y& X$ @* Q, N. p4 r40
5 ~8 C3 J; b& L41
& H6 U3 Z8 ^1 `% b42
5 N: L* e2 K+ O' ^9 T43 R% l; K3 k$ ^4 k, B
44
) Q7 r N: O P9 M8 w45 V K, D# f$ }: u. d3 S& q5 g
46
5 ~) m) k, P2 z+ I475 ^4 p* X. W1 F# z1 W& ^# L
48
. R8 n$ L9 E% n# x. q4 [: SCountTo.vue组件思路' p5 m. T2 X6 Z' k# R
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。' h3 @% [! T8 q6 h+ W1 K
5 T+ M3 \6 t+ X& N引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
4 F9 Z9 f- v/ E" u1 t( H1
4 m( ]% R' W# w: a/ I Z6 Q需要接受的参数:
$ H- R' f7 ^5 G% | B* P: Y3 V' ]/ a% O/ J7 ~
const props = defineProps({8 t, X) b9 U" \
start: {
8 f0 ]- N' d$ X3 m( b type: Number,
' A& K* d- W4 O/ F8 J required: false,9 X, _# A3 Q @
default: 0' O. L ]# B5 X# g( I6 `. P
},# A+ s7 p- e ^) m; X
end: {
; v1 \8 l/ Y8 Q type: Number,3 p+ A' ?$ j& D; D( @$ P+ D
required: false,5 p& y* V. d/ l6 `3 W- k8 l
default: 0
/ A+ D+ o( p; M' M, P4 T },% K2 H4 v7 d# m6 G; b8 ~, k' @6 ]( s
duration: {5 K: o7 P; c/ l, z
type: Number,
. {2 W% u1 r( q required: false,
: X+ x1 T ?5 D* Q, x. l! O default: 5000
6 y7 X: x1 x. l },
1 B2 O, c6 m) r: c; ] autoPlay: {. t1 v6 S- I, d3 d9 [1 a
type: Boolean,
1 S2 A1 Y! z0 c$ F. M required: false,
6 q; p9 U# I- i! H1 O default: true
' f5 n+ _4 y2 i },; ?# T8 S1 w, a; _
decimals: {, t+ c% z9 H4 Y( \! l. a6 D
type: Number,. f2 G; u& f* N/ ^% v
required: false,
; _) B2 Y6 l" L" Q# |4 E) w default: 0,. t) H1 S+ n8 w. V
validator (value) {0 Y: J/ m6 `" s% k- a
return value >= 0* G( j# k+ y. r+ L( [6 J
}
" Y7 T' T* _" ^ },6 c( C3 D( q8 s1 m, w) f: K- f0 H
decimal: {
" M: |+ f; v2 z9 r8 ?8 P9 [6 U, }+ Q H type: String,
+ z$ A0 ` c' z& @/ T7 _. D, y& t | required: false,* e T& r" c( v
default: '.'+ x( Z& p7 @7 H) a) E
},3 q7 ?1 k6 W9 n7 {1 C
separator: {
7 s( i$ U/ K' ? type: String,
( r4 E2 K$ W/ h# i8 k% b required: false,
& N" q( Q+ `5 [/ X& n4 I& f default: ','$ Z- }7 M' W% {- q$ w8 K6 u
}, x0 s5 e" W, q( X/ G/ q/ X" n
prefix: {
% z" g, u6 ]. j6 Q" h type: String,
" a: m- L; G1 b5 j3 F required: false,
1 G2 k1 g6 f' ?4 I default: ''/ s3 _1 N6 n) n
},9 Z5 ]4 B) c, h% q! @
suffix: {6 s3 l+ ]1 {- [7 A! @6 U) N
type: String,
( P" X8 I4 U. C required: false,
" a+ D& x4 w8 L default: ''
0 _2 p: D4 T$ `: ? },
- N$ ~3 I: E$ I8 F- I useEasing: {
- w6 e6 u# N+ I; k2 c/ } type: Boolean,5 Q) h. h; p6 q) Q' n6 p* [7 e
required: false,
! k. {( ~: Q1 s+ s$ u default: true
/ J- O3 ~- q% e1 j, c) A },
% I" k4 j2 L9 y8 g easingFn: {
5 Q' M2 A% j/ d/ o type: Function,# v, Z+ f( M- _9 f" L5 s0 x" @
default(t, b, c, d) {3 T T& |- u& b% m8 e* G+ u' Y( \
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
2 U3 f G* r3 K. [/ ]% u( I }5 j/ ^) \; k9 g/ r) G$ M) x' i
}
( j% i1 J% t% _ O( c8 J* w})
/ W! s, f# ?/ [% w
0 G) b9 i7 `- X2 Z0 ~
+ }: o3 T2 H/ g1) O. C i' q x" S/ k6 o9 Q
2$ u, K2 Y& b% c! d5 D' H& _
3
/ b& D! J! B1 k8 r8 O4
0 C: `) K+ @; s2 T5
6 K) r* M7 c0 C+ B( r5 [: V/ I6" L4 i; v& K6 H
7
4 L0 O! ~1 s1 Y8
% T- C- e- q9 \( P. O9
, z9 s9 ~. m b1 s10( \1 w* k( t) d4 [, z
11; W4 H% N' E1 _0 P" Z, a: H, h) c5 j3 a
12
6 i4 p* l- v$ F' O1 Y13
8 F G$ B/ T& I! p14
3 S) e+ J! v- |) R/ X: d( c' z* i9 Q151 \2 x) r4 N% D0 f# P
16
& f0 ^! I" j# B/ e1 p2 i3 d: f2 v17 u" z0 P! k, h7 s7 m+ g
18 o9 q+ N8 Y5 g1 \
19
' ^) O( y8 }. {+ b20" {- a, d3 a- {
21* B+ ^1 F1 ^8 W3 L( o. y
22
5 h; N7 s5 D' B t: T23
9 W6 k1 I& k- |. t/ c" L1 q24
/ O0 Q& b( H3 C6 z! F! K/ S: K250 t3 I- H# r7 M
26
7 v, R) F5 T4 |" z8 j; R: z27
V0 g- f" B3 ~) @28
+ [' h, B' H. U( z29
4 x( m+ R6 J* C3 j30. G W' ^+ Z& Z) W$ S4 F
31, R: F% r8 D R
328 v3 O+ T7 u4 z) B! Z
33$ P, L! r; `# Z& X
344 X1 Q1 y* f! W" C
35; K6 {; I0 X, d2 I9 W; c
36* I2 A0 Y4 b" p* x' A# ~2 R! q
375 N) C' h" W0 k
38
& ]& E2 a! ]* P6 S' x$ Q0 A2 i- ]39* f7 }# ]2 x) o/ b( }/ R1 W* b
40
# d6 ]: [2 ?- v& `, m6 d p1 D9 U& H41
9 d6 k j( m4 l* Z6 ?42
% ?) t: H6 P. S! W9 j* d1 r43' F8 ^0 H$ [, Q( ]4 A2 O; v! v
44
z$ s: ~; S5 c6 x45
6 {! n! t4 X8 B( t' o( }; ?467 A& Y: O) w# ~* p4 B- K& Z
47
+ C' L7 G% @) y48
4 M9 ~# L" H/ r8 \, r7 l49
! |$ c# B8 R2 T h- K$ C50
# I% ?' D8 P% v# s5 v51
3 B. H- h5 H2 g; n526 o( Y- `" }$ n
53
) O: F ]6 ^! T k/ |54
2 d' g5 c: E$ p, [55
8 s3 ]7 h0 n. W6 s56- ^, W5 x7 ~; K% D2 e: P# \
57: S. L: K p \4 @; U( o9 I
58
; U; U! k5 ]' C% Z O1 v2 w59$ O6 u; E) z& K8 q" y" n2 M
60+ y! I1 p0 |4 ]# t! y" \# U
61
6 B5 J& Y+ Q/ R7 E5 O# c8 ?62# o9 B( W) d( ^/ _! M
启动数字动效. I1 d1 Q* Y; r% S) D$ _ C
3 E5 @9 E! G; P4 N, q
const startCount = () => {
1 u- {3 g9 Q3 R5 y- x! ^. a state.localStart = props.start/ T0 [8 h8 t* q2 v, v
state.startTime = null. P& [1 w8 c2 Z
state.localDuration = props.duration
0 Y* N( h+ a0 \9 q0 o7 i7 o state.paused = false
) i2 ?; a; V( ~' N3 f2 j5 h state.rAF = requestAnimationFrame(count)
" O" b1 ]! m) h) E/ Y9 d" X} l1 @+ i$ z4 U: `0 L& M" a3 a
1: M- l2 |& n" i# K" |
2- p% o) W3 f0 A6 ^# w! [3 D
3) Y7 m. c# t% v3 x
4& A& J) m& t4 e& S9 v
5
% l8 L8 f0 |) {. k6
) z$ O6 X9 J0 f2 L3 N9 }) O7
0 O z' b1 n+ I1 `1 x% N核心函数,对数字进行转动5 S4 Z! ~- o0 ]5 E3 h, k; u! ^
5 I" O3 w, \6 V if (!state.startTime) state.startTime = timestamp2 g5 C5 a& t) E& c+ P( S6 l
state.timestamp = timestamp9 ?1 q9 O. N$ E' E
const progress = timestamp - state.startTime
0 ^, G/ S- O0 T1 U3 ^ state.remaining = state.localDuration - progress6 l; g6 B! V, U& X
// 是否使用速度变化曲线
) h. ^; q7 V# t7 e) v if (props.useEasing) {5 F/ H- @( E% a. @! T
if (stopCount.value) {4 z) T" K' k2 e( R
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
* p: m2 b" c- _# _& r" o/ v } else {5 L: b) O" t5 x# M
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
! a8 @5 W& n% l; V( C# a% a }
1 x; B$ h5 n: a E: n5 V/ T } else {
% J) x" w& R7 f: T# C t' B' q7 c if (stopCount.value) {
9 R2 R5 } K- B5 D4 A* V state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))9 v2 `' O0 j) i
} else {" M/ L) G2 Z9 [7 L7 Z+ H* Z) N
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)4 F- Y/ I. E- C; `
}2 E L+ E1 h) y8 \
}; Z+ x% P6 I) A* ?( w* [
if (stopCount.value) {2 S, |/ b1 x: \0 R, c) j
state.printVal = state.printVal < props.end ? props.end : state.printVal a9 [) k) V3 Q
} else {% h3 }/ j/ N! z# t. }7 d
state.printVal = state.printVal > props.end ? props.end : state.printVal3 q6 Y. ~* W( f! b& w& T& n
}7 m( w5 g, O7 s/ m, d" N
( R8 D3 ` c$ j6 B state.displayValue = formatNumber(state.printVal)
2 c# G" I X" z0 H3 v if (progress < state.localDuration) {
9 M# y9 B; M3 j; L! o state.rAF = requestAnimationFrame(count)0 A- H9 H: U6 h# ?2 X& e
} else {0 J& L1 @9 i7 m
emits('callback')
* D" y' e9 h' ~% t& | }% C+ P2 }" @3 p8 w
}/ R8 C5 F g5 X8 @7 t
9 V, x/ Q0 ^3 Z; u; h1 ]
% Z3 n* f2 B' d# s! j+ G
// 格式化数据,返回想要展示的数据格式3 o4 ^* B9 B* ?
const formatNumber = (val) => {* ^6 f H5 ?3 a( k1 C& v! I
val = val.toFixed(props.default)
+ A8 Y# ]& X$ }/ r9 V9 N5 a val += ''; `( d) b F. j7 L, B; m
const x = val.split('.') ]) ?; e) o( u. k) O. J
let x1 = x[0]/ ?, E, P @4 Z* J" o
const x2 = x.length > 1 ? props.decimal + x[1] : ''& P l+ T. {+ _' y* `. M3 R1 E
const rgx = /(\d+)(\d{3})/3 r/ [& E. C5 L3 A& }( c
if (props.separator && !isNumber(props.separator)) {3 o& v$ M0 {+ ?0 D. e) X
while (rgx.test(x1)) {
9 D& R9 e0 I/ i0 S x1 = x1.replace(rgx, '$1' + props.separator + '$2')
$ K2 I2 D0 x; [+ z1 Z8 K }
( q# s0 m& h; Q6 Z3 } }
* R5 B4 N- F" h p return props.prefix + x1 + x2 + props.suffix) Q0 b% s# F' R- w2 L( r
}
% ~: d% l1 ^4 F% V+ s
7 Q, V( _; ^' {+ p2 N6 R, f1
5 ~; U& h' o* w2
, Y4 S) S5 [* a" g/ l7 V3
: O, s) M# w% B& k! C4
2 V2 n( Q8 r2 p7 y2 m" P: C, C5
' O/ g; E' m$ y3 O$ _6
& P% B6 }0 [& T! [7( w5 ~- I' u* o# a9 K% h) h% c0 \
8. P, ]% i2 G, C: i
9( f4 ]2 U, T' k4 S, w
10
- v* ` ^0 i0 [# j0 c' ^11
~8 a! Z. s3 p% x }& I& O12
! {4 ^ q% z6 }0 x' T- I6 A; t9 U13/ i' d$ J: N5 T
14
! W; U( r! x- i0 \3 O. t4 b. P15
7 ^2 j+ M% `! V/ _; d16' J; k3 U2 M5 h2 X+ c, X# m! i
172 ?$ d/ ]& S G L: W; G: D/ X
18$ k2 e" I d# Q/ y. e( q
19
" ?* e o* E% B7 e/ \/ H6 d8 K( {. L207 U( `" Q# i E9 M$ K
21
6 S/ y/ \, y6 l& ~7 i4 z22. n! Q7 h3 o4 [% S4 @7 E$ G
23$ h" z8 _# c0 \8 M/ w& b7 T
244 u) ?0 L; ^+ Z! ]4 F
25
9 X5 W/ N0 V2 d+ J* P# |) ?$ M, r5 b261 h U0 }. O2 |8 L) w [
272 Q3 G, H0 D7 o8 y6 B5 N5 X9 W1 X8 |
28
/ E6 ?: W: t1 n4 Z% J: s29
: ]9 s: l! U) B0 n, U' ?30) ]/ t$ r. |( K: \8 [8 p. Q
31
# V, d* F; u2 X3 S32
3 C- ]& m, s, t0 G33# _: g) S6 C0 a" m& d6 M) j
34
# a/ R3 j s1 o! {6 @. A! y( n" X$ C35 ^7 U% B* ?7 P* a( }4 {6 m
360 \: S/ S6 i+ g9 A1 |
37& o% Q& d) l* N& e* F( D9 S
38& g, m3 T& q; G `. Z9 `# s- M' L
39
* Z# W6 j: ~) l- q6 q/ K40# L0 Q) m2 w, s: v7 }. b
41' b$ K, z( f6 a% k1 K3 Y$ T" r
42
& L+ p& p( t F ^43
$ r" ^1 k2 a5 h' ^0 t44$ }/ d- j! X1 O2 l" _" Z, D3 V
45
9 a& Z# O# m5 T7 G( N46
) i1 I# j i+ h4 r3 D475 ~/ T- @+ a" C; q6 G
48, ]0 q; ?- I4 t2 R* [
取消动效
% X% S' s. w: M9 ?7 [3 U& i$ G2 r2 Z* n2 J
// 组件销毁时取消动画
0 A9 }: ?, S( X1 q: K n5 W; ?+ ponUnmounted(() => {
: u- t( w0 U; G, w# w0 w cancelAnimationFrame(state.rAF)
5 I7 O/ J: z9 a: ~3 l6 r4 Q) h})% H# k1 \, b* R/ w4 ?
1
& h" s1 ~& p- n- Y) G! ^2 l2: k3 d E5 z9 y4 b1 u
34 n. b3 h0 y. I+ o& [
4- Z- v8 h% l' g, U* p9 Y
完整代码
5 f: {: w$ z h- K% d1 @1 {& D# W& L) d6 e: k
<template>& T: x, R: z) ~5 y
{{ state.displayValue }}
$ [' G( i7 F& V</template>
/ f& d, _1 c4 [2 c8 }# d$ J w: Z Z; j& L! s1 \: v1 I H# a( I# u# x9 R
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
* O# B: m0 |+ a$ M( I; `6 X3 }import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
" j$ X9 z1 |- Z/ n2 h9 aimport { watch, computed } from 'vue';% E4 R4 H2 h& K1 H% ^9 t
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'8 Q# J6 X; W" _0 J
// 定义父组件传递的参数
: K, v4 v4 j7 H8 b! m Iconst props = defineProps({
2 Y* G' ]8 _, _! H. Y) i start: {
# w- h% O) S! `6 a* C6 f! n type: Number,
! U8 t: `$ n8 _ l0 E8 t* { required: false,) p0 j9 S3 |3 @$ ?
default: 0
1 T5 I: l+ U, q },
6 J! e, @& v$ J6 d. ] end: {7 ~/ @: L6 |' O- k/ N B
type: Number,
7 A, A6 x+ K1 x( V required: false,
3 e3 e( N/ s5 ]0 W default: 0
: j2 Y' `) d( I4 R' u3 T( x },$ ~# C d: y( p; U
duration: {
, Y8 v4 s9 j3 ^ type: Number,
! [& D2 f) \! p/ S! e required: false,
) f2 ]7 w# y# b$ K default: 50002 x3 c7 i, x1 M
},
$ ?0 ^$ N O1 H, }' |" T autoPlay: {( T6 ?) k, e& |, l8 ^3 V4 ~/ D
type: Boolean,1 s1 n B* P* R! i, }5 ~
required: false,
3 g6 H% s) ~( c* h1 V' I default: true
+ n- V6 r4 l* I3 S* B9 C* ~: k1 E3 \ },
4 q) \) a8 E9 n& P* D7 ^ decimals: {
# W& H' d* i1 h! t# y% A type: Number,
( A* ]/ s- f0 [1 f3 G6 d required: false,* o% G6 O, F1 _& E! S
default: 0,7 [- G% b6 _. T1 ^
validator (value) {6 m) e3 ~0 |0 ^2 z) N
return value >= 01 ^% N$ _7 P5 s j& m7 Q
}4 s* |' A( t) [4 g7 u6 T+ t: T
},% w1 r! H. [+ `+ Y5 p
decimal: {
- }$ {1 v* c1 {: S2 W type: String,
* {, y# O8 p$ Y( u required: false,
* E- U0 m) e2 U8 L! n+ P default: '.'. H: u7 u4 ?: H/ z$ ?* X: Y# h
},7 [. V8 z% h9 V5 \5 Z9 [
separator: {2 V. B* Z; H7 |8 O
type: String,
4 B6 G: |2 u# v- i+ {5 T3 w" m6 @" ?" |" q required: false,( l6 Y( k# \7 Y" ]$ e# l9 g
default: ','
# Y5 e) e. r+ Y; n) Q },
# _1 O; |/ u+ q) X prefix: {
) \6 G6 u0 D! N( {8 G6 J type: String,
8 M7 R Z& S( c$ X) ~ required: false,
3 q7 u) Y7 w2 f9 o default: ''
5 B8 o3 U' W( r8 D" f },
; D9 ^. p5 h3 N, M- ^ suffix: {
! R% c3 _+ g$ P4 t u+ W' \ type: String,
% a; k _) Y3 Y0 S required: false, ^, a4 b* K3 O! [) N1 h
default: ''
: b% l3 X e5 c },! ?( ^$ a# P$ o
useEasing: {
( ?+ j0 a8 U7 L$ H) m type: Boolean,
4 {4 u9 r2 I, a8 B9 J. T7 F required: false,& z3 `, k8 j2 V8 L: Z$ n: v! Q
default: true% B& l* T$ q* f* ^+ b
},% t% g x. {: `( I% m$ ^
easingFn: {
) t3 {6 Z' y* A! h( e' w9 G type: Function,
f0 N% c* y' u8 |$ f* ~+ ?+ E6 v default(t, b, c, d) {( d" t X& u, L/ x) |5 G
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;" C6 b3 [& b; `* m$ J' h
}! v# j6 Z, b$ p7 j: P
}
3 B5 r# O$ B4 G# n: ^/ b6 O8 e})& R% W! X9 c$ ~! J9 @
) H$ B# D! N; A9 m0 sconst isNumber = (val) => {. u3 d: `: Q+ R3 m7 `1 e% ]6 b
return !isNaN(parseFloat(val))
% ^; ?! K7 \& o/ K6 U# O}
& z; i& i' X* _* P' P0 t7 i3 t: `% ^: N1 U* @
// 格式化数据,返回想要展示的数据格式
% Z3 N6 d& C6 x- b9 oconst formatNumber = (val) => {( Y; T1 Q% y; ~
val = val.toFixed(props.default)
6 F' H5 G- j( N+ u" D/ h val += ''" t# o @6 c# W: U7 R
const x = val.split('.')
6 C( {+ S) M& g+ d let x1 = x[0]
8 p3 I; l$ H8 z8 a# Z2 v const x2 = x.length > 1 ? props.decimal + x[1] : ''
8 p* {3 w$ \0 V: l! J const rgx = /(\d+)(\d{3})/
: n2 ` e2 i: z+ Y if (props.separator && !isNumber(props.separator)) {
3 L' N+ I% z: Z while (rgx.test(x1)) {# G- y, h. t8 i4 c( A2 ~+ x$ h; ?5 I
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
" ~. p3 m/ e. U& R8 h/ ` }
! j) \& Q5 P8 Z; P) u: ` }5 F# l+ o/ X4 @, e. S, H
return props.prefix + x1 + x2 + props.suffix, p: F% Q1 Z. |3 N4 @3 s! Q4 V
}
; V: r8 x8 U0 Q
8 O+ M/ p# v* T& V# I4 t3 M3 n9 Q// 相当于vue2中的data中所定义的变量部分* y8 O/ D& k# f: l
const state = reactive({0 R6 }8 F) H0 k+ D# R2 B3 K
localStart: props.start,4 |( E1 j& J' G1 ?% e
displayValue: formatNumber(props.start),
7 `9 f! ]0 T5 m! n& {' x7 M& t printVal: null,3 {, S' K) g! @
paused: false,
% t: {. h" `# [! Z# a localDuration: props.duration,3 A3 _, d9 H" p9 X: @# ]- |! [
startTime: null,
% [* f3 R, n( b& M* r3 I% B timestamp: null,
0 s$ @- S, q4 x9 _) P: Y0 l remaining: null,
% a1 u: M2 Z% F: T+ s$ x rAF: null+ e" F0 K! k( j9 N5 q
}) N; \& i* \2 v5 X6 i# F* m: D
6 L% d" K# ?) n
// 定义一个计算属性,当开始数字大于结束数字时返回true M2 e5 C# b2 n7 Y* Y6 j# T+ D
const stopCount = computed(() => {' l1 r" r/ ]3 g6 {: N8 \
return props.start > props.end
' T Q! s- H! P: a4 L, m6 o}) q' t$ v8 \7 u X: B2 y
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
- p) G1 K! U+ s: e: F5 T: z$ j5 zconst emits = defineEmits(['onMountedcallback', 'callback'])
' V5 d. O7 v8 S; e9 w1 |+ R1 ^) W/ A3 c8 s3 I- b. H$ L
const startCount = () => {
) P0 K v1 D$ s9 u" n7 _. X state.localStart = props.start
+ ^: s) h4 o, } state.startTime = null
; m( W s3 {5 M1 ^! c9 G0 W state.localDuration = props.duration X# X! u' ?7 P8 ~
state.paused = false
4 V( U6 L! J( x: v( t3 H state.rAF = requestAnimationFrame(count) C1 t& Z1 {; o# n9 a, b0 @
}
8 N9 t8 G$ u# Z6 h6 `2 A0 W& r" K$ H( X. B: @( A
watch(() => props.start, () => {
9 g% `. i* T. q' K" q \$ s$ J if (props.autoPlay) {
% Q2 p+ f0 W. F# e startCount()
' R8 A! z7 @8 R7 D, i H0 |% c }2 _- M8 P# |2 m5 C3 i, k6 D
})
1 o0 x# s* ?) n' a
; K6 L. s* i7 ]' A( f! Qwatch(() => props.end, () => {1 \! V" B. T. o; w9 a; m/ ?
if (props.autoPlay) {& m% }- n7 E* M: k- h2 c: i- T
startCount()- [5 `- ?/ x( u) ]( g1 F1 i' q
}
7 y8 s3 [/ F" |})1 _2 \+ _. K. ]3 {
// dom挂在完成后执行一些操作9 H! G7 F7 B" c" [2 x" _
onMounted(() => {- _* ]! i$ |, z; I, Z
if (props.autoPlay) {
- H3 J A+ V5 [& a# S! O. t startCount()
: B* [4 p+ n7 u( }) @; M }! X7 x6 F) V3 g
emits('onMountedcallback')
: U5 T% |' w9 v9 U% m7 b. L})
8 u' N, d- p6 X2 E( y3 e2 R// 暂停计数
% o+ b% k# |# z8 W0 Aconst pause = () => {; F$ }" E+ W! J. \. c+ T( f' T
cancelAnimationFrame(state.rAF)
+ z2 d {# q; C3 p}
: S- x8 h4 z2 P- u// 恢复计数
2 Z4 f1 J* ^& uconst resume = () => {
4 L. U G6 ]4 J4 {! V3 m& n state.startTime = null
2 f: K* {! `1 S7 Z: D5 X state.localDuration = +state.remaining6 g# _; o1 k5 ]- Z( p+ Y4 M* F4 S
state.localStart = +state.printVal* A) z* r/ O. w( s1 ]
requestAnimationFrame(count)
1 C: [% f4 j: w5 n}
3 O7 `* e" Z& n7 W+ T. _7 O; T8 d0 s5 I# D
const pauseResume = () => {: n& s: @6 m! z, H6 o1 v1 B3 ^
if (state.paused) {
; `' K9 \& {6 g resume()$ H" {' v+ ~* ]% ^; I
state.paused = false$ l- T2 u3 x6 J! Y9 G. a
} else {
3 U' j3 V' R( w5 Q) y6 J pause()7 t7 l9 D: l8 O% |( ?/ Q0 c; h( r
state.paused = true
% ^5 N$ i: s/ C$ \& \ }
* V' l' C: G6 l2 f- ~7 l" y: g}
& q- J- O4 d6 }! c) z7 m3 R; U, [2 W( T; A$ Z# B
const reset = () => {
3 g. S9 a7 k L! ^+ G state.startTime = null) E$ }( e5 X! P0 S+ ]/ X: ~4 ^& l1 K
cancelAnimationFrame(state.rAF)9 \8 _' q) R: q" @
state.displayValue = formatNumber(props.start)
( @) A9 F' L& V}
; M- j/ i& ]% h6 t9 B3 y2 _$ s( O5 M% ?2 E
const count = (timestamp) => {& L& t$ B2 A& u# S) k
if (!state.startTime) state.startTime = timestamp
3 Z8 F- E- }( |' D( _% Y state.timestamp = timestamp% N- U& V6 f6 U& z4 j0 H
const progress = timestamp - state.startTime% U F7 z" F" z4 `, s7 C! _
state.remaining = state.localDuration - progress
4 B' u+ ^; e" i& Y) ?$ t. A9 P1 N1 ? // 是否使用速度变化曲线
1 R6 }9 H& D8 n% H% p if (props.useEasing) {. M- _9 ]+ [2 v3 J" c
if (stopCount.value) {
, D1 D) l; o9 m7 ?4 y state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
T3 U% Z9 o' x7 K: k% f y7 j6 Q } else {
6 ^' E. q5 R4 P- J- F state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
( G1 m9 @) G6 N# X }
: G) P0 n: W! Q& @ } else {
3 E5 Q0 }/ R. n" q$ X if (stopCount.value) { n' k' g) \* b) v- o8 b. x
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
0 ]2 e' f5 p9 }6 j! w } else {/ C! f1 E5 w$ L
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
5 k, k9 x1 q5 F6 L }
1 U) Q3 H0 k+ P5 V9 u }
* z$ W( |$ ^. \ if (stopCount.value) {
" T; R) d+ c# s1 E* L state.printVal = state.printVal < props.end ? props.end : state.printVal
, ]! U( p+ N( o } else {! B" Q: D' c5 h: W; b& B. J
state.printVal = state.printVal > props.end ? props.end : state.printVal
, \- C4 ]) \. f; O- o4 { }
9 Z9 Q, Y0 W" \% |7 U0 S0 j
2 n1 C5 |3 ~5 G7 T0 R; J7 G8 E( ? state.displayValue = formatNumber(state.printVal)0 R* {3 u2 P4 \$ Y
if (progress < state.localDuration) {
' R( t# p3 `; Y- _$ Z state.rAF = requestAnimationFrame(count)
6 h9 y) G6 q- i7 R; a9 a } else {
2 E$ E. V% P ~0 ~ emits('callback')' [; p2 H* e# D3 w) E! t; |+ X
}8 z' M3 ?( y0 a. I
}
3 m$ b% f! `% q* m6 t* s6 v- \: g// 组件销毁时取消动画8 a0 v% [6 ~* V0 _
onUnmounted(() => {3 Y6 z6 {, d, V$ y
cancelAnimationFrame(state.rAF)
- b5 f7 I0 F* n) k5 D})
* j# }% U! ?) p: T</script>- c7 O) p! K& N6 C+ u
# u3 t2 X8 R0 Y. B! v$ `0 y
1& C ^, O7 C8 Q8 Z& s4 E
2! j5 s" V$ B( \5 J4 r
3$ v, ~3 v9 t! T+ m% h3 w
4
+ {2 w9 o* O: I% ]$ ]3 Z% m8 v3 Y58 v9 M" {3 b0 q4 t7 j- t- q
66 g" X' I; y3 \+ c
7
6 P, s6 R% I- y1 c8
2 |& P7 q$ a1 ?# P9 y96 A" v! R+ L2 p3 d
10
# y( _" w% J5 a& z, b11
0 w' z6 N/ i9 }( S# t7 g8 S12
0 @) ]' [1 w5 l B6 Y+ f! K13
1 e& v3 o& G1 @% \# H5 W' D0 h! |14
1 k4 l" R5 T2 y3 ~2 f150 v6 w0 M* t$ i- `
16, ~( J* u, {2 Z5 Q9 t
171 x: H9 d: W! {$ C( T3 K
18
, ^% y3 z& I3 m8 B9 b9 W, a19% Q, Y9 U4 Q) [3 ~* n# p1 R
200 e; t3 C/ h } E# u
212 c7 e4 \, ~5 |
22/ s. D5 @! |' {* D8 v$ A" g
23% m' C2 i& l4 d9 Z3 |& E& J
24' q1 u3 h7 _8 |) B. u# v& a
25
1 |3 H5 E( T$ [" ]2 Z3 G5 \26
: M8 f0 g4 G) E& M: t- f/ W$ [27
' s0 ~5 L* U5 x+ A8 t28
7 b2 t% Y" k$ B3 f8 |9 H29: l+ g( o; n# o% k6 ]
30- }) ~7 d. s: g
31$ A" n( ^) g/ `, \4 ]
32) M9 d- y: G* F
33& o6 w$ H( x. Y. c+ a4 O0 h
34* h" F- F8 s, z& M% O7 K+ @
35
5 L5 W% R9 w( y9 P0 |" a% L$ z2 k36
/ ]- e. x# a. r8 T, D$ ?37
. K7 q3 `2 E) d& _38
0 G7 _+ P" n# q& o& G, c; w% K/ j39/ T4 M+ ^4 i. {& ~7 S7 t( s) D! c
40
4 Y/ s- V7 U) a0 F- \' f41
3 \. u, l! F) M9 T6 w6 p& g+ b42
6 I$ r3 P: y. p9 s. Z43
3 V7 j7 _- p( i6 ?0 E44# _, q B& }, l
45, v' b! b# e3 }" c: I: q8 u# C Y, U
46$ t/ ?, d |( M( z, Y7 X1 i/ E
47
7 q# u$ O* \3 A; w48* R+ I/ J5 c: O' P1 Z, q
49
$ ?& I7 T( p$ c/ x: k& P50
8 |9 }$ \% A3 w3 N51! b9 ]* i8 P8 u: M' i/ _2 d+ R
526 [2 Y- }. |9 b- q
53) B6 P; [' u# b1 l" [1 P
54& m6 h! s$ _+ j. d- c
55. t( R- s, k# I8 i6 d' n
56" H# V j; [! n4 d% Y4 L2 }
579 O% ]% E1 L2 u7 n5 G
58
: E4 |( n5 t& B59
/ P* K8 J4 `! n1 X/ ^3 o60: K2 l4 K* F9 L, m2 o0 w9 l
61
7 }; I1 _: e( u# B- v6 P62
. G% Y2 M0 _; @& w% G63
0 R' H) _ |# n0 h( J7 @# i64
: R9 ?+ c+ w. B" L650 R6 \; Y* r$ v7 h! f
66
4 ~+ r5 O, N! @3 O L67
: k. L' O9 y& l68
2 O+ U/ |9 z3 M692 e. j% {( u; g1 I3 l1 ?8 m
70! p7 t: e* J! I/ J; C) K
71
9 j9 G, I+ D6 u2 b$ ]) }72
* m; F6 u& C4 a/ ` k$ [- V73
. ~/ A% t# N# [! N9 w: ^741 Q( j/ w& i4 h7 d5 \& E
75' D& d$ c; T) c0 y. L P3 S b
76
3 M+ }7 r, }3 O% i77' H! [8 O* b3 y4 N, W1 I
78
* V4 ?8 J0 }2 _/ O3 }79
( j$ J' |2 f5 d ?4 h. n0 P) |80* ?$ A: Q; Y4 u' j( N
81- `, G* v8 i$ f, h( ], n
82
% F* `, ?( l* P5 P% u83
5 g& q* O, F# J' l: b& i. |/ N84
8 e2 Z, _& ] z3 H85
$ ] M5 J9 H2 j; E86% E6 @, r5 {: U
874 ` Y5 E+ W9 D: F+ G, i
886 w5 v5 q/ u* }; z
89! l( Q. H. r4 R& N" L+ L% S" N+ ?
90, k/ d0 ?; w4 Y- _2 u6 r* [# |+ ^' z
91
( G& m& z- n- d; e920 K" `6 u. m- c# @8 D$ N4 b
93" N/ m v+ _' A( f* D E& R
944 ]/ m& _* w- f. X L
95
$ |% H% U7 X2 q3 [96
9 s5 p, o5 C+ y97
- [: ^+ @8 d* p. }98. q# n- i7 |! S
99
o* o( ?) B( a6 d# n100
6 W: ^6 D) m M! R0 X+ {101
4 C# n" {7 F0 C X; @102
9 Q. P! S7 @& q9 f x; t; B103
2 x n& t4 P( H. B9 K2 K2 \- s, z. E) y1041 E# `4 |& T' T
105
9 o% ?$ X/ Z5 v$ E$ {# o5 P! y: `1 V! t106
# k' P2 { U( [0 q- E1071 _* X& J t9 B1 S
108
% k L' t6 b) Q- X6 {109$ o. o7 E' C! ]: x$ M9 e x
110
+ o( A& t9 T: |. g111
& X4 a& _ r; \* c& C112$ e+ h8 l' P( e$ x. T5 x
113
3 `! N p4 s. W. U114: w" u% B- r. W: C v/ A0 N4 X0 M, k/ L" T
1158 o5 P) ~+ G8 k. Y
116
$ d! a8 F' R: ]' \9 R+ i9 S117
. q1 N7 g5 y v7 m( n118
2 \( p) P/ F6 E119
; |2 c3 @$ }) V. _" {+ G; f% s4 j) [120
: J% {3 }: v8 E8 `" S) l- B121
/ x, S" s2 ~# A, a122 P# |" Y7 W& C( _+ v. B
123
$ n) H- P1 g; r+ E$ ^8 w124
7 y7 u+ `' Q7 l; W) w125
- X' h x+ |( M. O126
: O0 g. C& }1 l& S4 }) k1279 J4 E" o+ Z" m2 S
128; @( r7 O* F( j
129! n; G+ Z. S$ D9 } I) @! A R" s
1304 H: v& d" K6 J, A! ~, R
1313 J- U* p; [1 P# a0 X
132
: I R$ u' f6 N0 k9 `133
, C1 b' q2 d' K% e2 @134
+ j" r2 T/ M" @. R: D+ j# T1354 T8 ^0 p# v5 s3 B5 H* m
1367 U' M/ @; I; ?# Z) U
137& o5 f) E9 t, C$ Z& I( Y Z
138+ Y1 h [ l# B* \3 b! t
139& o" |4 S+ V' Q9 t. z# h# n
1408 l$ ^- K3 D. ?( V7 S9 U
141
. ~+ h' z) Y' v. j8 @% ~1 o# O142
) M2 |; d6 ~7 s: n) ]1 D; Y143& W. U+ w5 X' H y! l# F$ ~
1449 ~! D5 }1 H1 G# W/ }
145+ |) e& P; p3 t: G' D
146, n! ~8 h m4 V( d. t; Z4 Z' I: X
147! w: Z7 k, e E4 L) C
148
# v8 A4 B1 n& `8 o) j149$ f: t! J9 n5 j+ c) m# {+ d
150, e; M/ Y( B& K& @* q% h- ?# R9 n
151( M8 b( i& o! g1 i3 O
152
) E% C' I0 j6 Z( m! d1 }153+ D; Y f1 w! y
154
+ X1 W" @0 H& w2 {1557 A6 x) k7 o* ]* N0 Z* K
156
3 }8 w" X7 J! n1572 _% k- [5 c$ ]% h: t
158$ j4 I4 l& }% q
1592 s5 l+ ~5 z$ @1 \
1600 y5 o5 ]3 X1 ~
161
+ ^- @. R: x; T. r' K8 N! j( \162
# R$ J$ C$ b; G8 T. S163$ V6 ^3 h9 @* F" S6 e6 q& c
164
( ?% y, E7 P3 S$ x+ \3 F, B165
& r. T0 u4 L3 X! f+ n* @) I, W$ R* `% J166
+ |: G9 J8 c4 l& c0 `167
8 C7 J5 T, K7 r- } I1688 }1 T- ]0 b7 K0 n1 X
169
) {9 J; V4 V/ I+ }. M/ H170& j# F1 e3 a2 Q. k8 C
171' J4 J; D3 J1 P* @1 F2 M( X e
172
" g" V; W5 Q+ w @1731 x4 Y$ g1 w" ~: `
174# u, [# s) i9 C3 q+ T6 W* I0 ?+ J$ j
175. o2 y. S6 B2 L* ]
176
; A+ d4 L# w! U% R5 \177
4 ]. p2 H1 r# d B( b178
$ e& R# R9 P# A( W1795 L1 `8 F1 U- U- I
180
8 O1 ?9 f! q- r181
; T5 O( Q' h6 [. V1 {3 [182
7 Y1 w/ ^, g) m: h& N183
" x+ y- L& Z2 @4 C184
7 @6 Z# k$ X" v9 M7 K185' R. P" B, x' J1 L0 k9 H
186) E3 A! e, e! L: ~. b+ L- M
187
& R2 _& W& o6 }& @2 ]( y188/ ]# r2 {* J' \/ D7 a9 e8 w4 P4 F
189
- q2 i7 S( C6 T) k/ x4 _5 |. K/ d190
M8 V, \, {/ E; x, a$ p# @' |! _191
# M6 `9 e: x* {# l5 Z+ I192
' T" _2 |, O& A1 ]' M1 @, R193
& |2 `" Z# K- E j! G) O& Y194
: ]5 o) c A `$ S195
; Q; b; a6 k$ c- Z* N. [196! D6 p! t% z0 R# l/ Q: G
197
9 u9 x" A6 J. Y3 p+ G) U198! ~8 _- @5 [: C% a @
1999 V. D: }- j0 _9 B
200( h* F( E+ J4 |! e4 F8 j( y
2013 E6 ` ^# v2 H! ?* L- q
202: }3 Z' \3 w0 N/ m! n t. x
总结
+ U0 A1 L: o: u3 X2 {5 ?自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
* }' G* b& M# d$ F! H5 A! f
% E4 S, }, |0 M& tdemo演示7 k9 }1 _6 s. M' @0 s* E
后续的线上demo演示会放在; x" m/ d; w$ p
demo演示# i, T1 O) D" d8 @9 ?8 t0 ]8 r
完整代码会放在
9 [: s; _5 P# V( c# ?个人主页6 o, P; y; ^- ]
. `# E7 R1 T- |希望对vue开发者有所帮助~
v" C5 q2 O8 c* O* _
9 m0 ^- n: S ?6 a W6 h1 S个人简介:承吾) |/ A4 w4 y7 W. r" R% Y
工作年限:5年前端
; l! u; m% }* a, w: B9 k2 a地区:上海# k9 R% e) B8 Z& @, T4 h ?
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
" r4 { s5 p& l F) A% r2 F, ]/ r7 G6 y7 {
; L: o% Q4 p0 p5 S$ [4 Y" _- H7 f& Z* N# @0 F
) Z2 Q- w0 c: {+ c# k' K/ m
————————————————
: L4 v+ v8 B3 K! B U1 I版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。2 f( U4 t2 F! O4 ^% \4 C/ \
原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
0 p9 O0 f9 m5 p; V, V+ g# ^& B8 V
7 J. [" j* e3 r- [- x
|
zan
|