- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564443 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174556
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效/ g# b; K% d, G, c# G4 H) I
- |- a4 ^& ^8 R$ J- C! Z* P前言2 j, t- V" e7 R0 V3 |/ V- A
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
! r1 J! Y+ D" u& C' f2 _7 s3 x" K0 @TypeError: Cannot read properties of undefined (reading '_c')1 C, o w: z# U1 I2 b, I$ |
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
8 {+ n O' b+ s7 [9 @0 @4 d; }( D* S; o6 |
0 ?5 A7 O* F$ z: j. ?. O2 e1 H思路# f0 P# h; W3 D9 l J
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。0 V* o. }1 B7 _, c
' h( [" n+ D6 |+ F& p% l
文件目录
4 O8 z% c7 p4 G9 x. c: w0 w$ w% ]( `3 y4 j q4 B3 n
3 s. u: M% V$ {5 I% I使用示例/ u3 t. H5 D3 p: e# ], ?4 R
<CountTo+ e0 `! f5 Y! R* I
:start="0" // 从数字多少开始" I1 O2 {. z) i$ s& I$ ?
:end="endCount" // 到数字多少结束( a2 n; B) G5 }1 m1 \0 q
:autoPlay="true" // 自动播放8 u0 x: C. r6 |' A8 T% q. I
:duration="3000" // 过渡时间
) r6 @, s# u1 `1 Z' X prefix="¥" // 前缀符号- _/ y: J( C2 w! g: s
suffix="rmb" // 后缀符号
) C& `% C3 C8 L, Y2 m /># E v( J5 a; m+ l. B
1
& ]0 }0 i- A, n: l5 ]2
' P" N7 H, N6 z. I34 M h* L+ h# w+ f7 N: y
47 @0 I- q, k0 y
54 B4 ?3 }- ~! J+ @' Q R
60 f' Y7 G# T; A+ F
7% a* O) `- O) P' M
8
$ h# x- Q- J" [& m$ u! U5 q' n入口文件index.js
/ {; ]+ K: y' u4 g9 P! x6 _' U3 W+ N! q
const UILib = {0 ^( _5 c6 n2 G/ x1 z' E
install(Vue) {
' }/ r" _- b4 o/ Z" c: S* g7 t Vue.component('CountTo', CountTo)/ d: L" W4 ]' K1 i" k
}
+ {: ~3 p6 G) t' b}/ _" v% r5 r7 k! E2 ?
. I# d4 _5 E- ]5 \+ c
export default UILib
+ H6 w# g) e0 g2 F# k5 W3 j/ u8 r( |4 C! {- D& y" }4 Z
1
% Z5 a. g1 `8 |) w1 `) s21 t. R0 f. z: J8 j5 p0 g
32 x# a: B; P+ T2 D/ J1 ^5 U
4; M( A+ Z+ R" s: d9 j5 ?( Q
5
]0 @! {5 P% C+ |3 ~! @" e6
" w# P3 ]$ R0 @/ o0 n% d# u3 T: ^7/ D' ^" v! L: T2 B- v5 N
8
% q3 i# ^* f f2 s Y9, M8 p9 ?1 K+ V* e- a* C
main.js使用" |& J8 S5 q; V. j0 z
import CountTo from './components/count-to/index';+ j8 [) O7 P d: e' }9 d( o
app.use(CountTo)
# y# q" w& S' t; V1
" O1 U- Z* `+ \, A4 ^" x4 t) s. j2
6 E3 l* H8 v" @' k- b; y) t- erequestAnimationFrame.js思路& b5 V. |- C2 [. ]8 a1 r' o
先判断是不是浏览器还是其他环境9 T b1 N) @, j# a# Z% R- f& `" s
如果是浏览器判断浏览器内核类型
! E1 m9 c( z. M, l如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器
. L- Y. M% I* n, U7 [导出两个方法 requestAnimationFrame, cancelAnimationFrame$ {6 D/ i6 U; ~" ?
各个浏览器前缀:let prefixes = 'webkit moz ms o';
: `- x4 l- l* E, s/ t判断是不是浏览器:let isServe = typeof window == 'undefined';
* b+ ^! y, H8 Q `增加各个浏览器前缀: ! d8 v( L3 |# k) ~
let prefix;$ ?( R) j8 @8 ^6 G* H3 d6 m
let requestAnimationFrame;
0 M4 J0 r# J* h+ T( ?5 y! _let cancelAnimationFrame;
) m) V; `# j( p// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
1 u1 a7 n9 l; U- l# K4 t for (let i = 0; i < prefixes.length; i++) {
! P2 n6 U. `8 l& Y1 t if (requestAnimationFrame && cancelAnimationFrame) { break }
8 o$ `) N' A4 [ prefix = prefixes
/ B6 R( h2 X+ n requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
1 j9 x$ ~) M! ], D cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']2 A5 h+ O) L- |. W. [ s9 Z
}
% a4 }' z- ?& X/ R, z7 V; E- Q9 w% y# W: E x
//不支持使用setTimeout方式替换:模拟60帧的效果
: G+ d- W; Y7 n( E! N Y // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout5 P' q |: }' r. T1 o
if (!requestAnimationFrame || !cancelAnimationFrame) {% {( o5 ?3 c% i, L# K, ~
requestAnimationFrame = function (callback) {1 z" ~: l( D$ C- v
const currTime = new Date().getTime()
" o+ l1 R# D% N* j; F% \6 I6 H // 为了使setTimteout的尽可能的接近每秒60帧的效果$ W- d6 C1 q$ J! }" d6 n
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
$ j o1 [! J2 Q- o const id = window.setTimeout(() => {
1 c& z6 w+ x9 g6 P. h; | s callback(currTime + timeToCall)! c! H; b& x% d* x. ]6 N: G, X
}, timeToCall)& ^' r w0 x5 j
lastTime = currTime + timeToCall
! s" f& h% u$ N6 u' _) u7 U( d return id9 |- e' D) q' k/ ^7 E
}
- t) C2 b6 G. Q, f' I
; i! k* M7 r0 L! x: b cancelAnimationFrame = function (id) {/ C5 l$ i- s% j
window.clearTimeout(id)
, v! j' X { v2 }/ j' r5 o }0 U8 V& ]5 \7 u! J! V$ F
}" s; x( Z* @4 _ e2 |; p. r
3 a% Y. Y2 Y# n& N
1
5 D$ M5 f; i& N/ B2
: A( }" v5 E3 s) r. n1 t' X31 j5 m- [4 V- M! ~$ ^4 ^% k
4
0 V/ Z4 E7 `( ?+ `) _3 `: S5 q7 e58 [& d- U6 R* F' i
6
4 p! V0 D# W# n1 k! e4 P" i74 i9 O, c& [- X4 [7 m( f9 n
8
* U* r) [# {; ?# \: \9
1 x5 t) d8 D4 P% R& p4 [) c10
7 U# B& v! T) T4 U/ p0 C$ h6 `2 W11
" ^$ |* p* }2 M: u' j, x R123 N# j1 c' I3 ?. O' E
13& \, i7 u8 o* p3 j
14
' I! }: I# J, _0 H$ e; g, o. I15
. _3 v1 V- [" N+ ] R a165 \/ b6 P) r/ W# v
17
+ \% J' z {& ^3 h; J! g188 V [8 W/ [$ }$ J
194 r6 G4 y; l1 M- m5 {
20
$ y1 Y( s, h2 @214 ]6 E( ]. ]% Q1 u
228 |5 S. t5 [" ?6 Y
234 Q6 c$ h2 p U
24. J% W" j, S+ t4 d) e- ^
25
, g" t' _6 b- b( Q! z, m26
3 X. f( ?4 z0 n H: i27
/ `% o0 }9 ~8 ]28
9 Y+ R) E" n- f9 Z8 Q296 v" l4 @- m5 r: o3 i2 u
30: R0 \9 t5 C3 u- {1 [7 K; J
31
& B, ]8 H' B# \1 T4 ]32
6 X( l; @8 ]) W完整代码:
4 {& ~- ?# P0 e, B: i& J( F0 X& xrequestAnimationFrame.js8 m# u, {0 y1 y M8 E
# z* z6 B; L1 ?7 [- mlet lastTime = 0
9 h8 i) i: G4 g% ~const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀6 g1 b! m% G( X4 c
( b( ^: h' v& X c* i' u7 ~let requestAnimationFrame! y s7 G9 Y2 W2 m* G
let cancelAnimationFrame
" n5 s/ ]7 {/ L
6 p* ?7 k2 d" z7 h! u// 判断是否是服务器环境
/ w. r! R! ], }( O* V9 fconst isServer = typeof window === 'undefined'- ~$ q3 X1 `/ S- R! q
if (isServer) {5 ]* @8 V0 A H! E4 r% n g, H
requestAnimationFrame = function () {* |- a/ Q V D) k
return
# n5 [* d6 E9 `' u }
5 ]3 H3 X+ w5 d7 ^ cancelAnimationFrame = function () {- n* z1 L3 E0 Y4 p( n
return
, Q7 n4 g3 J$ a: ` }* i3 H9 h2 z6 @: |0 O
} else {
; U6 \7 |3 b8 v* J$ { requestAnimationFrame = window.requestAnimationFrame
E5 P, {7 S& E cancelAnimationFrame = window.cancelAnimationFrame2 {: a+ Q1 d$ B5 e' R
let prefix3 J' \0 }7 X+ x) {9 n) \$ ~+ D
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式& m# D0 c$ o: x) S% z1 ~/ K/ J
for (let i = 0; i < prefixes.length; i++) {
5 e: n" C6 h9 j9 M @ if (requestAnimationFrame && cancelAnimationFrame) { break }
8 |; `0 ]9 o0 B7 b5 W5 Y8 k prefix = prefixes$ Y& @: n/ e$ w0 k& w8 W: t
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']& S, ^- a, {/ U
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
+ ~, X0 Q" E' I' X+ v* J }# I9 ?2 m3 j; R2 {! C+ E3 ]
9 C7 B6 A* [' J0 n6 L: B5 e // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout2 Z" z+ A' Y5 m* B' }+ P; j3 V( r/ S
if (!requestAnimationFrame || !cancelAnimationFrame) {$ L r5 F5 @5 A; R) _5 }1 l
requestAnimationFrame = function (callback) {
n \4 ~7 s# n& u const currTime = new Date().getTime()2 C% Y @" F, s0 G" @
// 为了使setTimteout的尽可能的接近每秒60帧的效果
! o' ]. ~# v; o const timeToCall = Math.max(0, 16 - (currTime - lastTime))# C% R, L+ L4 Y. |5 P. Q* S7 X
const id = window.setTimeout(() => {
4 F1 a, l7 g, q( H: u" _ callback(currTime + timeToCall)
' O5 ?; e$ ~7 m }, timeToCall)/ E6 I3 a+ m8 V. w& t$ V
lastTime = currTime + timeToCall- Q/ s. X# w x# x
return id
0 K! ] k* v: Q2 y4 q9 Y }5 z6 n9 r+ I6 v" Y; a8 e
$ [3 K: ~4 J' U% \- F
cancelAnimationFrame = function (id) {, |# y, K' n/ c$ I4 G/ o* G
window.clearTimeout(id); _/ C. k7 M) t9 ^ X# B5 b
}
# y% Z- J# M1 M3 \ }9 U, W& U$ W% H+ z
}. r6 A ]5 f- z6 Y
6 G. l3 m* I k. n
export { requestAnimationFrame, cancelAnimationFrame }
' c# t" U) _$ O5 s! F0 A7 o5 r) [( {# T. w& X+ Z$ w/ C2 u4 w
7 d& e/ x+ b" y$ U* U/ l5 V1
& }! I' |$ O5 G3 w2$ X3 T" i4 T# m; d
30 K9 _9 j* `2 e8 N2 x) `
4
8 f) `& M7 U: x5, N! ^- Z' @ o0 k$ v4 c
6& c1 Y/ _# O4 q. B
7
6 ?; q: ?# ]# W: l, i0 ~8
4 g! _' K1 I, g/ Q% r9: C# T# R/ V3 ]+ n" d
10# }7 j4 q# ]% t9 l) L5 \
117 R) ^% J* Y3 B2 |) m
12
) N% g* r' b P1 F13
) C: V; w/ N% I& Z. H( r( L14
: l3 I c+ W/ L3 c5 T4 x15
' Y- y$ g# T8 S/ X" H16
, s6 F% c R" J( I17
" |' i5 j6 j3 T( X6 C18
: U8 ~2 z @% w5 U' T7 W7 o; v' |3 c19! a. ^: L! O2 ^- P* _9 O2 _
203 ]& y3 C- R# A% S U7 i1 k
21
, D3 h3 [( @7 o4 k- F3 m8 U22
1 v3 J1 q0 X1 Z' Q23
1 }, i% x( O2 I- O24
( t& p" i h/ L- L4 g4 T i25
: E, k ]7 N* j26 K8 y! ]7 W& G" r; T
27
4 f, W# s/ p, _% y% Z6 X28
$ l6 b9 q+ `' r; h6 } t29
5 k( ^% J j# y30
3 Z: t; @4 l% U8 ], N( H31
' ^7 R5 U5 L/ e# H$ H32
& C( ^7 d" L0 N5 H% u' L0 E$ X6 { L33
" d8 d5 |! l; F7 ]" J5 C34
; ?6 {# Q0 P3 d. k35
. x2 E3 F0 g6 [. Z& [: |( T364 `/ D% S( {1 ^. J3 g% ] n6 D
37
* j, J$ \7 z" x/ V9 S38
2 a$ f/ x2 N( d0 @39! Z) O7 S) X* v+ b; r& b; g
402 {. x# q) [! [$ Q5 {2 Y
41+ O9 z- g0 t7 T5 L
42
% `9 C2 Z$ F( O, I2 |437 N" M' P9 e. x# Z) m9 Q
44
$ M% L: Z8 y" o F! L2 g' ?/ ]: X45& \. Y% X; ^- g( g8 `1 Q$ p
46
) t$ ^; g6 O: \, |47
' o2 D) \4 u) F. q: j48
- C( h$ L0 s% Z/ {+ `, B4 GCountTo.vue组件思路 K& X2 l& o$ j7 Y, [
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。( h M- c3 e; x, F4 v8 o' [2 U* t
1 v$ C' E! D1 N6 K+ z引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
1 J! h, e4 p4 ?19 P2 f0 X% Q! c8 j: ]
需要接受的参数:% [! ?4 V/ H& M1 N" N& `+ _
# H, \( j% b1 }9 q9 e
const props = defineProps({4 Y* |7 |$ i% `
start: {6 P0 F, u. ^- L E6 y
type: Number,0 b1 A* [- U6 Q% D" P; U; X
required: false,& j% X! {* n+ G" u- s
default: 0
; @" m" V/ B* E6 o. M, q! B },
4 a- c& |, S+ v8 o$ c% A end: {
, e+ ^# D# f! ]$ `2 H type: Number,
" T. ?( B0 h1 X2 u& X0 l. @. a required: false,
: F3 D7 P% e- A$ U8 ` default: 0 P! c9 U- t; @0 p! b' d7 X/ y
},
1 D, b1 L; F2 h: P4 n# a2 M8 n! | duration: {8 q9 Q+ t D( `4 c
type: Number,) {' c! B* S) ^' G& q
required: false,
1 N+ O1 T0 S/ I/ k default: 5000
. ?) u9 r) S" q4 E" c9 l+ ], a },
" Q; }# e/ y0 q: g4 A; N autoPlay: {
* @. Q! l9 d) u type: Boolean,' I( t" z. [( U& g0 t
required: false,4 m h3 Q0 ~/ a$ o4 a% _
default: true, h' M- |- d y2 O4 X4 d% @1 ]
},/ ]6 u/ j; q* P
decimals: { m, p" C- ~! w
type: Number,
2 m2 O) U1 z: ~4 R; r- A required: false,+ E: M% p& V: _- ~( |
default: 0,) ?+ i0 k* R+ N3 I) J
validator (value) {- C$ ^9 ]2 {+ d9 b6 b
return value >= 0
$ T+ ]/ B. Z! ~5 Q }
/ R" F8 l; x3 L },
6 G! T: F* j0 H# h( t4 c j# B decimal: {
: S+ \' j& l% J5 [ type: String,- T, K4 r0 H4 V- ^( S7 O
required: false,4 _: Z& o" @; z+ H; i+ o( t/ R4 e4 a
default: '.'
; E7 w" e% Z5 v) W2 b/ V6 R0 ] },
3 B; g# U8 K$ p: T# S8 S- W7 o separator: {. m! V6 W. d% P/ {- U0 I3 f
type: String,
, ^; \8 |. l6 J! }7 P! C required: false,
* U8 E9 G5 z, c6 c8 g1 P9 q default: ','5 J( I( m5 F, R8 v: n
},
% N2 e1 ~' P$ X/ Y. A7 X prefix: {! y6 E8 V- h0 `8 P; ~1 a* v) @
type: String,
9 M' R" J" N8 `7 a# z9 L, t7 p$ A k required: false,
3 a5 l6 n6 P7 H9 C# x! S default: ''
0 N; z* l/ t1 n$ Z$ j0 V },
% _+ a1 x+ e, {, e" Q8 M suffix: {9 C3 Z* D; ^+ s8 _) j4 N) E
type: String,
/ p( L7 O' F) w5 M+ b3 n p" @ required: false,
9 L8 v" B/ _0 c$ y2 U default: ''
' o- b* V* p5 ?% m& @! o6 o: u },
" E+ b! [) D* h; @6 v( w! j7 F/ O, q useEasing: {0 a f6 A9 G. e2 L* | n2 G
type: Boolean,' W' x8 Q: S; r
required: false,+ p# X, A* M! B$ m9 a. e2 n& E8 F
default: true! [' U8 `: ~0 k0 S+ p
},
* O( M7 {1 d" J/ [* g* y easingFn: {8 k3 [' l0 [0 e, [4 l% {+ H4 K% H3 T
type: Function,
6 C- H) B& ^/ |8 }3 x default(t, b, c, d) {! Z t+ b. w/ d5 v# a: Y9 O
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;0 T: a4 |' R) s# }$ B
}
6 w$ \4 Q+ l! Y+ | } b+ Z) b, y8 ?* K# w
})* J! K8 E4 ]6 @" k4 y: k
; ]' U/ w) d* _$ |
7 V0 Z6 O; O1 q( p- T# K4 z
1" K- `- r1 r7 q( {- N
2& ]. e% ^& Z; e# k& h/ T$ a x6 ]
3
2 m( ]5 d0 F+ U; ^: |4
: D+ s3 g1 U' Y' Z% ?: ?7 b( Y5
; s! V6 \. g- z4 g6
: ^6 I5 y7 y& d+ G7
$ K3 h0 F1 z4 V/ }. p3 A( a4 s8' }2 m$ h! i7 A
9: o J3 F3 \( n
10
) r! a. K n1 X5 U112 V; j% ~- K6 z
12- D- j: Z5 _5 l/ g! F T& S
13
+ w* R' h t, s: p146 S8 B" L$ C0 I9 J
150 H0 ^/ h. C/ S) `
16: X& i: m, k4 _
17
3 T5 i" F; f6 K! k18; X; e% T* V' K" w
19
0 C: s6 J- ^8 U$ _4 i- P% A) H20
. B8 I) {5 ]& o. a: f( V21
! _0 r' y$ G+ V( {/ x' @ n22- O* s9 Y% W* q' |
23( p- X. z) [- {5 B
24
# d1 \7 w# L3 w p) c Q* E, w0 b257 R7 l! m& W6 q8 h( d
26
( T8 n4 P7 k( p7 A6 Z27" f8 Y/ Y# k8 b' C; n7 L9 N# I: ?
28
* S) C" E" f! F6 \1 b29
: A4 H) p9 t$ B; `# g" x) I30
0 l$ q8 _* H) a* W: o T31
) W. b; v" `" q% ~; R5 B* w, `32
! f& R( e, I9 c33
5 |! d+ T/ _4 W% v6 {+ \34: x/ m0 t1 W. d- z% U$ |/ F
35/ p, y( t& A N
36
1 o5 Z7 w' s4 c37
9 t& C+ |1 d) G4 F38
* Q. V7 s0 G% _7 Q8 u" k& ]39
6 k$ X7 h6 ]+ O" Y* m0 c40/ C. N. f8 |" l9 C* }! T
413 X8 a. g2 H* T
42
7 m- H, T1 W8 r% s5 X8 g43& E, ]# ~5 n0 ]9 g& I, X9 j
448 e, B% \ l6 i) R3 } @$ o; T/ Z/ k1 |
45
- B' c4 Q9 f4 g46* y9 p1 T, \7 V: k
47
3 c [2 b. m/ ^+ b# K9 `: D# F* F% o48
0 ?+ U& N* B$ U( `# S V49
" M) v. S0 G* l9 \50
# I9 U9 N( E( }" `51
7 `$ F5 k$ J' l5 `" M: g52
% Q6 D3 h/ s' J" O' `533 T3 r4 X6 t) R
54
* R* E1 ^' _/ {( y2 |55$ t- r6 Y% j, g2 }1 a% E5 \
56
! I8 n+ K( u! Y* \7 C& |57& Z0 w t. | e0 @' j% n4 @
58& I' A! ?' e" D% v7 F6 P, ^
59* `3 z0 Q% M% ^# C# \
60
0 q) L" N4 G8 F I1 y% ^5 u8 |61
' j1 J$ p7 T% S62- u$ ?' X/ J: T% r! r, O
启动数字动效
- ? B3 ]# f2 A+ r# J& `$ P |* X- A2 E: b3 w! W
const startCount = () => {, a+ ]) ^$ Z& n% J* M( P2 F7 x
state.localStart = props.start
2 |7 Q$ t7 C9 k v% F7 i$ J! m2 P2 K state.startTime = null
7 Y, }' u8 Q7 k8 r s" B! Z state.localDuration = props.duration/ K, J! p9 o* q! J- D
state.paused = false
# @ f, |, n) Y% { state.rAF = requestAnimationFrame(count): u& D3 f- V1 r* ^+ t2 N- r
}
" t8 [+ T$ X% s; s3 W( L1 Z# e1
* n) T7 \& x" O# V3 ?8 E, u: Z2
6 t8 v( R1 C7 m4 f32 Q0 ?: w) ~; `
4
( V1 G5 c4 c% N+ t H( U Z$ L5
* e. S. J5 T8 s- Q1 a' S2 K9 V6
5 L. y' |4 S" H+ ^7
4 R2 r0 q9 j t1 n; L核心函数,对数字进行转动
+ T o+ W: d$ n( w+ k- p& W: K6 p# |& f8 V$ o: Q- e7 H
if (!state.startTime) state.startTime = timestamp
* K1 Z3 i" E @4 g state.timestamp = timestamp7 S4 X0 Y! g E3 |) y# {# {
const progress = timestamp - state.startTime [- ^2 e- M$ j' L
state.remaining = state.localDuration - progress
) ^. H( {! L' A" U0 n // 是否使用速度变化曲线1 L. q1 L' g, B# n
if (props.useEasing) {
- _/ O. ~9 V$ b9 J; ` if (stopCount.value) {5 r1 w9 k: J" E/ I4 h
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration): ^& x: M) f+ K+ U- Z
} else {
2 |; x3 O' P5 n r* D state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
8 t) [0 Z$ i: F! G' Y }
. g6 Q/ ]% V7 I$ P" `6 z; G0 ]. X } else {
7 z4 N& P# |' u. h$ z if (stopCount.value) {
& ], _2 V# J0 C# K' A' Q state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
8 F: k u8 b" P; B } else {% @* p; b7 |+ `" x6 V! Q2 s
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)9 b5 n! ?8 D" h
}! ]8 ~- D$ q- a/ M- }
}
( X9 O0 O1 O& {( [' e3 A if (stopCount.value) {
3 c& O2 Q% e6 {( q state.printVal = state.printVal < props.end ? props.end : state.printVal
# }4 W: {, I! l, Q" z' | } else {
5 C P' Z8 q" W; M. g state.printVal = state.printVal > props.end ? props.end : state.printVal
0 [' P0 ]% ^! N' U) ?+ U }! X; z9 ~5 C4 u( W- f" Z ~+ W
" P2 ?/ b) j" R- Q$ ]
state.displayValue = formatNumber(state.printVal); @4 F& u7 r% _$ Z# B1 y+ u
if (progress < state.localDuration) {
9 _- M3 d! y9 x! q) `$ r7 J state.rAF = requestAnimationFrame(count)
. e% f5 v$ T' Z) \1 X% V" u } else {* e3 ~1 e1 ]8 d
emits('callback')3 u/ j5 \* s6 ?8 M% b/ E
}
L' y. h# N) m2 u' a}' \; B$ |9 I: Z
7 w* d1 D; L& a) r& G7 m$ ?: Y7 ?
+ e; \- H; S& R( u$ Y# R% L3 I |
// 格式化数据,返回想要展示的数据格式$ t* X3 X) k6 L) z, a7 K5 @
const formatNumber = (val) => {* ^% j! [# T! t! w- E! Y: C @( e
val = val.toFixed(props.default)# J5 l2 G9 o1 l1 Q5 ]' Q
val += ''
/ c# {- ~% g3 L# L7 O, r const x = val.split('.')
5 p2 k1 Z4 t0 A9 x7 B- v let x1 = x[0]# [7 K) [! d2 x K# @1 Z" C! G
const x2 = x.length > 1 ? props.decimal + x[1] : ''9 [( Q; u2 `: A0 {
const rgx = /(\d+)(\d{3})/+ _( D( O' m( r
if (props.separator && !isNumber(props.separator)) {- U6 I/ a5 \+ P, v9 j
while (rgx.test(x1)) {$ f# w3 b1 Z5 _0 P3 ]1 ]6 G2 q( ?" ~4 O
x1 = x1.replace(rgx, '$1' + props.separator + '$2')( i6 H) B j' r, f7 [
}0 w+ K5 t) T& y+ V: v
}
. X+ p' R7 Q6 A" C3 e' H return props.prefix + x1 + x2 + props.suffix0 z [$ }" A& m' {/ m0 H4 S6 K
}: }' u7 R+ F5 G N
. I3 O. L, C7 t6 I+ X, H. G
1
2 P: [0 u6 E) l& B% M2
+ a( x3 n2 h/ F+ E+ c9 u2 e3( \: Z" I2 R( G3 b* b8 S2 r
4
5 m, M; a1 S9 _! ~8 h1 K4 q* X2 Y5
5 T1 u% v9 g, l' @$ v0 |61 u+ j' c b& D$ F) n7 M) S
7 a% Q5 d0 o( r2 M
8
/ G& F2 C2 W# B6 A q! U9
' f1 @ t- _3 H& U! f9 m" {2 M109 P1 U- T/ j5 s: v) j1 V
11
( N4 h# o. D: u5 m127 @6 o4 r4 z2 |4 p0 U1 {6 a' h
139 b+ @6 F; K4 E% [
14
% }& V9 c, g7 K5 h5 e& S15
1 `+ W8 K% f8 F- s165 P! J/ u/ Y2 O4 H* m$ X
17
% n1 r: w1 [6 V* }, j; S; ~18
7 Y# `2 j9 ~) h) T3 D19
4 [. U7 S/ u" I% `0 N20/ n& W/ @% L: U$ _) B4 z: H
21
! c, L7 g7 c+ V; Y# [" U+ \1 r22
& L8 K7 @& T7 @+ i23
7 b* H; }' H0 e" G$ r9 I4 N5 F7 \4 @24
1 r: W2 o" h( N8 V& ]/ ^25
- c: h5 I z2 U3 y" w26
: S0 V6 c6 Q/ s275 L, d+ R% d3 d$ ]: ~( D6 n( ~5 M
28
$ N* Q+ H* C' |8 x29. ^) n7 ^& {, A
30$ V% q1 ? S/ \
31) o8 z( ]8 k+ h% o
32
, ^* c9 G5 u( y% A33& e( z* q5 U0 l) P/ K: V
34
' `3 r7 t, O) C# L35+ t ^; v, r! k+ }) p( {
36
. S K3 ^" ~0 c, I37
& ?$ B' K" Z" ?9 ]9 B! ^- Q! M; W/ }& j38
3 i: p) W+ J! T- i397 l: v# l# `# j, Y2 I( c: `
40% h+ A' N+ f# A5 B5 f8 l
41
4 J! {0 m' O7 F% q8 k- `42. ^& a6 T- @7 k% D
43
) o+ w0 K, ^% k, T44
! K, [8 f; h7 C. [; \45# }& J$ i" R9 M& w% W) p% s k
46
' F. |4 T( f+ a% ^47
' [ j4 `; w7 Z: y48
9 \# Q& D$ h/ ] M* ]& e% ]% b取消动效
. m* ~! Z: p# y/ ^
3 [6 B' [6 ?/ w$ j// 组件销毁时取消动画
6 z/ w. Y) ~1 i9 c* honUnmounted(() => {& j' E8 A: L: Z0 J, v4 _6 c
cancelAnimationFrame(state.rAF)6 b- c7 V6 f* e1 J# y, H
})* \& P; V, V) B1 n. W+ |
12 n9 Z$ C# {/ a$ e5 ]: p. |9 ^! e
2! Z! h. p; f# Z. x: k" i
33 X* o/ U# H6 B6 P; f- [& B2 t) u
4. G0 V; p1 i* S9 N
完整代码
! K6 p+ z' _8 v7 ? t( T; }4 r: f
<template>
' W& l! V6 ?) i+ w {{ state.displayValue }}
" w0 j7 ]/ j# k# Q7 Y& ]</template>
4 _2 b/ |% u: ^* q# R1 @6 F2 D( {$ O1 `& d& i0 E
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效& [0 p( x3 h/ S; d
import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";$ P- r' u: C/ m! e
import { watch, computed } from 'vue';! }" |2 \' M7 i
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'- F2 m4 c2 g- A9 }! f) N: u* X; O
// 定义父组件传递的参数
& X1 O; G: N! {6 O" d7 uconst props = defineProps({' M2 r# R4 v( P0 P- o6 Y8 H
start: {$ _* i# a+ P5 z7 @
type: Number,! I( l0 ?7 f9 H0 \7 M: Y
required: false,, _1 M3 _- ~: k( W
default: 0
* X: S6 ~ ^' s6 r2 n$ J* b },
( i/ A' A" V3 {7 d i end: {
7 P2 Y% @0 n8 @/ h. { type: Number,
* |- q9 l5 K( K5 x required: false,
" d5 _! h) B5 q6 w. m4 f# H) u( Q default: 0' Y8 d5 ]" a1 u5 }4 P
},& ]! p, G/ }. p# ~, [& G
duration: {, S, _6 B [, C- S ^
type: Number,
% a v, E. n& ]# j, Y: w6 c required: false,( A" o/ n# O/ O9 k
default: 5000) s9 z2 S5 s. |) _& y- Q
},3 w5 j+ v$ D0 c5 k
autoPlay: {
, }' x$ ~: g k$ J2 J5 a, K+ o- W type: Boolean,6 T, w+ Y5 X2 h6 Y
required: false,
- L& }4 G! M% K4 [3 o( N default: true
3 e9 B5 e$ Z: z7 M' t4 ? },8 {% _0 M* }2 c4 D0 f4 _+ |. G
decimals: {. k1 }. A& r& \: q) m- X5 M) s
type: Number,5 C7 w J3 [$ e4 Q
required: false,/ c$ m* ?+ ~0 Q# ]# |5 U
default: 0,
7 R% P9 ~2 U9 P, ?1 C6 y5 m validator (value) {
, z5 t: ?% K+ S' A2 |# q. i return value >= 0
- G8 ~% |2 B$ i# d }' \0 u1 a, J/ W
},
' _8 ^* g# }* E/ I& C ~4 R decimal: {
- P1 U1 a7 m/ u& H2 B type: String, d7 M0 |% p& O7 ?1 G# u$ b
required: false,) P1 S; \2 Q2 O& }$ E! `, p1 d! [3 T
default: '.' Z% N* b8 H7 v# w6 l
},$ o$ @) X: T h9 P/ O' `4 {7 o
separator: {
5 G; R# ~, ^% m0 l( E! T type: String,
" }0 S; O+ G1 I required: false,
$ B/ \( M9 g7 n1 b) z. I default: ','
& R B8 F6 |! C* `, U },* U! v% O) R! s( B9 b/ k5 Z2 `
prefix: {
( ^+ N/ J" T+ ? type: String,: R; |& Z7 E. O( D7 A; x" t
required: false,0 s5 h4 t0 |1 r# _3 v! a# M5 C1 m
default: ''4 t7 p5 T* e/ d; a
},2 r+ @6 \. i, J9 N% M; \* m
suffix: {9 X8 [/ G; A. [6 @4 L6 ?4 ?# `4 P) v
type: String,
: I2 S4 P3 V0 G0 V! M( P required: false,0 s5 O0 e8 O3 S% k" `
default: ''+ Y4 N' d% E- k$ X: F! R" a) h
},
7 ]2 P6 Z3 l' T useEasing: {5 H% d; s9 x/ d& F0 P2 I3 `! w
type: Boolean,# L- E" S( C( c0 ~9 b U/ W. K
required: false,* E9 K2 Z7 W9 H+ t( u4 o- x6 o
default: true! V, S; R- M7 x) s9 n1 u, [7 p2 G( I
}, c: _' W% I3 K( I* B9 N6 D6 [
easingFn: {
4 f; j8 E7 `+ e' a o type: Function,9 S3 K" z2 h8 G" O6 ~. i7 ^
default(t, b, c, d) {
' S" l6 g/ b5 C6 ] return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
. z# f2 g: z9 P* Y! V' ` k } @4 V8 ~: d. l( b, X
}( k# j O5 B2 E6 n, p' e, y& T
})* M. J x, Y- n$ q, A) V9 A
* i, J* Q& |; n: mconst isNumber = (val) => {
. m1 K4 J% G# O. r+ f9 L return !isNaN(parseFloat(val))
& {3 o+ x) V9 C& p6 G. s}
' O/ F+ I! z5 A
: K3 B1 G: r/ F- ]4 m. J# ^1 m" j( ]// 格式化数据,返回想要展示的数据格式
2 k" P, ^/ O1 ~const formatNumber = (val) => {5 R3 Z8 T6 B( }( Y# Z
val = val.toFixed(props.default)
$ U3 o/ `% P. b% s$ M, M* e val += ''; F* s) k5 X- N$ P5 Y$ P- E3 Y
const x = val.split('.')
2 ?1 D$ D6 V% t9 t5 j% H let x1 = x[0]
2 f. ]% B* o# `/ l8 J const x2 = x.length > 1 ? props.decimal + x[1] : ''
) h% a8 u& Z9 ?/ ~ const rgx = /(\d+)(\d{3})/
/ l9 G0 E( G. z( ~9 b6 _ if (props.separator && !isNumber(props.separator)) {
5 B/ ?& D- i" m+ h( H: r' |) { while (rgx.test(x1)) {
- o) L8 X- W; B& }7 ? x1 = x1.replace(rgx, '$1' + props.separator + '$2')
& x6 P7 W! [7 o9 F& Q5 m* V. u, a* l }
0 p' w X' C- K. P' F) }) W8 r }
: i; y% L- v2 o return props.prefix + x1 + x2 + props.suffix- Y/ W) N" g- R- [* n" Q( F
}7 ]/ U' {2 o m' a; V$ V
2 j+ a$ D1 V. J5 Y# N// 相当于vue2中的data中所定义的变量部分: C! S0 W, j: p. F
const state = reactive({
( @% E9 }! `/ ?. u" ~; V$ C. [ localStart: props.start,
$ s, O0 O, Y" J4 e3 W$ l+ c Y7 i displayValue: formatNumber(props.start),+ h3 T- E6 v7 e% ?" }
printVal: null,
5 Y* g! a, @9 O# `- e paused: false,
0 b/ J% s+ h" V% _ localDuration: props.duration,/ r5 Z+ u1 N; Z# E) t4 |
startTime: null,
. a2 F6 r4 z: |) v8 L: w6 f timestamp: null,
$ M5 Y: u) E+ @3 P* a remaining: null,* u- o- a7 G! A; j
rAF: null" J2 h8 w. z) B5 K, D
})$ [; c8 S* n4 Y; W' M
+ D8 q8 s0 c+ p7 x* O7 a4 p2 f// 定义一个计算属性,当开始数字大于结束数字时返回true
+ E. j& ~! c% R, b8 Pconst stopCount = computed(() => {7 ^2 W+ }( ?% ?) O, ^6 M! B6 A* `
return props.start > props.end
5 t& j% L6 H2 a5 V$ U8 L6 X q})
, z: v3 d! I1 S6 }$ {// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
" Q" b9 h$ s9 u- u/ O, ]const emits = defineEmits(['onMountedcallback', 'callback'])
E& K' V9 C, U) }
, l/ a' {* I8 hconst startCount = () => {
& J# N3 h. Q: ] W. B) Y, x state.localStart = props.start3 z7 q! ^' ?5 N/ ?
state.startTime = null
. q' I% `# M" u: ^3 j" c. u5 A: ?: M state.localDuration = props.duration9 u a3 H% N: B3 l( b3 `
state.paused = false, T$ R- K0 B$ @* p2 [, A
state.rAF = requestAnimationFrame(count)# F1 Z _" }1 I3 `
}
, z: F0 ]' P% p* Y: q: N1 j& a7 H% c p. g" D8 T" `0 @8 g
watch(() => props.start, () => {
4 f) `. K, z# y; Q if (props.autoPlay) {2 s2 L. u& z, `+ R6 l
startCount()9 t$ U( I, L8 ^* c. a
}
( k! F% `$ D* ]5 B})
- ?, h4 z& D3 {$ j1 J. u
9 i% K: h+ \. Z$ f$ Ywatch(() => props.end, () => {
/ W, v" S; x# C6 M& w ?% C7 Q if (props.autoPlay) {
% `' j/ M- ]. p9 P startCount(), Z$ A4 }6 H' `1 M
}& a0 _$ d$ `* Y+ Y& i
})! _. n, V9 j8 c) r0 q
// dom挂在完成后执行一些操作/ {6 i5 L! ~0 L/ B
onMounted(() => {
) O3 Y. E$ A9 J8 k* b if (props.autoPlay) {1 v0 g8 @ Z% }$ R: T0 b
startCount()
! G$ e/ r5 f+ x! ?! V3 e: b( ?, a }
2 ~7 r6 G& ]: q9 o+ ]0 Q emits('onMountedcallback')% k0 g* V# U6 B: X( L5 m9 i6 C9 B! d
})
0 K/ D0 T# N( j; h. l2 L: W6 B// 暂停计数
3 \( H8 L F, y* o4 e) Lconst pause = () => {$ N# w" _* |' `
cancelAnimationFrame(state.rAF), U9 {. |5 A: K+ a
}
4 R' j. p E$ L+ W5 p* P" H// 恢复计数6 ]9 A& B! t: k; \& j
const resume = () => {0 k/ ]- s3 g- ~( e, N g: p) X
state.startTime = null
- k. e# S7 Q; z1 q8 ~ state.localDuration = +state.remaining5 w' K7 G& b$ ]) ]9 J
state.localStart = +state.printVal5 y4 B+ F& A( H1 A! o2 U$ v
requestAnimationFrame(count)* F, q/ R- v/ P
}, [4 m/ ~- O; W* [
; Y+ u, [8 k* i5 W/ u
const pauseResume = () => {
, ^: E" d/ A' `8 L9 \$ B+ W/ P if (state.paused) {4 D& J& A; ]+ x
resume()
& h& c$ v. M% _) v state.paused = false
; }! w0 S" Y7 N; r' }) Z } else {
) d* e% j9 d. a% v u pause()
! E+ ] B1 c J+ I9 Q2 G0 ] state.paused = true
! I E4 U0 C9 o5 W8 P# T }5 Q7 i @ V) S3 T" C
}7 A7 O6 j. q( n
" {" ~% F, l: k( v( Dconst reset = () => {
" h' Q0 G/ W9 f* E0 i! T C% U state.startTime = null/ k" h' G) m, S+ i! Z
cancelAnimationFrame(state.rAF)
+ U7 q' V7 H ` H( C) v$ Q state.displayValue = formatNumber(props.start)* d3 \* S! ]9 l1 V( k" `5 ~
}! x* w1 ~! |! ^9 c# f$ j2 r" ^
5 }+ x; }9 {; q3 e( @7 b
const count = (timestamp) => {% W& [' _7 d) E* H) I8 }$ A- a n
if (!state.startTime) state.startTime = timestamp
4 x i M( o# C* \8 G$ U state.timestamp = timestamp
7 [ W5 t% }0 P# u+ ]- z- s$ R const progress = timestamp - state.startTime" t t: o% }' y1 h, ?1 h
state.remaining = state.localDuration - progress+ H! _4 o. O# C# S9 a# ^4 J
// 是否使用速度变化曲线
# B) p1 b% ~; W7 `- `9 |' D* Z if (props.useEasing) {' Z5 A' i1 w# q8 q7 Y) @# `
if (stopCount.value) {& @4 Q7 a6 J% e
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
# ]# }& J3 ^: G } else {# | |. B! {+ y- ^. D, \
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
5 y7 I8 P9 I# U) h& P# t }
7 O4 i* {# I' D6 k, E. n6 n, t9 p } else {3 B$ G0 ]: l% ?: [
if (stopCount.value) {/ U8 U2 L2 f0 G$ q; p
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))' ?4 B, S6 `+ k- o7 ^! b
} else {8 R* [) z& H% G9 ^6 T
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)4 B; G! j" [. @; o4 D' L
}5 M6 B& {7 R3 V# c _# n
}7 E" A+ A$ q2 t- C6 A5 D
if (stopCount.value) {
) Y8 p K) H- p6 C4 E) ~& n state.printVal = state.printVal < props.end ? props.end : state.printVal
5 ^2 S# E( y/ ~0 j7 d& z5 L } else {) W9 P& @4 J1 l
state.printVal = state.printVal > props.end ? props.end : state.printVal3 A' W9 T: O' W" C$ r/ [1 N
}
) G9 O3 E# w, _1 j! E' Y( P" M" ~* {. L! W. c; r1 X
state.displayValue = formatNumber(state.printVal)
- L1 F2 q9 p3 p8 v& {/ o# i) k* p if (progress < state.localDuration) {
" Y' G7 @$ u/ W" n1 b$ T; t state.rAF = requestAnimationFrame(count)
: V: Z3 k) k9 b/ z6 B# X5 R8 _5 ~ } else {* e/ [+ m- r: W$ s. w
emits('callback')% p" C1 O( |7 H3 J
}
3 B9 Z& `/ B; @. F}) E: N# ] y" @2 ?' G, ]/ A8 S9 W
// 组件销毁时取消动画/ F6 Y$ ^- q& f7 b( {
onUnmounted(() => {
# `7 w. N: Q+ O& R cancelAnimationFrame(state.rAF)
" j$ g) Z: O$ b' `) A6 B})' C6 ?8 M" D- k
</script>8 V* {, w6 H5 @
" F4 S9 L. t: \$ V9 o w1" k0 w6 ]' W9 w; [( H) U
2
# p1 L% c, Y2 z3. J/ G' e0 B5 ^/ I3 t6 L3 F8 d
4 ?- O( w) E+ ^
5
( f* {9 L3 C! p3 i8 s% @- D F6
$ Q( r- Z7 |. H4 l7 t" i! x1 l! I+ Q( r) `
8
6 F; c( {" H$ S) n+ t6 |9+ l0 ?$ J8 W1 l4 C
103 V7 y/ v4 H& J9 [9 i! n) ?) x6 ]
11/ f2 ^2 C+ c! q
12
C2 J/ p: ]9 `4 J5 ?9 O130 M8 q6 _! Q# e! l& e
14& s% K1 m2 l) n4 d
15$ W6 |4 @ N7 d) c( U
16/ j( B1 ?. c9 P" L5 S
17' K6 U# r4 `' `3 [
18
/ _9 [. g' W3 A" m19
$ e- g' b4 L2 G* |20
$ @2 e& a- S8 _4 I0 m21
% \5 l; X4 r1 |# X! ` j6 d: b+ e22
a6 \2 n6 g/ a9 ]: c5 @23/ {4 M7 [- M$ f$ ^. Q, `
24% u* c; e4 K/ I* i5 [5 r: L! R. o
25
' }! q: D! R( ]2 u/ s; o# G26 s% i0 d' z6 f. m5 V4 n
27
" M+ s+ B5 d7 u4 ^* I# G28% z7 A5 L+ M t6 I
29! Z' a" A- C+ _2 f! U! c7 g6 P
30
# q4 e0 g6 h- i" {$ P31
3 ]2 O B8 N: g324 J/ F; k1 u" T+ j& S2 \: B0 g
33
8 r! Y) m5 q/ G* f& W34; O! X7 w1 c# ^0 R9 i
359 p2 H: s# U* ?, U1 E- f, H
36
{) k* F$ [% R7 `( s5 n+ @: C, ]37; ]" a+ p( K+ v8 T: P: l% k+ |! F. P$ w
38! J. v$ \" E- V: H
39
- ~, p! |# C3 X40
2 O% i+ m% {* d+ w, H" U6 c41 P4 k2 p5 f% k& _4 x
42: Y, `' ?1 o8 ]- u6 E. x5 t; d: @
43
* { I4 E8 S& f: W44$ x; H3 {7 ~4 C5 A7 Y" v+ J) w3 u" R; ^
45
/ N6 K- \9 F0 l- K+ ]* t# Q469 ?9 A, M9 p9 v( r
47
* y0 p5 n* ]# g: Y. i2 k48, q) i' }& B ?3 }2 q8 T0 P3 l8 \
49. o/ G4 q* V* v5 w0 _. T
50
: h) K$ a; Z3 h51
% ]9 l9 A. n' i. G( S52# z- q1 v( Y: P; F
53" q6 j+ d! q; \, ^( A: T
543 u: ?; W" B3 o4 R2 K- x# h$ l
55
5 _2 y3 t1 K* N. b) A56, z* ?- A; f5 n5 j/ z0 g: C! n; [
578 ?7 q n% T" m0 q; k6 m
58
% n7 e1 N2 V" U1 x1 i0 X59& z$ |2 p+ }. G
60
6 n9 G2 f8 r+ O2 i) g- `61, @2 z2 H; H" {3 s3 V% v+ s8 B
62
1 o+ ]$ W& R! Y6 N7 A63' M, I6 F2 j% f0 Y$ D) I2 T
64
1 @ u6 B1 C6 g; B* S65
; U- j& V# e% L' @) t66
/ @# ?4 q- `7 p& u) j( x$ z* |671 v! _5 q0 _! s5 }6 @
68
+ ]! M; G5 c6 _$ ]% K# p0 W' U/ J69( L1 G L0 |2 F/ k
70- C' G* P) e; m3 x/ t! a6 l0 s! E
71
0 V; [+ B3 @; b6 ?1 x72
, T4 T8 T0 r0 `" p" x+ A! I# h1 K735 n: ~5 Q \6 @+ X& }0 y
74: G! `2 e. L! \7 u s& N- a) N4 u
75; Z4 U/ U& N5 \5 M( L( B! a# W
76
* d5 {. m; Q, g- u778 z1 n5 g* z, L' ?: y8 v
78* ?8 ?- J) Y( X7 L7 `
79
6 r' n1 l _6 A( I807 P: y- e) D+ ?
81
, T. _, D# {6 C82
' E$ G5 M/ u; o: Q: }% t83
8 q, V- m7 `" Z' z) |84
5 X3 I+ K& K+ `% S85# O. |4 `. N& ?; Z; k
869 c5 K# G+ p$ P* f& P& N1 N! _
87
( S- R% _# `- t2 l5 ^' J. H88
5 f+ n$ E0 z2 S( w890 f+ O9 ?9 E" E& m" R
90
* r: I& ~% D3 f/ L8 E$ k91
9 \6 Q# n2 M8 x0 U! {5 }+ ^2 K7 `92
R K. D5 [; P) h6 l- L) c8 y936 F" Z0 I5 u) e" _: r) ~; g3 v& ?
94
7 |! C6 a$ g5 g6 F. l8 L0 a) I95
; n" B1 ]+ i+ @' w96
* g! O# L8 p1 A, d) }, V97
, `* i8 `1 u. ?. v% w E98) \8 N- D6 G4 T& [6 d
99" K+ y0 p+ A0 O, Z4 E
1007 Q: P5 Y! b Q2 t) Q
101/ t0 i7 V1 `! X( S# \
102
3 @$ q1 R' _6 E& p103
7 j6 w0 h1 D; D; i T6 m104$ Q: t+ ^: ]' @) U- G" X/ O) T: |( i
105 o% f+ I$ P9 k/ k* C' G7 |. ?! n
106: G. R2 P P& D* p4 j' Z
107
. ?# J5 c6 R: x; b+ {% I108
0 D3 S' s, Z' U$ ?* i109- _; ?4 M0 D0 r$ t1 U
110+ V# d3 r3 {5 X. J) v" E
111
' i" I* H0 \6 \112
4 T4 Z% d- G* [7 O/ T7 A5 l# \0 J1 X113$ K. C. h3 P8 T9 r+ i
114
. L+ e* Y2 S0 a6 [$ o: j2 W115" t5 C# S4 e/ k' G8 K: z6 i
116
! X- _) x5 F% O( T0 t9 t6 C117
) t. f3 x3 _& N3 p0 Y7 _) Y1187 r+ x3 C8 P: ^7 ]- `2 J
119
4 f1 M0 r1 h8 o4 P' h8 C1208 {6 k* h6 N1 I Q" A) Q
121
" t: [) z! e9 }, Q3 K+ _8 Q6 v122
2 Q# B$ E7 I! R. W( G123! A9 j* }, r" J/ v' Q; s3 c
124# n- x: ?8 T* [; V F; L
125
4 r6 w0 J T6 ?126+ T3 c1 z6 J* F3 ^
1270 |: X! N8 q( A9 q9 q: C5 W
128
8 d! u8 {1 P# l( }) m& a9 Y3 n129# M3 F s7 _/ _* h2 f" O& B. f( q
130
& r3 N( y: E, i) E: ^3 A3 ^1315 d8 p: y0 `& {$ A6 X3 c! v( g# `$ O/ s
1325 X( D3 s. ?) S
133
" l( O: T. h7 j134
) ~. t( W; o- h3 ]1356 r9 ?$ Y. H0 e' Y1 X4 O
136# j* f5 W P/ h/ f2 W4 g+ ?$ z7 T
137, T9 q3 I4 f$ v) ^- k
138) z( ^; M* q7 _2 Y, n- _, B7 n x
139
& ?8 f8 q% m3 [5 E" _: l140
$ S* s, X* c/ x1410 q. @$ Y- p2 \7 p1 R4 S/ p
142( f9 m8 j7 l8 C
143
# ]0 G, b" O$ q1 R2 R2 U% z1 a144. d; u) \; p% f
145; o" u$ x- l' W, V9 c1 x5 u# s
146
( ?7 o' C6 Q5 v, V. x9 z147
+ @6 I/ i8 Y6 \ m9 c& l, `148
; k- [3 ]; E" Q149
E0 R' M: b: q; q, k, E150
: p6 \8 V6 J/ w& i1 \4 v$ k1 n' _" B151, b3 m0 A5 R5 v# m
152
6 v3 G( z* q- [8 u) l( t153
: U/ n% n8 {5 E0 ^4 D, l154
( i; f5 V# C/ U5 ]& l& o1 h' J155
( l3 L9 p+ |; ^3 ^156
2 j( [5 }/ ~5 p9 f9 T157
; Z! g3 E* @) n1 W; P158% {$ T: p p6 t% X$ @2 V1 s5 O) ~
159$ l6 ~1 j1 e- q; C+ A6 [' t& A
160
+ G( A( z0 n" L ^+ H4 _161
( q/ z \9 w! z# t" d! r+ F162
# d+ b* m8 N: a' ?163+ I' R. a% A9 ?8 X
164" d9 G& u, r9 X9 ]9 z) ]0 i1 M+ P
165
; k$ i9 y$ R, z5 i166) G- u4 b5 s! u) K% m/ p
167
. ^$ \) r j( i" d" }/ h4 l168
; t t. e7 x4 t169! t2 L5 Z$ e1 ?0 t7 V! X6 M# t$ v
170
# N# L2 T1 V% w2 k5 ~. A171 @: z7 Y) _! X. V
172- i( c8 f; }: d9 G- n( m
173: t7 i4 J5 r! [8 C$ O0 y6 J
174
( N$ U$ O; w, s+ p175
P, E' z X& ~176
) K6 a& C0 }* b' M7 x177
3 `3 ^- L2 C P2 O/ e |. g+ C178; e# o5 Y& @: n# t, X' ~
179
5 o! }: Y; I2 {! Z" v2 N9 T8 Z1805 d- {9 o* d! j( ?7 L8 @0 W
1811 M% j6 o4 f: V+ |1 S
182
) q+ g& @) c' H' \+ X N$ E# Y183) z- j$ v; z/ S! L
1846 J* d4 {+ E& ~$ k; D
1855 R- z+ p) \* Z8 W$ \& s8 q
186
, r# R$ c+ L. }. r- x2 [! r+ ?% l5 _/ e# Q7 }187
! i$ O5 P" ?3 |, K$ {188) [) G; }+ N( `' S: T
1895 B3 q @% @4 z2 }7 |
190
" B4 K1 r& S0 k# F9 h# _1 N% v% `191/ z4 p, o q0 w2 H5 j0 X
192) ~1 |$ ]6 W/ L) j% s1 ~
193
; G: c; P6 h2 a194/ ~3 p3 y$ u7 i( T
1959 M% t5 q7 z7 X1 G* U W2 y
196: B1 U" z: N8 o1 U& J
197# C) A* w" {" |5 t' U, @
198
' n) I# a4 C0 p! |+ K, K/ E199" k' N! |: x4 _' G6 Z. [5 g
200
4 Q6 _1 d9 K0 y' q8 q/ M201' H) d- u$ @' @. G; V
202
: y* ]5 `, @/ w1 r5 {. T9 L总结: W3 Q |/ y5 B/ v
自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️: ~) |% ?6 S# m
& w6 \! q5 s+ B+ @' `9 U7 a) s+ [5 ?
demo演示
; X# C3 v& g. p+ o6 a) {2 ]8 Q后续的线上demo演示会放在
4 y+ c7 y8 g+ t' _! v! {) wdemo演示
- j1 i; m( ]) r' k完整代码会放在
9 `# n3 n; ~) z9 s个人主页
4 }! h$ s6 ^3 Q7 E/ X2 E8 L+ q; U4 U
希望对vue开发者有所帮助~
* ~# X0 r8 @) T) x9 B3 M3 `/ \) i2 B3 d3 y9 K; S
个人简介:承吾
, \! [. h. h+ J- W工作年限:5年前端
3 S- p( {: Z& H& ?4 B" x% O" K地区:上海; N8 n H6 H1 `0 z6 H; g! v
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
2 G& m% K% t) C' j; {- O/ N8 D8 [5 j. Z6 @6 p2 ?5 m; v+ d# q
. K9 s( B* p, n1 e
; `3 x! b1 g g/ x2 x# s& ~* u$ h* i+ x7 Z B B5 v; @; Y
————————————————
N1 {+ @0 `: _$ Q0 H版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。$ ?8 T* k0 I3 s# f5 T# ]8 |
原文链接:https://blog.csdn.net/weixin_42974827/article/details/1268318479 C1 g. ~. P( b; G* v3 ~
" Z: H- v2 y# a$ u. ^ M
4 g2 Z( e! ^) C3 d, l p; Y
|
zan
|