- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565163 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174772
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效& S- }# _. A& Y0 ?/ |' M! d
+ S+ t! l2 o! W( D前言1 N/ K4 `8 q" B# t
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:1 R4 o- W- [5 J x# I1 V
TypeError: Cannot read properties of undefined (reading '_c')& ?5 L. F. P, X
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:( e2 |$ s4 B5 B) a
# y3 i. y3 r: z2 Z) C1 \9 k
/ V! ]0 F1 y% G' r+ i5 b
思路6 x5 H: ]$ x3 r% u0 G
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。8 p9 \5 V) |, q+ F/ g
& Q2 u. q6 t( \6 i- X
文件目录
% [. N4 Z; ]% y$ `; k. d
. G! a9 N7 t) Q: c. K% d% [: g" f8 S( f1 _
使用示例
9 p. @' A& X- F1 b9 X; c<CountTo
4 d9 c$ h; G' b& y :start="0" // 从数字多少开始- j/ F) n. t& w& X' h% n1 y- k3 D
:end="endCount" // 到数字多少结束
6 N: ]6 z \6 N: H8 l- Q) p :autoPlay="true" // 自动播放# \7 _$ s% a+ G! t2 k) T8 Z0 {
:duration="3000" // 过渡时间! i0 f2 L1 n0 F& `3 k9 C
prefix="¥" // 前缀符号
1 L9 |/ _+ X2 b! e- J# H suffix="rmb" // 后缀符号4 r' D" ?0 w* G+ ?
/>
6 C$ y; \# ]9 t+ n$ [2 n j K' C1
9 y G7 C( X5 g* a6 X0 Q9 w3 Y2
# ^0 y2 l ?1 Q& J% Q+ `0 R3
1 D; s4 |% `9 f1 W7 k6 C4 k4
Z ?, k1 l$ k8 X3 U. Q9 ~7 a52 W+ {2 H5 U- _( H" ` k
6
9 y5 W! J5 R: D* b0 P& ~77 ~5 v! D5 R8 ^# |
8
6 x' f6 T* k0 Y! P/ q" i入口文件index.js
* G* {, R: w$ d3 V' Y+ h7 s1 u) n8 K: L, v
const UILib = {
) S2 p1 V: L' O5 r install(Vue) {
% [" k/ F9 q+ e @! l6 [3 f Vue.component('CountTo', CountTo)
Y1 Z4 q8 ?2 h* a7 Y; U }- { Y, m8 O P
}
$ _, `" h( v& o. `3 X* |$ b# v( y" E
- ~* Z8 l6 S& g- k* [0 ~, o5 Hexport default UILib
, T# B/ u" j; E3 n5 H9 o
+ d1 J( s: J9 p% i) k1& b3 ]& f' E% A
27 w. f* l; v; y4 r) {) P
3
9 D) U) m# s; p4 H4 h# ~1 z+ T4+ d' J1 G* z7 ?4 ~# @3 \( e! X
5
2 D: P" ^ z- F6
4 T) C8 J, t6 b6 X7; ~- ?8 b' z- d! Y
83 P9 w3 \% Z p1 t
9
2 a( E- U8 J% l& a& Z# omain.js使用% z' o! I# {* P; [4 k
import CountTo from './components/count-to/index';
' n2 l+ q# f: }app.use(CountTo)
, D! P6 r+ J9 J& C8 ^% |+ [1
- h Y. y8 v' X) t: D8 X4 _2$ b9 |3 B; Z1 H; D: c5 M2 f( U
requestAnimationFrame.js思路
4 [ M: V& w2 W. Q先判断是不是浏览器还是其他环境1 M; S9 b! p5 h! [9 ~
如果是浏览器判断浏览器内核类型
$ m8 W$ O( z- X5 ]如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器6 ]1 |% t+ P" s3 C$ F2 K
导出两个方法 requestAnimationFrame, cancelAnimationFrame
6 m5 p+ @: p; t( h各个浏览器前缀:let prefixes = 'webkit moz ms o'; B. }( m% ]# ?# f5 q
判断是不是浏览器:let isServe = typeof window == 'undefined';; U, \! ?/ a8 V( }/ P
增加各个浏览器前缀:
, Y5 {" c3 y! C, }let prefix;
1 D3 \! e7 n. u8 Ulet requestAnimationFrame;' A6 s/ x" l/ o6 U. ]9 Q+ ^
let cancelAnimationFrame;
$ Q& X8 m/ J% ^. S4 p// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式, a4 w" l" x/ S4 q% d
for (let i = 0; i < prefixes.length; i++) {
: X! q( N* j6 j! b, c# H5 E A f if (requestAnimationFrame && cancelAnimationFrame) { break }( O% P* N" K% u* s( E- B1 P
prefix = prefixes
) {* L9 @: u( z# d0 H. |5 d, ?; t requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
( T6 a3 f% `) u2 | N$ }+ I cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame'] V* u# {9 m9 R2 y9 k0 i% g
}
/ p, C: g. e, q, k7 u S1 Q! q7 D8 h$ q% _
//不支持使用setTimeout方式替换:模拟60帧的效果
: Y0 A, X8 F. A! ]; C7 O // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout8 J) i. R! X0 M1 L) O3 h
if (!requestAnimationFrame || !cancelAnimationFrame) {; A+ V. T2 Q4 C1 o
requestAnimationFrame = function (callback) {
8 @* C1 k+ o( E& ?+ v7 w const currTime = new Date().getTime()6 Y: b+ D' ?% z5 ? G
// 为了使setTimteout的尽可能的接近每秒60帧的效果
; E" \& D1 }3 I8 e! F const timeToCall = Math.max(0, 16 - (currTime - lastTime))
! y0 [- i5 v s const id = window.setTimeout(() => {$ f- Z2 F& |6 j( C
callback(currTime + timeToCall)- n7 F! p1 |3 m" E+ G% I! n+ p9 [
}, timeToCall)
' F( t, e# c/ L! q# V5 d* _ lastTime = currTime + timeToCall* J/ h l9 l2 A0 i# n
return id
3 r& R% b- i$ t6 r }
) X+ W: ~% b0 f7 v& O! }2 |9 v9 M
% [3 P5 @' E4 H" ?2 q6 |/ ? cancelAnimationFrame = function (id) {9 D4 L v8 q d1 k' S2 w; F! |
window.clearTimeout(id)
. r# t; @1 Y5 Q$ e' ^- X }; Z/ F- j9 q3 G" ?9 Y$ `
}
% Y0 ^: K5 n; Y6 r
! P( I4 `5 o( w8 {* G: i1! {6 [6 F' I' d2 Q& F) V8 u* W2 n
28 `4 R' }: A% r2 P
32 V; w: `$ B: p$ Z
42 @# k/ P0 a' H) d) y' I7 f
5
% X: c: ?. e9 p' h& Z/ M+ p6
; Q r7 c# B& ~0 a7
' N9 N$ ^9 o0 _# J; D, V: ?5 k8: D# [: T& p: d6 t6 ~& j& J) H
9
2 m/ K1 Z/ H1 \6 X/ d. X101 H5 ~8 n2 }+ O* j( v
11/ x2 r* e, `5 `# n! J/ ^
12$ S1 J& C h* Q: U
13
" |2 H9 J: ^; t$ z6 ]( U- R* B4 D14
9 A1 B$ p1 |" o( V# V v* J15
, [7 [7 t4 W% i: e/ y9 h16
! n9 E( `2 T3 h' p$ _/ C- ^+ \17
8 o% A) @3 L/ a7 }# u183 ?' s4 s* f5 Z; P& I7 R
194 A* A3 p+ ^3 L; D
20' v# ~4 ]$ H4 z& G3 }% O+ d
21
( F2 ~; p+ v4 I$ @+ r22; e* }' i* u! n7 Y6 ~
230 _# U7 U% ?, l2 }6 ~
24: t. u( X; q9 E7 ?7 @. k2 r0 L
25
; j+ _" Y- J1 Y6 D) ?9 s26) s1 @( l: K- i* I) I* N( S( b
27
. A0 m9 V& J, t7 w, a/ c28) A9 E* H) |3 y) O# k( i
294 I& I9 ~! _ U3 H! e% z; I
30% G2 M, O6 i! d$ ^: f
318 [/ y3 G+ M( S6 Z8 ]" B/ R
32
- ]4 n7 [0 u, ^8 U完整代码:
' g5 ^( O4 E5 A& j$ Y! `4 YrequestAnimationFrame.js
8 o* I! z7 g" G: f, @4 d5 v( O( V+ _ b+ l) ~; G
let lastTime = 0
0 W! F9 i0 `9 O9 n! j+ o% o8 @/ l" Mconst prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀4 Z2 o7 T; O# l1 w& c+ U
4 o' E* O5 `! q, f/ r A. I0 R
let requestAnimationFrame
* r' K4 a1 [8 f* m7 Z+ xlet cancelAnimationFrame
$ P# D' J( K6 b% m5 {- E; k" Y4 T
// 判断是否是服务器环境- [! n& e4 K, m9 f( q
const isServer = typeof window === 'undefined'9 g0 u1 Q3 o* U9 I' ]7 Z
if (isServer) {0 i( B3 p' C: C
requestAnimationFrame = function () {
( k" K5 e# N2 ~: h" H8 ` return6 m" R4 p+ C; ]% r
}
4 o9 N6 A* w5 ]- J3 W cancelAnimationFrame = function () {2 e4 k, V" [/ i9 k( {) w
return
$ V5 N* i( V# E8 C- f2 ? }
3 N1 B; |2 _2 V9 ]: m! ~! F6 H} else {
7 _1 N2 b+ @4 u, c, d2 h requestAnimationFrame = window.requestAnimationFrame4 V# K0 E$ s5 o U# Z. @! b5 M$ S6 ]
cancelAnimationFrame = window.cancelAnimationFrame
$ }' u2 H" X, O J3 j1 L V h let prefix$ |, E) M7 T; F
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
6 d! t2 i Y: c0 N for (let i = 0; i < prefixes.length; i++) {
5 e9 R+ C* n+ J; G( F if (requestAnimationFrame && cancelAnimationFrame) { break }$ }0 a& l& I, F' x, l- ?; b X# M
prefix = prefixes C# ^( X/ D D1 O3 D7 I3 l8 c
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
: n4 z9 y4 M9 t" E- h a5 K3 c5 L cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']$ {% r# F: @9 k* `0 C
}
* w# e$ \) F, S4 i" w+ S5 k+ L$ S1 U
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
9 r: _& Z2 G3 T% Z* d! c ^2 Q if (!requestAnimationFrame || !cancelAnimationFrame) {& m% _0 X8 x, }& `7 x
requestAnimationFrame = function (callback) {
/ R& D! r0 W0 u& Q const currTime = new Date().getTime()2 U$ K& {6 s9 p! D7 L, v8 L9 N+ U ^
// 为了使setTimteout的尽可能的接近每秒60帧的效果
! L' o+ O. e6 l$ O( C$ T% N const timeToCall = Math.max(0, 16 - (currTime - lastTime))$ o2 M9 {- T& Q2 Y* {2 s3 }7 w- U: v
const id = window.setTimeout(() => {
3 B% G6 {/ s" B callback(currTime + timeToCall)
7 a, F2 }5 m# r8 U+ E' Y( V }, timeToCall)
o e T1 C- S lastTime = currTime + timeToCall8 u5 v) H: J# ?
return id9 B7 x0 S( c; S: e; D, n/ ~! `
}
5 q6 J! |- a" }) M3 i: X$ x2 [8 |, O/ Z- B) O4 C% B' y3 H7 \1 }
cancelAnimationFrame = function (id) {
U# N: A3 F& s/ U7 } window.clearTimeout(id)3 D1 l: Y# W; C% n
} v* I* X4 ^2 i0 K9 @
}' U4 ^) }! b6 r2 }% [! }
}
. A7 n. X" l1 }5 K) f6 B1 O- g
/ @2 Q& r' Q# Y: l- X- i7 U; yexport { requestAnimationFrame, cancelAnimationFrame }
& J# R* M! E {* R, h5 B( h' [6 s* V9 \
' L. e9 m3 d. V1
0 T5 f' G- L' Q/ g# `2
7 x) W' F5 W/ E- p3
/ C! v1 f* H' y2 ~. _. ^5 _* j9 V8 i4
w2 }# P. l7 f* ]5) c- I5 ]9 a/ I0 \0 M0 `
63 T- H' C6 y' |0 n0 \# V, I/ b
7
( p9 [! z0 C' B% \3 \8( P3 @5 W4 J! M T
9
u2 N/ a% u7 [. T d$ V2 r: ^10& I, L$ s' u4 ]- {1 \. @9 W$ f, W! l
11; i% u% \ w% f* {2 E" c ^
12
* K7 ^( @, R& g5 w u+ X& n13
; R+ n6 ^- L+ T14
( h$ \7 F3 |. i: Y& ?$ p' B+ i0 X15* `; w/ S5 g+ s
16
$ ~$ C& \1 T7 l% z- E9 @7 W17" t+ d. L) a; t ]! g
180 a' B$ E1 [; e9 s& K) y9 @% ?
19
3 C3 L' Z) B) P20& V' W8 h6 |( y2 Z+ U9 a$ B/ Y
21
6 O( b- f) ]$ i% \7 ]22
+ f7 J# s% z! W4 a2 G: ]1 T23
1 t* `! {* Z [6 q9 ]24
8 u6 a* S+ p6 @# w25+ m( k. [4 z: ?: \3 x B* V
26
1 P" R4 f% r+ l3 S$ y1 I27
1 P: v2 h0 [. ~0 a" X28
0 Q2 {6 _* a+ A S: d4 I293 H& T9 b# S" g5 m' v) S) U% }
30. y/ @+ Q- q$ b/ A& F
316 t: I; A. t* z* n; R1 R. u
32
+ F& E$ t! J/ L. a9 L( \! P331 ], L' b7 z) z W# }% i! v
34
* W, i4 G- f! ~35
' M' Q+ k2 E. v' q6 {* Q36 @: l) _' ^& t9 p# j. L
37
$ s3 b6 X. e% @( @38
2 v! J& a( G" p, N, x39( ]) E0 R+ Z8 I4 z
40
; _, f& j- Q+ m6 T. q$ d" k414 r2 y$ ]& R8 j- {/ Y
42
+ D; A) D1 t0 Y- k/ N4 _9 b& p- s43
; h! G7 j+ x0 ~7 I44, Q% z0 v |# q
452 ]; P& N* z. a" \" }; X/ b
46
, q! V5 U \# v( s& J) E) K& R47
9 \8 g. l3 G. C$ A48
4 h T; {7 z% q/ K: eCountTo.vue组件思路! s2 L( y, g0 y9 y
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。* K1 w5 K6 c$ F- A+ k" E- U
4 A6 x1 U4 D! \2 Z引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'; s" V6 I' b$ Q& w% A6 H( \
1. ~5 R" D o7 G% Z9 Y$ O2 D
需要接受的参数:4 Q6 y- S+ F- _7 H# M% t! u$ ]
) B% D( E. V8 @const props = defineProps({2 _) Q3 C# s5 h) K+ L1 U, ?
start: {
7 O8 R: u; f9 j$ l* H! z type: Number,1 g% Y) ^; W% F
required: false,
g/ L. }# _% [) ]6 D' p default: 09 s5 s! d$ T' R( ]$ J. C
},- \* G7 K* Q- a0 v0 s
end: {
" J( d4 L+ U2 p# y' x$ e type: Number,
/ o* @- G; ^/ w; d6 x required: false,3 J" f$ A% } b/ j! ^) ^
default: 0
9 n& O9 R% X( X+ W+ Z* Z },( u& ^ n. h( \5 }9 v
duration: {3 x& @) l' H, `4 o i$ f( ~
type: Number,) T6 {6 s% h5 P) Q" F: ~( N6 M, ^) M
required: false,' ~4 a, I3 s+ j* V1 B; o! G
default: 5000
% v6 A# R0 c$ s# J( _. H8 Y },! ]# P+ @$ x6 I. j5 `
autoPlay: {2 v K9 A8 I/ ~
type: Boolean,
) I1 N" x" g% p, ~9 W9 `+ Z4 T required: false,7 @/ i; {0 H, K& U* j; _" R# U
default: true( R4 J4 t$ b/ z: g; t
},
6 i2 j2 c8 f5 Z0 {4 Z decimals: {
" u" x; s9 J: j5 w5 G/ P type: Number,
8 k" s2 Q$ M* j required: false," |( y' s4 x6 N9 n
default: 0,
3 v8 i! n7 F! O: w validator (value) {- V9 e, f4 H0 w; o
return value >= 01 o6 y0 M9 C# ?/ \
}5 Y# L2 T3 c* |( d$ r' i
},+ d7 I2 N! h ?7 s5 D0 ]5 X
decimal: {
5 I; }- z1 E ^( A1 i: |% ` type: String,
8 b5 V4 y. T, v9 D required: false,
! ]) [. O. F# r) E7 g- S default: '.'
. ^: c ?) x2 { },
9 K- `9 x) o) q$ Y. F9 e( M1 s# c6 T separator: {
2 {! U8 R( z: K! K( E' _8 l4 Z6 J$ k type: String,3 |! u: B ]! G* g% O$ `
required: false,( I9 C8 F$ X' f5 C
default: ','
3 v o4 W, ?! S, H6 d, t },) ~! Q( `: _, [# ~4 e; v
prefix: {
x- `; }4 \/ j! P type: String,! r8 o' X( D) m1 @; D/ V* o
required: false,$ {( W# A& k6 c4 z. S
default: ''0 G/ }( O; t/ E$ [: ^+ g' L2 p
},, K3 ^9 m- \- r$ @& I! r. u( u! x
suffix: {/ j+ f! q2 c( s9 k$ u# D8 W6 r
type: String,
: Y9 r* n- R5 z. n* n required: false,4 p4 P9 \. s/ B, V
default: ''
( N% B7 x1 A/ B },
; A% a, y1 I- L# v4 i useEasing: {
3 n8 {' T" o j/ Q type: Boolean,4 z' v3 Y$ d! S1 z/ T
required: false,) ^" Y& N c' _0 |
default: true7 F: K) j) g/ Z/ u
},2 [" p6 A! ]- ^' @' N `& O4 h
easingFn: {
4 q: T# u4 y, J7 Y, u/ K [# ~ type: Function,: r" m) y; l9 Y! E
default(t, b, c, d) {
! \. l, @! Y$ w3 L; h; k* ]$ k, y return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;7 j% Z7 d" N; V* s& X
}
+ {/ Z$ ~1 @+ v2 s D }
6 n! C" q1 `! J6 ]' p3 d})
H" z0 }# [/ n. r1 e& b; U, P2 ?, f- O4 ^! a' n0 @, Q) a
7 n! i2 W3 F! Q5 z* X
1
- ]9 S4 M, n7 M7 K6 f5 m) e2
7 ~, E l `) v v F) F: e/ }3; L, D' D5 Q1 A
4* R- K& G0 `, X' Q! B4 g
5
; K+ }7 ]1 W6 i+ {" H6" g1 A, Z, K" x1 e
77 }+ O k- A$ l% a' T
8
7 v' N, L; u9 @- g, r! x9 A- \# ~0 p0 x9 N8 |; Y8 O0 c
10
1 z+ _" k" r; D9 S11
! E, k2 g% q/ m2 K- q1 d2 ^12% R& e" H+ f, i9 q
13( i. a! }, D- q: T% K% F
14 J& H1 |% o! C% @5 E7 O' A
15
. K1 g" @8 g: F7 z- f( f, ?16
# a) \0 T. \6 k3 d( C, u6 x+ ^1 i" {5 i17; a' m4 d% j6 p. h' ?: p9 }& k8 j
18; z- M1 g, G+ a6 w8 `3 r" w
19! i5 v& f m$ q
20
|9 v/ K, V, Q* {. E9 Y8 C8 H# Y21
% W! Z7 c2 u: {22* J0 h, y# N& Q% u4 n) y
23
" v0 L) {: @$ n2 _5 k! }1 S2 Z242 U( \ t6 I) X7 y
25% T6 V0 G0 n9 {
26
* c$ r, _+ p1 A7 `0 U, J270 m) ? O# H% o3 i/ g
28$ I- P$ U( N" D- F; E9 E t D( r
29& J4 B. i1 L0 Y( n4 ?6 O
30+ P( ?4 ]; x- @2 p
31. m' k0 {: j, p4 m3 u6 c
32
/ L. V/ H, ^" U5 a2 F/ j( l33
/ V# N0 \8 h9 N( I) A& y X4 Y1 n34' Y& ?( m' c7 l! J
35
, Q; w8 d, y! y& M `36
3 z- h* H* {, I8 k8 G0 H `5 f37/ `3 L- q6 V& ^, a" N3 s" I' z6 N
38
8 |( Q/ T# z- v9 o4 _/ u+ Y& n7 b! g39' J( n' N2 k( ]9 R
40% C p+ c! n4 s/ A. f
41
# u' _; D+ i& t# |6 h" [, l) Q; `423 V( w4 Q3 K8 Z
43( f% I* J5 {# I. ~( H w
44
' A) T4 _! `3 I O( d3 }: Y1 N45! h* L. h1 ?0 A$ D( o& P
463 y7 T" c# q% x! M4 I
47# N2 s9 B9 P5 A) M, z8 T* {* L
488 T3 J8 g9 }5 t6 h' D7 I( M
49. B. \$ l- u! n! j% @" a6 }
50- c0 l0 `2 j9 {# c* O! [# |
51
, t+ L, d+ e" s* k3 S* W520 f+ {$ _ s9 ^3 u* ]) a
53
" M/ l p7 ?: R" f# `2 u54( ]9 e% N/ M; y( I
55, X7 c/ X& _: c E$ v
56- A! T* q+ v* w( E0 f4 F" g2 T
57
0 e' l' l5 N# h2 I% r# \) m2 w58+ A" n/ R# L8 C# |
598 H9 u2 z$ U9 z. I1 x6 C
60
9 ~% D4 @. d* U& k" @611 n7 S/ T* i, p6 r
62& {9 W s6 k, o$ m
启动数字动效7 @- B- Q" c' i4 c" E- C. G
; F, |* P. K2 q; Oconst startCount = () => {8 ~" L- H4 Z0 f0 w5 B
state.localStart = props.start. a( ~& A ^2 `+ \( e
state.startTime = null
$ S7 H" e. X8 m% T) U state.localDuration = props.duration
3 a1 e) W( a, ? r7 n state.paused = false. l6 h: W) H0 j" T+ H
state.rAF = requestAnimationFrame(count)* ]3 Z2 T& A$ E2 h
}1 x8 D6 P$ S. H: Y
1( Y" U9 B8 X8 n7 ^3 X, U; ?+ B
2
; e4 R) U/ ~1 E! E7 k! ~# V1 [, b3
* m0 K# p( l- ]4( J4 Q; N, S4 R7 q1 U6 N
5
9 w# l6 A7 c' Y6
" J$ K) b+ i5 d% Q* B; y' o5 s9 F1 ]72 G& ?7 K: ~ u4 o$ q
核心函数,对数字进行转动
6 M. e# e% U+ @; K8 B6 h0 ]+ p, y& w4 i( ~+ `1 s. a! ]' K, K
if (!state.startTime) state.startTime = timestamp$ {: I" n4 d0 t4 t% Q7 u6 H o. K) [
state.timestamp = timestamp
" |; d \4 o( {* s6 d7 i+ w const progress = timestamp - state.startTime( l3 a% E4 R w5 _, N
state.remaining = state.localDuration - progress
6 x: J! `* N/ V4 l, c // 是否使用速度变化曲线
# [! @$ N5 C7 V$ D R7 c if (props.useEasing) {9 i r) V. B& v5 t% m
if (stopCount.value) {" d2 z6 d6 d( Z- r. y$ d
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
9 v- f5 e7 z0 Q) C H x } else {
. u: s8 f* Q! H: L: B6 m) J state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
: Y1 {! Z" R9 v# J6 n# b }
3 j1 F7 a4 A6 H; e5 Z/ x9 \ } else {
( X/ q& h. i# P- x if (stopCount.value) {
3 m4 c& [7 k% c, h9 V state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
7 N( x! a$ F4 h } else {6 C8 c! L5 `1 d# X) ^
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)6 s \& `9 f- \; E2 J6 Z! T: T
}
& ]. F5 k8 w/ K; r' W! M }0 {0 ?; t/ M- c9 l @5 T
if (stopCount.value) {
% F3 e7 W& ]7 m+ F state.printVal = state.printVal < props.end ? props.end : state.printVal
- H- F8 _1 x( \$ O2 L } else {
6 L, P2 O$ B6 \' B9 [ state.printVal = state.printVal > props.end ? props.end : state.printVal8 F+ q2 X$ e" G; D- ~
}7 ~2 b- t" P6 b6 `& g" J
& j+ u9 n4 @% D* J
state.displayValue = formatNumber(state.printVal)
; x( b }, P, `. m, W if (progress < state.localDuration) {
; ?/ I1 \: W9 `" x) w state.rAF = requestAnimationFrame(count)7 p1 f: Z6 K6 R9 t4 }% u
} else {
, v8 k! U/ [. ~2 R2 d3 a emits('callback')
N7 w# b/ v# O4 _; e }. @" N5 x' \7 H% M, u: F" L% }
}+ Q6 }9 P: T' F/ j
# R4 v6 ~: M* @! C1 F
% s$ U& L \1 ]9 B// 格式化数据,返回想要展示的数据格式+ m0 X$ C/ ^7 v. R; T
const formatNumber = (val) => {# x K' U* y) C) L4 z" z0 u
val = val.toFixed(props.default)
7 v8 h' U: v& l+ A val += ''
. }. f# X$ p t const x = val.split('.')' T8 O, k* C3 J) b+ Q6 V* i, I
let x1 = x[0] @- N; y5 `! w
const x2 = x.length > 1 ? props.decimal + x[1] : ''
5 w/ r/ e, L( _- W$ q+ s+ J9 i const rgx = /(\d+)(\d{3})/
0 [$ J: j! Q+ o) b; a5 d0 z7 \( T if (props.separator && !isNumber(props.separator)) {; O+ ?* u5 \4 g- C
while (rgx.test(x1)) {
' i2 r/ A; q, b" P u8 ?3 l x1 = x1.replace(rgx, '$1' + props.separator + '$2')
6 e+ C/ I, @# k8 l }
0 \3 h$ p! V6 u1 D* ` }; M: \' c5 V3 {# D2 o3 t% N
return props.prefix + x1 + x2 + props.suffix
7 a( u! C0 {4 I}
. u/ |9 ~7 q$ X# P$ ]
% [( P, j9 p3 [0 v0 O. s0 E1/ K3 J1 s4 `, z8 G* A
2
5 A* Y* s- p- _& N3' I8 y8 x5 }8 v
4$ J8 R( @0 r7 Q* | n* |" ?; Y. i
5 s# ^6 m: v/ i5 m( H
6
) A3 ]" M! ^* ~; W( T- r7
8 z2 T5 \- i( N: `! n8/ p; l H+ j2 U% L7 Z" M
9& ] d/ M* E: e. b% w6 v! x# O
10. `9 L d- l' @: Z1 H
11
* v7 o, p4 a' P, F' u* F12
" h6 f% Q5 e$ g" S. t8 E2 g13
2 e0 H/ h" C7 @: v$ a& W14/ k7 X7 z: x; ]/ W+ g
15! |/ q, i, G/ _3 s
16
% ?) Q) g+ b6 h1 c: `' L17% S% {; v1 Q2 }+ E' l) ^& E
18
3 M, F0 m* Q& c0 ^# m19
/ e4 B0 z( U& N" K201 K7 @) c8 S9 v' e
21, X: H+ {7 u7 h! W
22
) c+ G' V7 l0 ~7 \, k23
# x3 t1 }/ }$ b6 V# s7 [# c; d241 t) M" v; C: P/ J/ G2 J
25! `5 o7 p- a2 B
26% s* j& e8 _2 f; c0 Q* o1 ~
27
7 }8 `, F' [! R3 [! F7 r28' h0 `' ~ h l8 T) d5 b
29
5 d9 a( B4 x8 o5 {3 f' P$ C30
6 i: C" S3 u: x& ^& q31
2 j0 O3 p: m% q* m W) z, t3 ]321 P S* A7 p$ z, V( v
33" V& `- c- p6 M; ?& \
347 ^; h4 q5 g8 N% E/ ?" a7 Y4 c _; J
35. v1 }3 l E: a" R) B8 s
36# E7 X" R1 B" T* {! d
37; i* w$ ~7 L( |' x2 e) m' c2 q
385 T7 f4 ?8 e8 w$ u. G9 X A/ H0 E
39
4 x$ F( r/ P; C$ n6 H: [8 o40
; `' K* M3 p/ p41" G) G* U$ K- t$ H
42/ P% D" { d+ }( }0 ^9 M: k" C
43; e, X4 f7 `1 k3 I4 w4 B( U0 k
447 S0 }( q* J+ D" ^+ r8 Z
45
S" P& }# Y: Z0 z; d' N# S7 M46
% V0 a" V! @ U. R7 B) c1 k1 X47* l; ~$ i0 s4 l9 _' Q7 e
48
* u l- S/ |: O4 x. w取消动效
$ T1 S& {" X+ X- W8 D6 a0 @" Z7 d. |1 U# o3 p: N' l
// 组件销毁时取消动画* }3 I/ ^# r% k8 N0 R% I/ `: U
onUnmounted(() => {$ K3 D& D* ^' f6 Q+ ~' v1 ]1 H2 m; n. R* z
cancelAnimationFrame(state.rAF)
" B! i& W( i; k' | ?})
( B- J/ n$ R6 Q0 c14 U4 y/ w, K% h& G$ _# Z5 l
24 E/ G' K: J$ x
32 z V' V: @* G; G
49 i! m; S6 N3 W
完整代码' K4 Z: B9 }8 m, E4 Y
* s2 J/ X# j/ }6 ~+ G% l H9 g- ?
<template>
& m2 N+ L( X) d @; \" t {{ state.displayValue }}
3 q# q p' E/ x7 h: r" a</template>) t8 ?- U' a) N" b4 t0 e% r/ ]. y/ ?" u
" n+ E( S% j; Y3 [3 P) V<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
: T! W) y5 ]1 }9 U" o! Gimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
: O5 r4 p; |' a1 s! o% U" Jimport { watch, computed } from 'vue';
6 i8 _, i8 l3 timport { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
( p T, @, X, b+ C% \4 a// 定义父组件传递的参数6 d8 \+ p" y; u0 l& i5 [! P
const props = defineProps({
" ?' W+ ?( X" H9 o5 ? start: {- k9 V9 |7 F2 m1 r7 a# `% ^# I
type: Number,
# I! o5 P3 g, A: P: g' I8 o3 Q0 F9 G' B required: false,
4 l& z/ H2 _0 s7 I2 K0 ^ default: 0
$ K4 t% a& C1 R# }/ ? },% u0 V T. E& ` q& T7 i1 `5 l
end: {
, M$ [) f5 D7 B/ F, ?0 z( x/ h- u type: Number,
8 k q% f! s+ y [: i# J! k- p required: false,
4 O m1 C* S: l8 B) ?; a default: 0
& K m: W" O, V! X( P$ R. L },) \+ n/ O: |5 f: N* T9 {8 i9 |& K
duration: {+ R/ ]! N7 K5 {& J& J
type: Number," E& s% \/ X9 ]) J8 |( E
required: false,
Z) N" J. I, `5 B4 S+ O, ^6 u3 } default: 5000
f' ^0 F2 ?% K9 ?% e) L4 j: K8 m# v8 J8 ` },) |% v8 o- L8 l \4 r# i+ M" R
autoPlay: {8 b2 h7 t: N4 a1 c. N
type: Boolean,9 R1 J* O5 i% ^3 |7 {" B
required: false,' P' D) `4 Z9 ^( x6 Z# W
default: true
* C3 m `- r8 x4 R },
3 d' M4 i3 Z y R7 L! ?9 m& ~ p decimals: {
; R& r9 g) r4 [ type: Number,
7 W7 U# I) ]8 h" G0 N required: false,
1 G' Z' M4 k+ h2 O8 _, ?( ` t default: 0,' y" i! q, h; x! ~
validator (value) {9 @ r0 P% C3 l+ q( ^
return value >= 0
$ s7 w1 q" Y& f; J }
# N3 |' D# k, A, M% ~0 K },3 Z7 z1 |, l" B* D) c$ l) i
decimal: {( v% J* j' i' V( T5 J. D. B& g
type: String,
$ ]4 [* k; ^; J( J* P9 d, l required: false,: I/ C* A2 k8 J# V
default: '.'. o) ~0 {+ a! ~$ c5 Y8 h& l
},2 @7 L" r5 F% ^" j( f5 W* L
separator: {+ N4 x, }3 j9 R: b' J5 I( ?
type: String,3 U- q5 K1 D/ N& v
required: false,
5 ~" ]* H; j. I default: ','
d' Y9 Y% d6 f3 | },
) ^; ?7 r. N. p$ f& u prefix: {
8 Q2 I% _# N6 M type: String,
7 B7 G* L( {0 l7 B required: false,/ D8 \- C) ?8 Y- A9 U
default: ''# k: g' V: s; O7 }9 ^% V
},' ~( G# F5 V( S, r- [" b
suffix: {& H2 b* x+ e" u- j. K$ w* h- V
type: String,! S; t% _0 X5 X, @% N/ w
required: false,
4 C9 \- ]$ `! f1 ] default: ''
) c6 u" x& V. ]3 F8 ` D },4 \3 v$ a( F. y
useEasing: {9 @' q+ A, O* b% |) R. c; U
type: Boolean,1 Z7 I/ k& P( ]1 s' y, {
required: false,9 N* W6 j# V K' r/ t9 P3 h
default: true
. d' Z% n3 b6 C( } },
- ]" J8 H0 J: @% Z easingFn: {
* j, q% D/ a/ A' v. K7 E type: Function," A+ a- o! M0 L8 t
default(t, b, c, d) {
/ D/ s3 ?/ t. h" E7 Q( W O5 Y return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
5 p v0 ~9 D+ ?# ? }
6 ]& f8 m( e" C! S }0 U; a) U6 U% Y+ H( K& n
})
, [ W B, j N% R; \: Q* H1 r! ]8 T1 u: a" i. A
const isNumber = (val) => {. P3 U+ L. g5 Z4 f2 B
return !isNaN(parseFloat(val))* X0 z) h% a- ~3 v+ n) H
}% z# E# Z/ Y. Q0 c: k5 G5 @
" f; ~7 C3 t; d. J% F4 G7 l/ C% [
// 格式化数据,返回想要展示的数据格式
( W$ B0 Z" i, }! Vconst formatNumber = (val) => {
+ Y1 i- c7 F! q# d- p, A9 ] val = val.toFixed(props.default)4 K/ s" E! @/ S/ x
val += ''$ v* a# C. \ o$ V0 W' U
const x = val.split('.')
$ v: ~# M/ @% }5 o! z& ^5 k: g# r let x1 = x[0]
7 G( @* e2 f! k6 @" z const x2 = x.length > 1 ? props.decimal + x[1] : ''
) B, L, C( g7 b1 W const rgx = /(\d+)(\d{3})/" _' M R: t1 E) Y; v. W& V
if (props.separator && !isNumber(props.separator)) {
- E, c; X. s8 l" w while (rgx.test(x1)) {
3 f3 M* f* Y$ P" E% E x1 = x1.replace(rgx, '$1' + props.separator + '$2')6 G' \9 z. z- A$ v' v
}
5 |) }8 i! K# _, E }
/ k8 O7 o$ ~6 `) H4 T: c I return props.prefix + x1 + x2 + props.suffix2 }; a( Q" Q5 m
}! E2 E ?! E$ V) m4 [
, l! F0 m G$ }' ^3 o// 相当于vue2中的data中所定义的变量部分5 ^2 B( g( [( \; [
const state = reactive({
1 j* @5 c. Z; ~* V* Z localStart: props.start,: Z8 l" u$ N& S& ?8 I5 b
displayValue: formatNumber(props.start),
\; G: V) Z. y( t! O" f printVal: null,; e3 C1 A+ T2 ]8 a
paused: false,0 f Y/ r3 v) q( u1 V6 ]- O
localDuration: props.duration,9 ^, v. o3 h9 t1 q
startTime: null,
7 c6 q2 H. e& E2 B3 Z# M0 O timestamp: null,
7 S) Z5 q; d% r5 ] remaining: null,
3 Z% R; o- u, Q4 a A rAF: null6 Y: n8 f! b; `- O
})
?4 H0 u0 j$ U3 O$ y8 n! J0 z: g6 Z& X! T
// 定义一个计算属性,当开始数字大于结束数字时返回true4 S2 ^& W! u) E" E% F
const stopCount = computed(() => {
6 k4 s( G. K$ ]* z0 e/ j F9 A* x return props.start > props.end/ @2 u! \& q' @; P
})$ o& P" t3 z) P& O+ V/ `9 c/ |" p
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
& E# ?- {3 |. A1 j. D% ]const emits = defineEmits(['onMountedcallback', 'callback'])' l/ G- n) l' S* @
+ [) r$ h* e) F
const startCount = () => {
# p" K3 k( e. G3 _) D; A/ L7 @& L state.localStart = props.start
/ V0 O9 ]( P0 E0 X! Q2 p state.startTime = null8 R" p! ?/ D" m
state.localDuration = props.duration' x C1 _" t3 c" D9 X5 a
state.paused = false
) N/ j7 P$ T* @( B$ \, `% G state.rAF = requestAnimationFrame(count)8 g2 l! R5 a8 m4 Q5 J. J- [
}% _: z- E$ I% v4 c/ E
3 M5 ^% u' Q0 @- A8 o2 qwatch(() => props.start, () => {
E7 T T. L1 t2 i; y5 L7 _ if (props.autoPlay) {+ g# m* y- a: c+ i
startCount()
$ F* \& U; ~% _1 ~/ l( S) \ }% ~! ]" f/ I% x! d( p0 y5 b" T
})/ k3 p& b6 }! V- x& d! f, \
6 E, A1 M. L- K [1 G# w( Y
watch(() => props.end, () => {
H. O. ]& y" K8 F8 {* k if (props.autoPlay) {
4 Y6 J! q- I( _6 H startCount()
) v( O* P; p+ d* i4 f }
6 F) U: D0 e+ F9 K, v+ K})/ t( n9 _9 L: V% R2 Z- ^( {7 N$ s
// dom挂在完成后执行一些操作+ j& k9 e8 _& F6 v& W0 Q7 n2 D8 o) J
onMounted(() => {6 g( r! h; g \2 U2 M" @
if (props.autoPlay) {$ J; `/ Z' w- l4 l# D* h3 Z1 w
startCount()
( B1 y( |9 Y& f$ F8 C7 g } q0 y- @+ ^: m, J
emits('onMountedcallback')
) f4 R O! w' ?( ^$ \4 f7 z})
% [: j: P0 S! b3 s// 暂停计数
8 J# Y5 w$ \$ econst pause = () => {2 D5 r1 B3 p& F& V9 D9 x& |
cancelAnimationFrame(state.rAF)/ \" z. k. e3 |" ?! N: z
}
+ b9 a, i) u+ V, g9 \// 恢复计数% q& g- W, C( P! I" \) U/ v
const resume = () => {
) R. L3 Y3 `& J9 n6 f7 T7 h" M state.startTime = null, N. ]# Y4 D7 W% V4 o$ s7 }3 E
state.localDuration = +state.remaining
5 B( v: i. C) k- d state.localStart = +state.printVal3 `. F9 e; C. a7 z
requestAnimationFrame(count)
b- l7 c8 T9 m) s+ Y1 T}
" Y! ]: ^; B" E: h
6 y2 S) d# x0 t! C( Dconst pauseResume = () => {
3 t5 p# Y, g* \; J- P& A if (state.paused) {( t- G1 e( r& q6 v, A t7 q
resume()! D" [" F2 T( @1 E( a, [- |
state.paused = false
$ `5 g$ ?2 H3 e" D# J } else {4 k- R% V# u( ^/ n2 _( h
pause() b/ j9 F; s( l) F# _' a! q
state.paused = true
4 o7 n I( _- L. i }
( E+ Q) E3 j1 y0 I" A* U}0 [/ l5 N" W: X, X* ~0 \2 F
' J* X4 _& j, v1 j1 u
const reset = () => {
# C9 l: E: o0 M a* {9 z state.startTime = null
7 Y# k+ ^4 \7 P; Y& u9 k! F cancelAnimationFrame(state.rAF)
5 D& t: j1 h! b* B state.displayValue = formatNumber(props.start)& j1 i: g# u) `2 D9 i1 o' l2 I
}
% E8 a; E5 x8 E* O# Q
/ L; W$ M7 C$ h- n/ s) k, R$ f' X& ]const count = (timestamp) => {7 A. M, C: M2 D6 L9 B' b
if (!state.startTime) state.startTime = timestamp% R' K" F& W3 T0 R8 m
state.timestamp = timestamp S1 h) Q! P6 F5 W
const progress = timestamp - state.startTime
6 G: _2 M6 o* ]9 `$ @* f state.remaining = state.localDuration - progress
* z' _* C, L4 K* w // 是否使用速度变化曲线
6 z# E" |. H8 W. v: M if (props.useEasing) {
* W" m5 g; A- r( r7 }0 P if (stopCount.value) {
2 ?7 s2 b8 [, a8 T* k( H state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)+ I' @- j( G! q7 l
} else {
9 d4 e6 @& [: ^% f8 k& D/ c; l state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)0 N9 [5 g! L7 S6 J
}/ e' r6 f* \8 M. ?# D( K6 Q5 @) R
} else {# A, ], H3 |% d0 w/ a% v
if (stopCount.value) {
0 m* Q5 | y: x$ t# G state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
6 Q8 o) c' Q# v, d1 s. Z3 o } else {( q0 b6 ?+ |7 p+ X% ^$ b6 ^
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
, b6 P$ X; \5 } ^1 p" I }
4 z: _; M3 W* `& U }) W V' c5 c+ j' V& N6 s# l
if (stopCount.value) {/ v" Q' Y+ V% s) {' c
state.printVal = state.printVal < props.end ? props.end : state.printVal
, {- Y) a6 y' A } else {
- [% E. ]4 W/ j; M. h$ g state.printVal = state.printVal > props.end ? props.end : state.printVal9 w' j, v3 a/ X x G$ p6 \
}3 y3 ^# P6 n9 E0 s* g( D
* k1 X. }5 E+ x8 J+ ` state.displayValue = formatNumber(state.printVal)
& }7 }" g5 O, O/ U( `' J" L if (progress < state.localDuration) {
8 J$ X" P& f! ]9 D! a( r' Z3 Q& V state.rAF = requestAnimationFrame(count). G. K$ w6 k! [" e
} else {
3 S5 A0 g/ E* M6 y$ D9 ? emits('callback')
4 `6 z2 H. w" F1 `0 a6 O }
! q; @0 d" m' Z2 _" Z! {. e}
, X4 Y5 n8 m+ x" h6 {+ x// 组件销毁时取消动画
$ j3 f! X% x1 q1 u0 Y3 l& f+ {, c/ XonUnmounted(() => {, f7 F" _5 o7 Q
cancelAnimationFrame(state.rAF); ~6 `3 T$ S+ d
})
$ n9 e" U3 o) {1 }, X</script>
* r& b' x2 A, O7 A; L
! W1 }' O- D( d* x10 Q: m* ]) {% A' S
2( Q) m2 N1 S5 F: i8 v, _
3
. q% A/ |) @$ }: V) F3 J4
$ m' |: q8 I$ {7 m5 Y6 D8 q5
' \+ q2 }) s7 H60 y3 z$ a( g1 s- s( J
7
: ^4 H" W# f l$ i& F. o8
) k& R+ z2 _$ Q, b+ V! D' {9
0 k m; k+ ?* r* d6 e0 {* y6 [10
/ g! k) {/ Q! y" \11% j4 i0 G( f( [0 P2 _" f5 r
125 L% c6 r1 ~ b
13
6 I2 [- P! u/ s- ~% Y( B; t14
5 \/ P4 Q/ ?% q [. J0 p+ O4 ~157 S1 T9 e- B; k- M0 ~$ |5 s
16
) l8 ?# N. \* L& M6 w E& B17
$ S! U' c: S. l, G3 b6 c18
, U. f4 R L3 q0 |# }5 \8 X a+ y19
4 E6 X) H3 h% e' C9 U$ h20$ I! s5 N/ r3 }! S) u I! c9 L* ?, [
21& V: H! |6 o, X8 `" B( _
22, Z+ [' U$ c: Q/ _" ?
23/ c" C* F" i* r" T
24
: b2 Y) [" D+ R4 u9 z1 H5 X# v25
1 f5 t6 g: y1 I8 E; K- N260 k- Q! Q( X7 ~, I
27; u; ], U9 `' T6 Z* i* n8 a% \
28
( M+ `3 a$ b- O) v+ Q: i29
" E1 q' S$ _; F30, M6 V# n0 O: a9 a7 e1 T
31; Q% K9 e5 W! {- `# F4 _& S
329 ^' ^" Y: J7 c3 ^" F' X1 ^
33" ?% J( t2 V2 h8 j
34. p6 |- A# }' n! ^# M6 o
35) ~9 `8 H) e5 w# n2 D7 E. ^
360 L: |8 N0 H& d% R0 V5 j
378 ?2 [) F% t% k" [
38
. \* k) s: J1 g% ?39
( S2 M) X, t8 a# L40! P2 a$ k3 a" w; F8 |: `0 v
41- l! F1 ~" x6 n: q2 b
42' R) O! r1 _3 b; X* l7 @$ ?
43
- c& B+ W9 u- p; n44
. F, b8 y; P: L) J, `7 t1 F452 q0 U+ ~1 M/ y& f
466 M0 p& Z8 w; B; G( m8 d; v) K- R A
47) Q6 z; o7 _3 m/ K( W# v
48
" L1 H1 S3 B, Q U' ]49
3 a. \0 [ e+ O( [50
* W# t0 G: v$ ^: {5 v L51' ]. e) ]8 |8 U: n# n
52
& O3 `# K) s: U# O) i; y h53+ V0 N8 ~ |: d2 W& `5 c
54, [" M( s7 `+ U! R& F m
55; T2 W5 v c8 V' Y4 T7 I
56" P8 k2 Y8 b9 N" e
57; a! {: c) ^% ]) H: O
58
9 P2 v/ w+ V$ m' f; ]& m5 c( i3 @4 h597 j0 v O+ e) t% C; n, C! y4 q
60# T0 y5 P# B1 v+ z8 `
613 r& S9 v+ v$ p% _$ q! {: f
626 {3 x- z8 {& u$ k) u* S
63
$ C5 I% j4 y: r64" K) B" C' x5 a
65
; D* z( [1 T" U/ k665 @, T U9 | D$ d
67
7 S+ n0 r9 y% A; \ ]5 ~+ z689 _3 N' p2 {4 x* p q
69
3 G" v# m. ?! Q) W" P a4 d70
! b9 [" O* a- d1 k4 q7 G8 r71
! Z8 i% M8 t# m5 ^5 i' [72
1 `' i9 Y T' W3 Z73( N- F* N! `/ \: p0 _% Z; ?
74
1 Q3 e8 g; A2 Z" I( R' |) b3 Q75( n# M2 \) i! m8 L6 k& j
76
3 [1 {5 N9 x# K1 I77
% `, r' {3 n9 U$ l% Z78
/ r2 |8 z3 X9 d799 b- `3 b( _! q# L
80
, f4 a6 N' T: o! `5 D81
$ I7 K, C; p/ N82
& i. `# h; F& w7 J839 f! R" I4 ~ j. D2 _- Z
84
% O' f! _4 m' u. @/ I; @85' G- P* J, [ }. d3 c
86+ [8 o4 C3 i7 O3 B7 d* j7 o7 G
872 P2 U: |+ X8 b) b5 J/ ^
88
# e, u; E: Z) J3 w! i% n89' Z9 |6 B3 R2 {3 `; Y
90" C2 w& ?1 C0 R7 I% Q
91
^- C' U! l* \; e X5 r92' c7 o0 d J- {8 t. h
936 G7 m0 b. o* e5 h% ^
945 h# M5 U% k n4 R
95
# f* E, @4 }9 g$ \! b. y) L4 g' ^ y96- D8 w+ V* Q0 r5 L& E
97
) q5 _8 J5 q8 v983 t) x7 |5 A y0 C( }
99
% v3 J# G( L6 @: u100! T! K. d/ c; j# w6 U& V! u# U, h( }$ D
101
$ H; A! Q; q5 X4 ]0 n102
0 a# Z4 b, b4 E) l9 p9 E103
$ [( m/ E+ e2 X1040 Z* Z s7 f! I/ R1 B& l
105
; ^0 T7 E3 k! C6 y3 b+ x# e4 n2 Z* S- n106
: Y9 w8 [/ P& G1 g1 D+ S107
( K/ i0 X" n5 E1088 F. N$ U' R7 D& u3 P
109
/ N+ D9 H C2 U5 p$ [5 R4 u110) }( ]( o- N% T# u
111. l1 d5 }& f+ Q$ E' h$ C( }
112
! b3 [% S1 p" [$ Q# R) f5 L113
A7 t- ?0 [" D; [5 _4 n$ Z114
[. z% J: a1 t" B. u- T115- z3 b# i& x8 Q e! C- E
116, e9 W5 L) L8 h8 t9 h$ [2 D; K
117% f* D C, f) ^: m
118+ ?( X' Z" M- {; b; d4 V
119# `$ S- s! S% f. e, }4 p+ W
120
. b; O8 G1 x" \8 a121( r! b- V7 G p
122 v, o+ E( a, @7 Z6 K) g
1232 W. _( u( A: q" l
124
% ^/ Q9 x) h4 ~* N/ g0 _4 C1259 m$ K9 {5 j* ~6 o( O
126
5 [ |3 ^4 n/ x$ |0 V3 W127
& ]2 N0 \$ H5 q: C* e F" R1280 x& O! r: g6 A) P
129
, k' b+ b* u4 m/ z, G% X" @; r- T1309 {; H* p3 D8 T% `
131
- w" k! r3 ]/ R2 M6 O A3 q2 Q132. o- B$ P) \, Y
133! m. |: ?* u: k b5 q. c& R
134# x9 s( t% U4 T
135& y! a+ q* w g3 Q' L g R( X* N g5 B
136" f- t( N7 K( D* p6 b
1377 r% q/ P% B, d& R* @. x3 K, E/ T
138
/ X- m2 r% c7 [139# I6 I1 h6 N* ], \6 v3 T2 G
1408 O# ~' a! l% S; } F
141/ S1 X* Z: j- b$ U$ x/ P
142- L& X0 S3 S# a
143
/ } {5 {% ^$ F8 b- s) N144/ a; b+ L8 x8 U3 |' m
145& A% d( p( W$ z5 M: E8 c' l. g- V
146
" F$ u0 }) I7 i1 i9 }2 T" R1479 M/ P9 a; c, {& U: k7 F4 w
148
) \. o5 C) Q- l% v+ }1 Y* ?# d149
2 {# i* i9 m$ R9 j0 w+ S% c150
- x2 |! \! s1 T; j151" E! N1 v+ y* L f, c$ e' k+ G- D
152( B W. N9 ]- n: X. e
153( O" r6 ?% t* a+ L q% s9 E
154* `) v9 n+ x4 Z, G7 ]# V5 M5 U
155
7 t j- I( J* _" G- ]156
5 A; n+ s# r1 u6 E1 A) O* [( G! }, ~157, q. }9 u/ V9 M$ o7 U
158
1 o f& t' G* i7 t7 [0 p* M159
6 H& _& A8 g i G: k4 B160& }+ F c, C" C: @: Q0 ]# j
1616 |! y( K1 [- d/ {+ [( J' w
162
3 R8 t& N; x- r163* ?+ t5 P* K$ O; I
164
: m" w N$ s% `4 I) z0 {2 n7 C1656 [, X1 A2 [8 I# G' M6 v# V
166: l# o2 s' H3 c A. U$ }" ~
167
- R; D2 o7 F$ F+ Z! O/ i' s1682 K( n/ S7 h7 ]# Z
169
, F, K' b F, } B170
9 _3 L: R$ M1 N171
. p3 P) @& k5 _, m0 q/ P172
( @6 z" Y B; P173
: U4 _( M6 i: Q! ~8 s174
- Q; I, u* f) @( v X: D175
- L1 W2 b! [- O9 p9 j0 v176
) H$ \" E6 z: f) q) O177$ I, r" h8 y5 b$ |$ }( }$ v
178
3 _* h! t; y) z179
, Z' G' j5 a, ^# z1807 P4 S% w8 P# Y1 p! F# I: s$ u; ?
1818 u+ P$ F/ b" R2 @. c
182
0 {2 p! B% R+ w6 a5 q183
9 z, t) k" w, y* k( o9 e7 G- }184
2 I5 c7 t8 w- l; j% h185, w' H) t8 S3 t& i5 Q) i
1860 \) w/ a* Z. h3 e' }) R9 G
187
5 D( T/ X. e, _188 \6 `- X4 K4 p0 E' q5 L
189, v! k) Q9 k# N. I! S3 ]
190
8 b& c* c" E* N# a" ?' H' R U191% q3 h7 Z* e+ c+ ]; f' v
192; u+ r( L8 g) Z' h
193
9 k8 g& q7 K i194
, i$ l3 A+ N# _% T6 y S$ U9 [+ F1954 e" ?: u }0 c1 @, _( R
1966 [. K+ ` \& `% g8 Y
197$ `7 Z% [, S9 Z2 I$ [( Z
198
7 H8 f/ i( t% }/ c8 D) ]* s# {1996 S# ^% v/ h; }
200- J, H f X2 |# i( }# A
2019 f" m; ^/ h* P/ X* a. ?
202
6 G# i) G' _! r. K, \总结
: I7 K: W! G; R# k1 b7 V# r" ]6 C自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️! n- W. j4 | T. s& R+ a. b0 r
% ^: @" n4 _( t' d" p
demo演示7 A0 w9 g# F2 _
后续的线上demo演示会放在
' U$ T; J2 d( e* l0 J1 _demo演示
3 x* W3 i6 E0 \: u$ D& M! K完整代码会放在
7 x- [7 y; a; j3 u' P; ]- w) Z7 f: S个人主页; m6 J2 Z& ~; l! y9 M6 v* U/ ]
3 ?6 r9 e! H$ X% U" @) A
希望对vue开发者有所帮助~) M4 ]/ @ Y) ?( a
0 F1 m9 s! u5 Y" y9 Y) w8 }# w z个人简介:承吾3 R) a6 ~) U! {/ ?1 d
工作年限:5年前端
& F7 M& B/ U) \/ \. [/ F0 s1 @5 L地区:上海
5 q; x& Z" f7 K$ u, U个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
1 m5 P/ ~8 r- h$ D
1 d1 ^4 h R1 v" Q/ Y2 y8 {( c* M! v- _2 [6 S; I
6 q% ]$ v Y/ n, @, x- R* I
" Q. |' q" x% O( J) n7 x————————————————" b% C( s. q% i4 Y
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。) D6 ~0 {9 a% _0 }6 s! E. Q, w/ R
原文链接:https://blog.csdn.net/weixin_42974827/article/details/1268318475 S6 A7 [% p0 ~ e4 `1 t( ^9 h+ C1 C
) [+ \ O# l$ Q! f5 ~0 q5 h; y
; g$ `4 N" A' y
|
zan
|