- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 558277 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 172856
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效: N4 P7 ?. c. V! r [6 q+ \5 ?
* a6 j. C+ j& S+ B. z- a1 U, `前言
8 K; ?) h! |+ ]; Y$ c: D9 w8 [0 {9 bvue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
1 U& H" B( k1 [# o% p! t2 bTypeError: Cannot read properties of undefined (reading '_c') j! M+ p2 _) N% L9 Z6 P
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图: o' z# i7 x! p6 f" F
% J$ h" ]( V) a, z9 K& f# Q: W5 s! i2 H( R) @- f0 K8 a/ t
思路9 Q( {! b$ Z8 U0 a
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
! M0 Q" H# w* ?0 F- N
2 ]0 \! g8 x4 r; Z文件目录: v4 o% R4 u0 a% _/ }5 U
& W8 V w+ Q$ k4 O- @: S7 A
" E; p6 _( Y* x1 j( U% z' z: Y使用示例
4 U, z( Z5 v+ ?& g* R, u<CountTo
) A% y- C b& q( F R5 Y :start="0" // 从数字多少开始
7 ^7 z4 @$ h: m1 @; P :end="endCount" // 到数字多少结束
+ s* `. p) o" G' s; |6 t :autoPlay="true" // 自动播放
$ z1 J& E7 C" [% w) B9 ` :duration="3000" // 过渡时间
' {0 d$ M6 u: D2 Q* C4 t9 j prefix="¥" // 前缀符号) M' l) R1 D1 N
suffix="rmb" // 后缀符号. M$ @( S# l0 t, Q& m4 _
/>) j8 o# O( r8 Y6 M' ^
1
1 {8 }3 j# _& D: `% }, g# r2/ i! O- }* q/ n o, `
3" L5 h3 e% \" F* } C( P
4* z/ q+ ]- s) D& [
5& t4 Q U6 Q, O# d7 }
69 T9 w1 q& R7 r( |. V+ ^0 H6 v2 E
7
; ^9 D m5 W9 d, Z: W8
4 \; n* [' W) h+ E9 h% g入口文件index.js
; b$ A8 Q( i3 O ^' G( a. a* B' O# N8 B J
const UILib = { G8 D: ?( t# J) A; }+ O
install(Vue) {2 Q; p2 f2 ~& B# O3 }! b( b' I
Vue.component('CountTo', CountTo)
1 } T2 {5 z4 I0 K }# Q0 ^- i( {, D3 g. X. J
}( O8 F, D }* X( f' y
9 j0 x( F/ p) ?$ {export default UILib8 o% p. d* d4 {& J4 u
5 P( j' U$ ^" [, |2 G6 \, V19 s% e( o* H: G$ \4 b! y
2: h; a. a# G* {. o4 u5 H% g$ V" n
3
/ A) u: S" Z5 z6 F3 q; a3 w5 r. b4
; z, l9 _: u3 r; u5
1 N5 u, y3 L5 k0 k) g6
8 c1 x$ }0 O7 e% W7 D7
' _/ f5 F1 z* N5 P) r: n80 q1 m- g* [4 ~0 o7 U: T. N; V
9
0 X6 U% u' f- g0 nmain.js使用
9 x6 G, z/ W1 a/ vimport CountTo from './components/count-to/index';, o e0 R/ Q& C5 Z
app.use(CountTo)2 Z& v2 F r' f6 D+ s1 K+ \
19 ]" @& t; y' }. c
20 B6 e& H/ D T# R, j) v
requestAnimationFrame.js思路( X8 w* @5 C; [( R- i
先判断是不是浏览器还是其他环境* H1 g: w$ F9 }9 w
如果是浏览器判断浏览器内核类型$ Z3 v5 r3 ?# c/ m, S* D, e4 \
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器
C# e' }9 j4 {导出两个方法 requestAnimationFrame, cancelAnimationFrame
( ]" \: g3 @8 S5 G各个浏览器前缀:let prefixes = 'webkit moz ms o';& |$ r3 }3 l, x7 ^
判断是不是浏览器:let isServe = typeof window == 'undefined';
( w& ^# h8 b6 h% a+ D/ L* }0 F增加各个浏览器前缀: $ [' ]: q% B& e. O% u& _
let prefix;
/ D! Y8 I9 W1 U& O! Elet requestAnimationFrame;
) Q$ u" W3 a2 E3 g- P. ?8 {2 @9 K: I# |let cancelAnimationFrame;
6 R; t" b, `. v! T" _ R6 l// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式" T, K! a, c" Y; [ B( \& s7 S
for (let i = 0; i < prefixes.length; i++) {
7 N+ O$ ]% S# ^5 C5 Y/ P if (requestAnimationFrame && cancelAnimationFrame) { break }
. g7 @, {/ S. v. ] prefix = prefixes
8 [( a. z1 n. U* i) {' T* ]* r# o7 { requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
* S( F( K& d% Z2 J" T2 G8 q cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']0 l+ H9 {6 `% I, W; k
}& p$ D4 G$ ?* ?3 o. n# n
+ @+ }$ A% x% {
//不支持使用setTimeout方式替换:模拟60帧的效果
0 u* @3 C4 R. V5 y$ s+ S+ w // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout; T# o9 ?2 ?7 l8 X. }! _% Z
if (!requestAnimationFrame || !cancelAnimationFrame) {
/ ~ U/ O6 V9 ` requestAnimationFrame = function (callback) {! {' R! t% f& ^
const currTime = new Date().getTime()
( z; u8 _% i( j5 r9 s: M // 为了使setTimteout的尽可能的接近每秒60帧的效果1 m5 O- G' C: |4 L: N% o
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
2 N9 c6 x# a( [$ v5 `8 M) K const id = window.setTimeout(() => {4 ]1 [& A+ r$ K+ T% E
callback(currTime + timeToCall)
) u; A. G1 x9 X6 S3 [, b }, timeToCall)+ h, M; y+ S( c- W& c2 |4 y& m
lastTime = currTime + timeToCall% | R' W) h7 [9 Y
return id
0 G) `: n5 d9 T3 {3 i& Y }
1 Q8 M7 r. x' S. a6 L* d, c( G2 G5 n- }: g1 \8 A
cancelAnimationFrame = function (id) {
0 N5 k& Z) Z4 |$ s) ` f window.clearTimeout(id)
5 E0 i9 m! U/ B' ]% q* p }
( b8 m1 @8 t; \0 o }
1 n4 `: m5 p$ x$ h! H& _
' j: m/ |3 J; e1 O10 H7 E8 B, ?6 r6 B
24 z6 M5 C/ I$ V7 i. r3 r! b
3/ {" |5 M/ |4 x4 y$ L9 l
4: v5 ~0 U: q1 r/ x
5
. r% }/ g$ L1 J6# d4 I9 H+ w1 ]8 T' }8 H
7
$ `8 p, u# Y4 @8
( y. a3 g; {7 n* ]' N' x# ^98 f0 o) r/ O. t% f( @3 v) w2 h
10
+ k9 ~7 n+ S# G9 n112 k! i) o U% |: E8 y; R3 ]
128 N9 ~5 Z' E( v1 R8 K% N, C
130 P! D; N! c9 T8 D$ b4 a/ K1 \
14' @' E1 l K- U
15
8 _! J. E# H) u- B4 B% D; ]. |16) [# l) o# U0 ]! d$ C% Y: I
173 E, W( A$ o1 T7 F. I; I
18
5 B5 N. G* y. Z/ V. ` g6 K19
& e% I$ R4 Z( v: V9 n9 f205 r2 G: U$ S) q! |1 ]
21& Q' q: B$ M& Y- C$ x: f8 U: x
224 e" D# a) n0 {) L' i0 @' k# {
23
6 l( p2 b/ O% L; H, A, p2 N0 U240 {- }! Y% F0 @
25$ Z4 d; i; e7 U# o. w- v
26; i) e# n2 T- Q
27& {. Y. U1 {+ i" z
286 R+ e, `0 N2 `0 c4 w. z0 _
29: z+ @+ S; W5 D8 p4 A+ ~; Z* e
30
& Y4 u @/ w, G& v( y31
2 J4 [% v3 o9 g0 P5 U( G32
/ {$ N. B3 p* i% B9 f T; P完整代码:
* T% k( T- F1 U6 J/ b5 SrequestAnimationFrame.js2 G- A9 T- w7 A8 ^: Z9 D
4 L7 G" Y% K1 K; K- `; mlet lastTime = 0
1 @* J2 M2 H( ?. i1 J$ `, N9 _0 ^const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
! ^( H' {' }) L" \8 c+ y7 `2 G/ E2 c4 K. F* @
let requestAnimationFrame" o( J) y; R* G9 O9 S) @. ^3 V2 A
let cancelAnimationFrame* E, N0 E5 {% [ B% G+ ?
9 V4 p1 L6 m4 i// 判断是否是服务器环境
1 [: o6 {2 e3 q$ I Econst isServer = typeof window === 'undefined'7 w3 j j+ n2 t2 M. A
if (isServer) {
- D% e2 B$ e5 S& X$ j( L6 b- x4 R requestAnimationFrame = function () {
& \) i% f, F6 U! V" G# T5 D) f5 ? return& d( E7 s( @( k( v5 |' q
}
& t9 o" h3 G2 w cancelAnimationFrame = function () {+ U; B+ E$ ?/ P& t4 f
return
' M9 O' N. @0 K' t1 z/ k3 `' d+ q }
9 h# p( s, B* L' V1 L0 F6 u} else {
5 I( T$ ] y" m' i- ]9 @& Y requestAnimationFrame = window.requestAnimationFrame; {1 z, Y. X& C F
cancelAnimationFrame = window.cancelAnimationFrame
' R' M; G0 l: O let prefix
: ^ _3 M/ w4 I5 ` // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
% [- `9 O+ L2 g. H for (let i = 0; i < prefixes.length; i++) {
" [# e1 Z9 i7 Y% S. x if (requestAnimationFrame && cancelAnimationFrame) { break }
% t$ }( j5 ~4 _ prefix = prefixes
% z' N: Y- p% Q3 F ~# K, i requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
+ b# l% b) Y {9 ]4 K9 S- r cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
4 b9 g( E5 x" q6 v4 j* W }* Z; u0 E% d) a
5 w2 N7 u( q% d- W6 c+ z // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
[& I! \; q& \# I/ E! }$ Q if (!requestAnimationFrame || !cancelAnimationFrame) {/ n# G+ _: @/ ~9 M2 [2 I7 A! t
requestAnimationFrame = function (callback) {6 ~: y9 J4 [' g& I- `- `
const currTime = new Date().getTime()
) l# J/ @) W0 l3 j4 c" K8 h- _ // 为了使setTimteout的尽可能的接近每秒60帧的效果2 [; S- G# E9 ~
const timeToCall = Math.max(0, 16 - (currTime - lastTime))/ ], Q. O: l/ y/ V1 ?8 ~! N7 x$ [
const id = window.setTimeout(() => {4 y( p; D [' j9 t ~7 Q7 d( v
callback(currTime + timeToCall)
; c" P" S: i; ]$ e }, timeToCall) H2 y/ ]$ a& p3 B2 |4 d* X
lastTime = currTime + timeToCall! h/ ^+ [& O# H6 x& r
return id x5 M# }$ r7 @' f
}! {0 ?5 B( F! ~1 ^' g. I
( S/ }) [! r; j0 p) p) k
cancelAnimationFrame = function (id) {% p5 n3 r( R& Y6 H+ [
window.clearTimeout(id), p" Q6 h4 E6 G
}3 M5 q% s5 A! q. N" |7 A; d6 R
}
, r$ N2 I+ q2 m$ e}
2 V5 T! l- B) f" s7 q3 ?2 }/ D t: ?0 J
export { requestAnimationFrame, cancelAnimationFrame }
" m- U' E; H* n/ Q( I9 X. V# e7 C- ^9 P$ w1 J- b7 E0 h
+ C% Q+ R# m, j: E- v0 ?10 D) D# ^! }7 K, `% K4 s/ d
2$ h0 U/ b+ ~% _# T% ^% I
34 m" s! F- z, A
4
8 d4 ^/ \" R! V6 H; p! w55 E: m$ m' K w# n
6$ F! N/ L$ } ?9 r+ f, K+ G( m2 u
7
) f; T9 s4 Z& C/ }1 U- n8
/ Q" k# H5 L. B8 T9 }& R* T1 g0 ^9! M* O& E8 `: Z/ J; B% U3 b6 p
10
# C5 |" T# n, A8 O11
# A2 U- g, |! B; R12
! c# W+ F9 Y! g* G% u# Z( s* y131 K! |+ M* n- I, t6 T
140 Y$ C8 C8 o! I2 e5 ]
156 W) m' S; W. P+ y R; i5 q9 H
164 f. y: U* ]; P9 }- w$ N
17% U; J/ S$ B$ x0 r- k9 c" C
189 J: _; d; V; l6 x7 F
19
! J& P2 C4 x7 r! |9 k20
0 z. i4 D o8 l8 y. C' [+ }* _( ]215 G5 G# j. ^- I" ` \0 Q; {, h' |: j. y
22
" I6 z, G$ t9 [* F; v( {0 W23
# V6 d( s/ ~+ `$ F& z24) {! P; M& ^1 G* C! N4 b2 U' F M
25
; ~0 V: c% o6 l- m! n9 a2 Q; R$ J26
1 U3 X6 T8 }) V2 `& N' S3 P27
3 i2 Z+ w; K+ ~$ c3 @1 G28
6 \; w* ]; Z0 P% [6 i8 w29
6 O+ h5 h$ w: m0 k30
1 i* R# E( L' z1 k4 m. u31
P) g' f# {) J/ T% t# G" Q$ J32
7 |- x3 X3 f# X! | T) j) A33" s' h5 _; t# ^1 r7 S7 ~. h
34
2 R4 k4 @: X( O35
$ t c/ a* `3 `- z36$ g6 Z/ ?+ K& H% | e- s0 }
373 j7 g6 {( l9 X
38
; H4 u1 _' w7 l* @39/ k4 \0 f" K2 Q' `( `9 I& n
40
3 S) K$ s8 o* ?4 d7 ]2 z410 o3 i6 V- ~: K% A+ k/ u# {
42, Z! H7 X" e4 m
43
/ f1 g- R" n! c; y. G3 m- H44* A& N0 M! B; Q7 n: x" n
457 d, Y* U1 e! k5 A* Z
46
6 G! G- s$ o5 B) P7 x$ Q, S' I8 S47
- f, R7 f; K6 Z1 D5 {, _488 I$ `: V; _7 |0 [6 N
CountTo.vue组件思路- R* M/ _8 P+ N; E: o
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
! m. N2 _1 U1 I* Y* _* P4 S1 E* B( c" r, o/ t5 r4 C0 z
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'& A4 W! V# C7 w- u
1
8 ]$ k2 b: Z% R3 a* i5 O需要接受的参数:- A7 J* z1 s9 |0 Q" C ?- D# d2 J
$ X( o% j! t: E" {0 I3 j7 w ~" y3 z
const props = defineProps({/ J) Y$ B4 w0 _
start: {) s) N5 v- f. Y
type: Number,
3 z9 v, a' ~# D- v! I. L required: false,5 D1 l2 Y$ E2 V9 w; H. R
default: 03 a, q9 }0 g0 E: V: Y
},2 c5 T+ i1 ?$ |' y2 Y. n0 m4 ~
end: {* Z# d% ?: Y% g
type: Number,4 @# B" v5 g2 j. h- k
required: false,4 X, a* j3 R4 m% {) g' z
default: 0
6 J" f7 V3 l3 B: }1 R+ [ F% d },$ P/ J7 c* m) R- x
duration: {
5 z9 N6 ^9 v9 f% }4 s; r6 _ type: Number,! n# N: P; ~& v6 o' W1 \( T) l
required: false,7 S% e2 f Y& T+ y& S. w) `4 h
default: 50008 S$ ~% x3 J8 Q% s
},* u: D7 _4 {; Y8 C# R( S9 g
autoPlay: {
! c& M/ b) x" y type: Boolean,
/ s- D/ P3 e# k0 |5 H required: false,
- ?+ W' a8 l' p7 b$ } default: true7 }3 x/ `3 K3 M4 m* a* N4 c9 c* d1 E6 L
},5 c" g7 i, F3 ], O
decimals: {
% z3 ?5 V5 e0 O/ s3 { type: Number,5 T5 O5 C8 t* Q$ J* q: P0 T
required: false,
0 [2 y" ?7 M+ ?) n default: 0,
^* G% C9 I0 Z) P' B validator (value) {
6 I* R5 x% T' t/ F5 S5 T8 W return value >= 01 h! b0 W! B8 m; j
}, i4 b4 ?' h' D: s. I
},: d& ]/ |, b8 L; v4 V, ?/ {1 f
decimal: {
" z' P( `& s3 [( n, M/ z type: String,6 P5 G$ K) g6 f7 Z3 C8 i
required: false,
7 p+ ~- t# Y5 Q, F+ [" T default: '.'
- F1 ?, `; G' k& U7 e' o# V# ? },9 x& I' n8 N6 \
separator: {
! z4 g, {. ]( d( S% h0 z: `# k type: String,: V [. V! O/ y
required: false,
" n7 L( u _9 W& v$ c8 ^# K2 I7 | default: ','
- ~3 G( `9 `) ^; P7 _ },7 f! w4 M7 ]1 w2 K& |; h* t
prefix: {8 m: r4 L; I2 f3 F' W) j% n
type: String,
' y7 q( y6 l. k5 V4 B required: false,$ r" W- E6 ?' `/ [, t) Q' P
default: ''
2 o& @7 }" s9 @3 q+ P },
1 i5 @% t6 ~" E: p- C# p suffix: {
4 R: G5 o' q) u! Y# L type: String,
% T$ \# N+ _/ c% z& ?' Z required: false,& C' J* y# ?" `" _9 V2 m
default: ''
( F6 @0 [6 A' L$ f& {" M; H# j+ m },
' e8 I& |: A9 g' P: E useEasing: {: y, T, ^8 F- G# t% A
type: Boolean,
2 g( E% j5 A1 h8 E5 A0 G F! ~4 U required: false,
1 ?- b" L7 V3 A default: true
$ q& i+ C0 n H },
5 r% Y* M/ K+ R+ o% R easingFn: {
/ |! ]9 u& T: K" X* R8 E# x# e* v" h1 l+ y4 s type: Function," i! {2 T4 Y3 R- E* Q9 q
default(t, b, c, d) {
3 ~* t+ `' C$ D! Q( s6 j return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;0 S; M6 D3 R/ r2 Z1 I# y
}
! t5 q; {) h. T }2 N# b( \# \% x% f
})5 @* _8 F) I5 M8 {
& Z4 l8 d$ @4 k$ E
: W, O" d7 A3 F3 H16 A& t; B+ Q1 M m. m* J
2
+ @1 {% i2 D; V- V& p9 v- _3
+ F' ]5 J3 z$ U5 d+ a4) o6 b! O) F2 `# I0 z" N/ }( w
5
) X# f \& p2 j' o; V; y# N6
3 C, G8 J1 G7 D6 ^. B( M7
- Q% _. ?! {. R& i4 G3 Y2 O8
. @( N6 [5 W0 Q) [& G9 V" |9' \" _% m; d# ? n
10$ n7 J* I9 ]; W1 E& t G
11
% w F+ \2 q2 ^' p" W/ r/ A8 r12
2 R1 C, p u# Q; y" r139 E$ p5 s8 |. y- H6 V
14+ O" {; I4 I4 s" m4 A5 V
15
/ i) `: {" e1 o$ _7 ^- ]. N# C( S" b1 U160 m: K0 }" J6 X3 r
17
+ h J. I: [) ?/ s+ V18$ {3 @! v4 [- s! R. ?
19
$ V& M* t+ {& e" f$ [; n& C1 D8 y) ~20" L4 Y, V& u1 L
21: \8 I. Z2 |- S2 W! u- ]
22
4 t; j" `) l9 b2 h23+ K0 \+ Q" X6 b% H, x0 n" j
24% y6 L; ^+ f! o1 @: K# j! \
252 o. n/ n( d P$ O' t: V, D, t
26
. _+ w. l4 U& Y6 f2 B277 z; f: p3 k( I; y
28& F. j f1 @+ e
29
/ e& Y3 s, m4 L, L" g& a308 e9 `" w1 A/ X9 r
31# N$ u. b5 T4 s7 y% Z K
32/ L9 I' l4 i6 ?7 ~( E9 L
33
6 `0 L9 g$ W8 a% w345 j1 x+ }5 L7 }8 ~4 {
35
. w: \5 r' k, N0 C5 ]' R36
. A6 A# d( [7 n0 s37* O1 ]8 z* x7 T' @6 U+ C. N
38; [! ~( C' r2 ^6 H
39
+ f( r' x- m# J( X2 `3 _) S40! U9 \! C2 Q4 s
41
7 n" u. e l' R. g426 p) ^5 u- o2 j* q7 Y8 o
43) a& w! \3 e# ]8 g6 T& b/ {& L
44
; p+ g1 ~5 F) E) X* H; ^2 @452 e# T: H# q3 q8 {: q$ ?
46% Z( W: m; O3 }' ^$ X5 W6 d
47! h1 t3 H2 H' y
48+ k; W0 L7 ]* `" p" _. D0 ]
49' b9 l' J0 {/ C9 |
50" M8 k$ d8 Q1 k- t- ?! h
51! O, {- z- I/ d& Z* E% Z
52
( \! y( h; o/ [8 H: y53$ u w* h- b' U/ L6 q0 m! S
54" c' [0 v4 k5 o1 E# L/ S) r( H3 j
55
/ a1 O" G' s7 k7 ?56
8 c7 u* x; M' N. D( I571 J- |7 R4 S+ ]7 b. y3 E* o
58
1 d& j7 @: }0 l! I) S59) N. A& X8 K/ Z% N
60
5 q4 F4 \# t7 N c" r61' N" A6 q9 [, ~9 {
62
. \$ w6 S8 s) _& [启动数字动效+ J: j8 [4 |- `- e1 Z
! G9 g( N! D2 J6 c( C4 @
const startCount = () => {
' ^& ~$ |. g6 m: Q% W state.localStart = props.start& M: Q2 g/ u, H8 o! G
state.startTime = null1 e i* S1 d o
state.localDuration = props.duration4 ^, w3 k7 Q8 G! F) C
state.paused = false' \# X0 u& y1 I: _! P! |, {/ C+ A
state.rAF = requestAnimationFrame(count)
+ y; i9 I6 J+ N! U% o}0 {* }) P6 G( A; c
15 Z3 g: N' [2 K. E9 j1 E, k7 ]
2 Z: K1 s4 {# N
3
; R( k9 `6 w8 P; Q- R4/ o& n D$ p# d* y! Z
59 G; C: z2 p ]
6
( L5 W8 s% q& L' D+ ^7
5 f9 T8 W3 l; B0 N! `$ `+ p/ \核心函数,对数字进行转动
0 R: m4 C8 o' @! K+ B5 o( h* D4 G6 _# j" U
if (!state.startTime) state.startTime = timestamp# e) q) G# h+ D. Y) I- B
state.timestamp = timestamp
W: t) J+ C0 g3 L+ F; T4 i const progress = timestamp - state.startTime; ?" f, d7 K2 }. _
state.remaining = state.localDuration - progress) a0 ~+ P/ j3 ]
// 是否使用速度变化曲线
# n8 D0 \, I( C if (props.useEasing) {
* {+ z5 F3 p, Y if (stopCount.value) {+ K9 p& h, m- a8 q# N
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
! X- h/ y8 i* T4 }& n } else {* A1 L N! S& y- x, G% q) X
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
0 X% R7 E4 X2 V! p, W1 ] }: Z6 c, n5 Y# D2 i8 m3 V
} else {
, U$ m5 N, z5 H if (stopCount.value) {
6 l' r1 e4 M, O( q# K state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
# a2 |) z1 S: W2 u' S } else {2 J1 U5 J# ^7 `
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
1 H( q% \2 Q- f) w }
: P/ a* M3 [; V- S }
, D/ P4 O$ o u- H. s if (stopCount.value) {" Y# x- ]$ k( }" |0 ^
state.printVal = state.printVal < props.end ? props.end : state.printVal0 q1 F9 c. w1 L4 i, A( f! e, }
} else {
, R7 n/ i5 j b# z state.printVal = state.printVal > props.end ? props.end : state.printVal# A3 c% U9 P0 v
}" z$ h8 ~0 V+ Z
4 n# `/ J; J( ^; s& d
state.displayValue = formatNumber(state.printVal)
7 P5 B" `+ Z; u/ n- z% p( K! s if (progress < state.localDuration) {: k' V+ G( J5 ~* e0 H
state.rAF = requestAnimationFrame(count)+ K0 S# j9 v1 G) r
} else {. ]5 @4 `1 m3 ?# v( o
emits('callback')
; L& B3 ? A5 d/ p+ v }" n. e' H" J& s
}3 D/ u/ N9 W; l' _( V' e
" w6 _ f- [2 W# M) u) s4 r& p) h( d
( b3 C' a5 i( C: \' k: M: x' L$ ~! Q9 h// 格式化数据,返回想要展示的数据格式
o! y, B2 X! Iconst formatNumber = (val) => {3 g. h$ d; f8 p( U% x/ N
val = val.toFixed(props.default)$ ]0 i* D; \& Y" L# q- y" [) I
val += ''0 n& [7 C/ }7 s: B: S+ u1 J/ r6 c, T
const x = val.split('.')+ p/ y1 ^* {0 r0 m+ b8 b
let x1 = x[0]
& M8 j3 z% |, D! x7 ~3 {* w const x2 = x.length > 1 ? props.decimal + x[1] : ''
6 o! @+ v9 r' U. Y7 ~ const rgx = /(\d+)(\d{3})/; p! k' \8 Z+ X. u
if (props.separator && !isNumber(props.separator)) {% C, n; ]6 A' I" Z6 ? s
while (rgx.test(x1)) {
/ M7 Z% K* m7 ?& e; T& z; c+ T x1 = x1.replace(rgx, '$1' + props.separator + '$2')
- N( L' \) ]! p0 g }
/ [% W0 s- G' a7 {' R6 g } }* P7 |; a8 W$ y
return props.prefix + x1 + x2 + props.suffix+ ]1 Q# V8 @3 g' ~9 L
}4 T7 i! z _: \& L4 U+ g( e, C
2 ~- ]: g/ e! S0 ?1+ L( O& u! [5 f* _; E- v8 ^
2+ m3 |$ z9 Q# B$ d# {# f) k2 m0 m
3/ ]& Y- e$ F8 i# V, B+ k# t$ b
4 H. O! S( n/ h/ k! \; R+ ?% n0 }
5/ z$ ^2 y2 d8 p7 v
6 r8 F# F6 p& X/ ?& r
7
) V: Z7 r) P1 j r# W, V" L# b8
: V, ?# f B8 L! r7 |0 V9
2 g$ L) a' T$ g/ L2 g3 J% m9 I10. q' d x/ M; J% V J# R5 q4 z7 Q3 F
11
y5 i- u) _2 d( Z. M5 N4 i, d123 t9 O* t" W6 ?( G- F9 `6 G% K
130 u K% S! g8 W
14, e9 n9 R' I- v" x) h/ w2 B4 ]
159 @! g4 {! ^# y
16
1 N! ?# G) {* p) @17$ o1 y9 C: @0 K* S$ h& n5 M
18
& J8 b+ p" X4 Z* _/ r6 g3 \; x19 V7 g! {! [8 W/ V
20
# L" @9 g. s+ x* A T: W216 i' m7 k4 d* |4 V
22
* _6 K* _! u- h6 ? D! Y1 R0 s5 j- T236 |' D( j' V, {6 }: M
24
+ x( N; y- |- Y" G25
/ F' o! _4 ^0 ?/ [' H267 l) B, F b9 H+ \' G
27; O0 Y4 C; A* R% a8 M( f, d/ y
28" s' x' k6 a- o9 t& X% Z* B/ X
29
3 U3 Q5 Y7 B9 U/ x30: w) j* V2 M) q2 K
31- s t% E9 O" B w+ v% u3 R: x# O
325 _. i: \1 T5 l* C, u! h
33
( Y, i W }- W; w) D9 I8 w* o# h1 O341 R1 L V! V3 h2 r1 l3 t5 J2 V; M
35. I7 _" D1 l( s: J/ K
36
7 Q" S2 M0 _6 S }& Z: b4 x37
5 ?" A. y( f( N: B: @38
; s6 |# ?9 J# U- Q4 }39
4 I" {+ K( a2 ~( Q40
8 E8 I7 S; o9 B41
+ y. ]/ h; T+ g5 e42+ w# p1 d4 c* q( S( s
435 v$ m1 c+ t% S5 ^" p7 e
44. o- v7 a: N7 s7 V2 F/ N
450 _/ M; m9 O9 D
46
% |% H W1 J7 G) H# G47
2 \6 ?* }) K' o% @, ~( t) P$ R Q48
& @& q. l, A3 h1 u( h7 d取消动效
& ^' o4 w. i8 J. ?
; c! R7 }' x. s// 组件销毁时取消动画% v( b% t7 h6 Q+ w
onUnmounted(() => {, O* @! z9 Q, p. O0 N
cancelAnimationFrame(state.rAF)7 M% ~8 U2 `/ m- K! y
})
" d$ c+ Y2 f: g/ Q+ S: r1
D7 C9 T& k7 L s. {0 a2& g1 f" h6 E0 @
3
/ {# h; m) C. T# ~# }% n4 H7 R7 S5 Q. O. Z0 P: H
完整代码5 G9 V5 s; c0 l
, K; E0 O J. C3 B! x; M4 }: k<template>
. P" [- J3 N+ e0 `; O3 O {{ state.displayValue }}$ \+ h- G1 O1 \7 q: m5 t/ i
</template>" c4 Y+ L2 N% T# s _( o
7 y3 q4 f/ n4 k; [; w8 @" q
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
# `) h) e$ u2 _. v$ J& G! j6 ^ Gimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
* j2 C7 f! Y( Ximport { watch, computed } from 'vue';5 R2 |, l+ Q5 ^2 U" h8 X
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'5 x6 ~* ?& q0 s) i$ Y6 H! @# a2 v
// 定义父组件传递的参数; x7 Q( U% o8 _
const props = defineProps({
+ G) M5 p* R. Q/ x, q& b! o) ~ start: {" H) L) \4 j5 u. c% P5 ]% [
type: Number,
% j L6 {0 f! ?6 u5 K, t3 n8 D2 }- D required: false,
( X* J4 z! @7 K% E7 | default: 0! x$ t+ H% m v! Y! k$ e
},
1 Y# f8 p9 R0 _/ p2 f: | end: {. Z' |3 [& g; R0 S. g; S9 D
type: Number,, u; U& ~# }' ~
required: false,( A. D; m1 Y# n# [1 Z2 p R- ]
default: 0
4 ?7 W" u+ h$ j* p5 M },9 c' l3 V, k% u9 E
duration: {
! [( e- b# B( G# j* D type: Number,
) Y! w9 U r' Z/ _/ N/ P! p required: false,, Z7 ~& q) n1 m5 P; W
default: 5000( d0 }$ |2 ~7 u w7 t- r
},5 c' K# m: B* f6 D
autoPlay: {
7 t1 u" ^# Z) ^5 s# J+ c/ x type: Boolean,3 z9 ?* A* d0 ^$ V0 b; I' H
required: false,
2 b0 f2 D, \8 n7 ~# z default: true
, ~# Y9 q: g+ C5 s; `! i& [9 P$ f },5 n! d9 y4 W$ C) k: Z
decimals: {/ M" f6 h% g/ n1 T2 B7 G
type: Number,% b4 b( p& Q" f& i' A6 |; M+ R
required: false,& {3 f* d0 A! @% o' {
default: 0,5 v* A7 y, C0 T
validator (value) {# U7 A) o" _9 @ ~/ N# i
return value >= 0+ s z' M+ B) ]& D# O" S: N
}/ z% o1 k0 @. c. B; j
},
) w9 X7 p4 f# d8 z5 q decimal: {
2 g2 ?% a7 e" ~, z$ o type: String,0 F5 L8 Q% d6 O/ f: d, F/ R
required: false,8 J, u4 R- w' h9 {
default: '.'
+ H# d* U8 S" q3 Q+ D+ C4 I }, c' s( D# p1 q W; n0 J1 n7 P
separator: {
1 Q; _2 C2 H& C type: String,
. {' g, t3 c4 K required: false,/ a4 n. C0 Z) v- B: G
default: ','
1 c Q$ K& y, Z6 e }," M `, {6 w& E' ~
prefix: {% u6 m* u5 t6 W# r. P; S
type: String,
4 y+ ^/ X- @7 |+ O4 n required: false,
+ {3 H# x- C7 ^2 M \* |# ?+ ], ~ default: ''# o5 r& B" G7 } z; N- H
},5 d$ n, i/ U( Q3 A; w* O
suffix: {
! H* J/ Q& H& G8 G+ l! L7 O type: String,
2 Q/ k1 \; y! g6 v# F ?9 C3 T required: false,5 m& _: S5 G, `1 i
default: ''
, z2 N4 c0 w3 J },
' q( C; `$ y+ j useEasing: {
; _: u y' a) j+ l, W type: Boolean,
7 k* @# |) x: z1 ~* B required: false,
$ l6 A( |" R0 M3 K* o1 x default: true a& e" |7 v/ P( Y+ z5 i7 L5 S0 T
}, U5 k5 k- b8 p
easingFn: {
) B% X$ C: A' H0 v& x. O8 M type: Function,
: u5 u5 i9 a# f* f3 K' \ default(t, b, c, d) {
9 z" W/ u& a+ l1 S$ L+ |. e return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;, t3 K0 [3 Q1 |8 q: t9 q0 |" v
}
8 S6 i8 |- i/ c7 ^( a5 Y }
) P! Z* f. G0 T. Q})# [$ e# t. i9 ~" `( C
5 H% V+ z* M. l$ |& H! D" cconst isNumber = (val) => {4 v; D; v8 g: o9 D2 U) V& W
return !isNaN(parseFloat(val))/ Z6 Q4 E; \) ?% b
}% o! B. l: i+ y2 F3 N9 g
9 G, K3 d; O" ]; Z" d
// 格式化数据,返回想要展示的数据格式
. c% m% A( I! [0 P0 G6 ?const formatNumber = (val) => {! j: n/ W+ O2 o4 l4 o$ C
val = val.toFixed(props.default)* t9 [1 T( R9 V) o+ i* Q
val += ''/ D' U, V5 m; T3 e
const x = val.split('.')$ ?$ l' I D- ^* x0 ^- W
let x1 = x[0]2 ^: T: [( |2 V0 B
const x2 = x.length > 1 ? props.decimal + x[1] : '', i6 o/ c7 M; l) H$ `& n
const rgx = /(\d+)(\d{3})/( Y4 \% W8 j. U. H$ D
if (props.separator && !isNumber(props.separator)) {
" r5 }' o) B) p while (rgx.test(x1)) {! _8 b( I; w/ F
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
5 x, w0 Y$ f' |+ r/ l }
" [% K6 G" k' z }( f+ c: V8 ~2 [$ a
return props.prefix + x1 + x2 + props.suffix
3 p/ M! i% ^; b4 B( j) X. X}# r& E! O1 ?* R
0 ]9 {7 n8 o; y& }6 \! |// 相当于vue2中的data中所定义的变量部分
: f# V. b: j* `9 iconst state = reactive({; o( M3 y: `+ q6 _( T* z* d" _
localStart: props.start,) p, F+ f! C3 t- C( p
displayValue: formatNumber(props.start),
( W9 w W/ V7 ` printVal: null,
: o& s, O; X: W4 n9 a& k" F) w6 H# ?- K$ i paused: false,8 w; z/ |$ H3 G5 b
localDuration: props.duration,
1 C2 @5 t" q. F7 z9 p. Q$ [ startTime: null,
# y' S6 X: X0 O$ U timestamp: null,- S( U5 T8 f7 n0 A$ E H; ~6 o3 G2 d1 H
remaining: null,( K4 i. G; [- E/ r3 D1 C% Z4 H* U
rAF: null. {% ?8 e! w, Z* y7 H) h* ?# U
})
' f3 ]( L- P& {* V
" J! p4 Q, R* ?8 o" h// 定义一个计算属性,当开始数字大于结束数字时返回true$ L: E8 i R, Z! i
const stopCount = computed(() => {+ Z. a% @: c" B
return props.start > props.end* j& r( `" V( G, z9 W
})1 h- j- Y8 _! ]
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件- K, L6 u9 |( |) Q
const emits = defineEmits(['onMountedcallback', 'callback'])
: ]' [) }" h& B% O' ?+ K7 r! W" M# X: K* t. |5 N) M' O; e
const startCount = () => {
, e4 I- K" ~4 t$ l) q state.localStart = props.start! ]1 `6 W; ^+ c. N3 C4 h J, p* G+ v* O
state.startTime = null) l5 q2 `% K g! J% J# c' s
state.localDuration = props.duration& v4 x* @# {/ _
state.paused = false
) B5 \* S( J& o9 P/ B. f) A% y% k3 S state.rAF = requestAnimationFrame(count)
$ t! `2 Z- P! R}4 c- f2 Z8 [: G) d9 c* S
3 J& I% N, c1 {% _9 W6 bwatch(() => props.start, () => {
3 l; W. m/ H+ \7 ~- C5 U# @5 j if (props.autoPlay) {
8 Q+ K' i3 |9 p1 B: d7 n startCount()5 U3 l* _ d, c3 q p" }
}
5 |# R4 B: }) H4 n0 k7 Y: j5 Q})) r0 K% A5 A" q) y
# b, w" e( b4 @$ k. x6 jwatch(() => props.end, () => {" x" w$ g- o2 L0 h, x
if (props.autoPlay) {
) C$ }0 `. \( \% E. [! b& k. K startCount()
8 h n' f0 s6 d }+ }# \5 p) R& c8 h' e7 Y: ?% V% T
})
( v1 Y& _- i3 g// dom挂在完成后执行一些操作; H/ M+ f- E5 q5 I
onMounted(() => {6 }, d5 J! O$ X: K* w
if (props.autoPlay) {$ M% B3 ]1 z. x5 \! V1 V* x8 ]
startCount() R. \# [6 Z1 t R" X
}
/ k8 n6 w; b3 k7 V emits('onMountedcallback')
; l5 v# \$ H: g" I}). E# p( }2 d6 F$ Y' Z3 r& a
// 暂停计数* k+ e# O; p) e3 t* m
const pause = () => {
" P* r( b1 A: e; i* }: } cancelAnimationFrame(state.rAF)
. a, G6 Q* l* f1 c0 E! D}
+ x# u. x+ H& ?1 j3 Y4 L9 p// 恢复计数
6 {- @% A# Y1 d- U+ m% i! L3 c8 Lconst resume = () => {
- z1 S+ U/ t' @; ? state.startTime = null8 F2 v( d! d5 t1 W) p' G, T3 V
state.localDuration = +state.remaining' c# H# X- W4 J! d# Z# F8 C( Z
state.localStart = +state.printVal
6 |* g0 K( U7 G. L requestAnimationFrame(count)
7 N& x' O \8 R6 H/ M+ |}2 o, C% l; `. a/ s6 T7 p3 N
" e0 [4 \( g/ e4 r; Dconst pauseResume = () => {' _3 t, C, Q( v' d& n
if (state.paused) {
: x$ X: R( v# p resume(); k- { a2 `! M) g2 N. c# b9 g+ ~1 t
state.paused = false" a B) {' |8 P# \6 X" _8 A' \
} else {
$ Q; C: G @; L7 |, G- {( v7 P pause(). G. N. v, q# |& s0 ^4 |
state.paused = true$ z4 Y0 N7 h% O- P! c5 p
}' Q. L: c2 w3 {) G6 @) T
}
* F- }9 J1 Q& \$ w( ^4 Y; }9 W, ?1 H r$ g2 Q5 ]0 V/ B& m5 ]0 l
const reset = () => {& R ~ z" \ a! R7 {
state.startTime = null T( a) T. N5 @( C$ N# n; b
cancelAnimationFrame(state.rAF)
X/ {$ P4 N* b$ \- A+ L state.displayValue = formatNumber(props.start)
! |/ p& q$ }4 [4 Q: z/ Y( B}2 u# _6 E# v1 ^) _( t
& y0 t b- d- |7 o, t# Y
const count = (timestamp) => {2 e& ]8 m# M# Q$ \: N2 m9 m$ F
if (!state.startTime) state.startTime = timestamp% P0 [/ ]4 U9 v) U- ~* F8 W
state.timestamp = timestamp+ C9 T, e# ~/ g3 X) Z; A0 t# k
const progress = timestamp - state.startTime
( X9 @# m; @3 ^1 K5 @: T5 Q state.remaining = state.localDuration - progress
A. b6 [) t: h5 @/ W // 是否使用速度变化曲线
0 t$ L o; j9 _$ [$ O if (props.useEasing) {) {; M' l$ p# w$ @( I6 g B
if (stopCount.value) {* g( p" a- ?9 V3 }0 X- C
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
4 R8 A1 o' g3 `- f+ K! I" h } else {7 `; ?! v+ v) e. E5 b6 Y, ^; ^
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)( ?' i& F+ X' \4 z4 ?- P
}
C( M" R" ^) L# U3 l. ? } else {
5 s, H8 z/ `# _6 s6 r2 Y0 m, E6 t7 \ if (stopCount.value) {( o7 z6 } [7 {* W1 Y: |" N
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))8 w8 @- \: _; B! ^3 O$ F7 y
} else {! j+ w2 D8 e" L& {' n
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
) h9 s% z# ^# s }
' I4 ?& c; |0 W4 k( [, A2 S3 U" v- R8 c }
, U1 _. m" o# z+ B8 f; W4 P7 D9 G5 P# { if (stopCount.value) {
- r" O7 j/ A; P! c+ V g# \ state.printVal = state.printVal < props.end ? props.end : state.printVal
* I1 o. {9 R+ R } else {0 P3 Z# Q# v! K- h" E! ?" ^
state.printVal = state.printVal > props.end ? props.end : state.printVal
7 B& Q) ~) ]: U' d4 J& v }
: b" r2 x( N0 e0 G* u8 Z5 I
' g- u9 F/ g4 I1 a- e state.displayValue = formatNumber(state.printVal)0 N j# Z* X, k6 k# q
if (progress < state.localDuration) {# H) o. ~3 {3 L) G; @% F
state.rAF = requestAnimationFrame(count); {" F; g$ A/ t' s
} else {. k8 U' T8 k% i4 E
emits('callback')7 A2 @1 F& g; Z7 \( w3 Y
}
: r4 s( w7 b& ~/ W, v5 n1 J}
a1 l. H/ Y$ g// 组件销毁时取消动画5 ?' n7 U! R3 a f/ L
onUnmounted(() => {
8 p* t' h+ D- T8 @9 t- y cancelAnimationFrame(state.rAF), } t' i: q; f- q0 w( k
})! b$ Y& s$ u3 z5 n
</script>$ X* t) F3 o/ Q+ @6 B! H8 Q
3 O! M+ {( L7 `9 _' C% f r: y% h/ c1
! J3 v. Q6 {5 @+ A8 v: f& a9 K2
G+ s# ?5 H& Q5 Z37 Z3 w+ E+ t" {: X2 `( T
4: |1 v" p6 P( k' u0 T C: |
5
3 i Q5 i) n, _/ Y* }( S; ~4 S3 P6' f {6 R) T/ N3 U3 ?
72 t k6 D& P7 s; F) e: D0 B5 Q/ n
83 `6 A. |0 I# U+ y9 q, o
9
* `, k& W) _: D' c10/ R& D. M4 U# \ P: c
11
: X* e! L; M) w% m. u. s/ z% ^12. E* O6 Z9 D+ B
13
. }$ y9 @9 M5 E9 R( G! \ c8 S14# [0 s: h$ O( o! v+ x6 c1 M5 \, ^& `
15( q2 m5 C. Z4 V9 L% X
16$ Z5 \$ {( U% R9 R$ Y0 Q1 Z0 w) S
17
6 z7 Y7 T4 |; r5 d6 v) S ~9 d4 L187 N9 \$ u* n" [, l3 y E2 o# T7 {. U
19
$ I6 N/ }3 R0 U% A( G" b6 c20
5 B+ l+ l' S+ K1 o215 U: w( ]% i" o
220 s) Y c: S7 |7 m; t( f2 b
23% u" a. }9 ?( t; [/ y$ N. E' }
24
! K# q# q0 h1 N* f+ m/ G25! E+ c' g* ^( t8 `! m
26% V3 V8 E7 [" |" J% B
27' S0 s: w( _5 D3 i' b8 |, s
28
7 P6 ^- a+ C8 v- z29
+ X+ k1 v J. h; M: M' R300 [* G9 \- L- P3 X% H7 @% Y3 z4 ~( W
31, W6 `- B! Z% b% P
329 P! a& W' l" ~! t" d
33
' p& U6 c r- j! ]9 ~- j345 R6 d/ F( c- k1 a. I1 I; \% Y
350 m& G. i$ ^ [( S
363 i1 j5 j* y/ E9 r7 \/ p1 p
37" k& \' y3 o) I: ?, h! n
38
6 ^+ ^& q; I! g9 b2 Y% e39
5 E) w# c; L- b* T402 [9 n8 N" d, V1 A* G
41
; a& Z/ Y2 U/ H$ I42. [0 y1 g) k: M4 s8 T
43% e% v, d: }7 o
44/ G6 N) h6 c3 P. U' ]
45
" \- T' C* C$ l! l6 D; H; Y465 \1 @* C% b0 W5 C0 `# H1 v. Y
47% A' J j: O" n J$ s7 o
48
1 g8 X8 A: `% F# W49
& A4 S) _" l1 X% u' s; n50
; x6 L" D% Z0 H: L- X51
/ S3 E$ d+ _$ {' ~52
8 H) N P) i) K53
6 f& v9 g' `$ e7 x' B" z; ]54" T; D! f0 n2 Q
55
/ j. ]4 J3 [; t7 {: f: x- a2 B56
% Q' u7 L/ h3 M6 Z57
: o0 |- q, x( P% S7 P0 F4 i, V58
( @& j; D7 L. H0 c+ |59, _1 ?, p5 y! n& l5 O5 `+ R
609 o& R7 U; |( x; f, p
612 f# l+ R! b: f8 b, q
62* M; }3 z7 K' d# n ^
63
) q: J. \/ s- W8 W& o* [! M64
8 g5 j7 e/ ?& x/ E; K65
6 f5 {1 j; n" N! b663 L7 L `; \# [
67
& v4 d2 S9 o @* r% H. G685 p. x l+ _5 R6 O* c% |
69
; ?2 z( ?" s; O, X7 g$ E70
/ k9 b3 E. _* B1 h6 g71$ e% G; c) Z. e2 M. L
72
! |- k& M/ w# L0 t73; P9 V* A- f& x
74; S+ Y+ j! z8 q5 M1 x
753 Z9 q: e2 x' P7 Y* j4 N# [
76
1 P0 i' |. d( G4 R77
$ S2 V, |: q& n/ o5 m' O78
" N, U1 L/ ?$ G6 B4 u# z* y792 W% F: b% X& m0 e- u4 l; P
80
! w6 @' `$ h0 j2 K81
s4 _. F( V8 N: e- o5 y# x* n2 I: U' s82
3 x2 t Z# y8 b9 p7 e) f$ k! L7 ?830 y* X* |; B1 _2 L
84
1 A3 }% r1 @. [$ o8 {& c, V! W85- _& ]. x/ r9 X+ \
86 f+ D* Q, B8 j7 q/ F# @
877 o$ N y) w1 P- y% @9 r3 o2 n
88
+ G! n2 M2 G2 [+ o3 `6 L5 K8 {89
6 o5 ^ z- |' n90- M1 w h. z/ h$ \# _8 G6 [
91" ?+ G: d$ P" } X! }7 a$ _. x1 _7 _
92
# m. t1 f. `, ]# T* M93& S5 N& a* \: T0 p( |7 F7 \
94, y" O, t# c% h# g
95
$ z8 Z7 X) W, [3 h0 t/ _* C# o: z96# _1 C; w9 O4 i3 t
97
$ U. i$ L" C0 J8 k. c/ g! x98
. A2 p! }# P5 g* ~& y" ?99; x$ f* H6 w2 c( f. ?5 E
1009 ?# c) k" K% W, v
101
- V2 P$ P; n1 z$ ^% c1021 B6 i7 b6 b. B
103" @# P$ T8 z+ y7 M2 D x/ t. I2 c5 g
1048 z( \+ D) k$ V; _: [
105
- r3 D( |* h& ~' _, J: q5 m4 h" h$ @106) g3 Y' G6 M; p6 k
1074 B: Y5 Y2 F& @9 M
108
: Y& B4 C2 p ^109% u9 d) E$ `/ s( i6 C
1108 S ?* n' e1 o7 R- Z
111! l) a; e6 l! k' t7 g* s$ q
1125 L. N2 N3 A# ^& _: Z! i
1139 u. g; m4 @, N% k% `' x0 B' u# j
114
; Q/ Z0 D2 i1 T. p; T& n115
- Z+ i& N5 d8 g0 i116 W+ R/ B% P$ O, V+ U* z% ^
117
; G, P. l2 @: {7 D& W6 V, o118& L. }# L' [8 q1 ^7 j
119 ]+ H* {3 P- y h
120! r) O2 }" U: O9 V9 F2 u
121
! E- R! L. ~3 Q, [+ T& C" d122
) Y5 G: N; K5 ^. ]+ G0 H a123
2 `, [3 O) n Y1 ]124" u8 c1 ^0 D! [: b
125: |3 z& v9 M4 \* x& T. v: R8 u2 z6 X
126
2 u2 b' i1 B/ M127, A" t ~( Q! J- \$ i c
128
! Q. m& ^$ y* v% }1294 f) K2 H5 F. G
1305 R( {8 D0 R/ b+ I6 g7 t
131
( s2 w( F0 g3 t. l$ F" W132
1 Z/ K9 n3 m% v* m133" x( J+ s& d! B6 c4 C& K4 h
134
+ L6 x* y, q4 Y) Z) K+ M: l135, w8 q8 j I C" d9 {: w
136
% a G5 J9 p) w+ o5 T0 R137- W2 ?! i/ t. u: G
138
8 i$ @9 a1 H; J" l% G139
/ Q0 r5 W" x- j# P7 t140( C8 T0 S* h& N( y' w9 t, S/ X
141
2 i0 c% G" X8 B C. l( f* R* X142& o: C/ ?0 ^+ U: g8 Q
143, [/ n2 c# x" C1 Z
1445 y+ m2 C, c# g7 J) @7 ~8 J
1457 P% e+ v u- `& I! I& r
146( Q' W- R- F* ^ w8 N7 ~
1470 q4 G9 L; L$ f% K0 }, j
1484 }: B. A# a* Q, H ^
1491 i+ F& I# v0 m, A7 ]6 U
150
) E: }% S1 p! f3 X. {2 W& ?151
$ l0 |5 o6 i: Q* T' A; a* b7 r152
7 [( g* U* j% J6 b G/ @; u( b1536 ?% z7 @1 t5 Q Z, ]: T% ]* f
154
3 y4 z, J/ K, @; H3 Y I1554 J3 Q/ u( Y. }+ {* {
156% R& |" e& B4 u2 ^/ O- f
157. p4 c, j- n# l. p# Y, @
158( |0 q9 X- y7 d) t
159! a6 G2 ?4 p( Y) P
1609 X& V# E! g/ G" O5 P( `
161: y; i# \, K" @ e4 _4 _7 ^
1622 B5 A7 S# b0 w ~6 _
163
( a+ L* q) T4 F' B* n164
- {# f' p m" r( w' D7 k0 \2 D" S165) z8 U! s. W; a8 G0 K0 b7 Q! T- ?
1667 z# ~6 I$ S$ y! N5 J1 ^& m
167$ E! j+ F' `4 H, ` b
168
6 S$ z1 {: Z7 E0 F7 U# d1 G1695 p2 ^5 o& D# X ~( m( D
170
j, \* Y1 w+ [+ O/ ?5 l171, h) [$ w+ f8 }( F% S4 x a
172
* ]- P, I2 t) d4 L l173
2 x+ ^ r0 C0 I" v174
! v1 Z- @& q& }# v- m8 W' r175 D3 o- w$ V* z1 `+ e4 o( _
176
! c+ [: J* Y7 }177" X2 P5 s( m3 Q1 r
1789 j- K, p; G! U1 E7 |, L% n& o: M
179
1 `. B' a. g( a; \; o( q& `180: L) @3 m" c) H* w) q9 W" x3 K
1816 I2 Q" H/ W( s$ M
182) T3 ~/ m/ G+ a+ J' }2 q, o
183; y' L4 |% r8 j, H7 {
184
C) h h l: d$ e; l( j& Y5 ^185. x8 u) k1 X8 M' W4 Q1 F/ D7 d
186- R" g2 @7 {& D) }! @' A
187
% X5 F2 Z( V9 m, T! `7 X188
/ y) a' z( U7 S& i7 B189
$ X" z* k% O# P190
7 q( g8 P; @3 o- }; N191
$ n# Q! t D ^0 a! w( n2 |192
' `8 e$ R" {2 P) d, u! N193' x# ?: E t1 D$ e; ?" K
194
) u( k: y- s* H( T/ P. m' }+ e& c195
' a- {; u) q7 \' }! }3 R7 n; i196
- Z- r& M+ s/ d* e$ C! w& J197
$ S) ], z4 w; Q2 K' @' r- O: x s3 N198
3 u5 C9 y% q# U7 V9 [199- D" r3 v1 \+ ^- p& I1 ~) R
200# a1 z/ V+ r8 Z$ e& K/ s6 ]
201+ _& ?( O+ }% _6 O
202
' ^: T& y4 g. z) R: l总结
$ a0 m% j' p X; O: X自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️; Y B1 x8 v$ e7 H" q7 n
8 O. Q; u! M/ k5 @% Z7 n9 ndemo演示
+ u7 g' Y5 r" A9 {) L后续的线上demo演示会放在' o0 ]# |8 j- ~ H/ N) K/ A
demo演示; y5 U0 U+ O' y) H4 o
完整代码会放在& @& j4 y: K' y4 |: \* H4 R0 x' E
个人主页, K h3 Y6 O8 ~/ S
J( |) `; e, c希望对vue开发者有所帮助~. [& w' u, X: R$ l5 I: i: M$ [
+ h' S) w# M0 u# A1 @个人简介:承吾 S6 c* I. J, q& o" Y5 J/ @: K
工作年限:5年前端( p G; G* B4 l& y5 G
地区:上海
4 }$ ^- p+ g. j' I个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!. A: R. L b- \, z2 z
. C8 P) [; B" a6 B: b$ A5 ~
" j1 X4 d/ N/ L% Q- A$ K2 v' w8 P( Y! F0 i! n
8 m; Q+ @1 p; A+ o ]& C- [$ D
————————————————
, X. L7 H6 M1 H' _' R版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
: `/ F# e" G- |1 P8 l+ i6 {* \# b原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847. Y! U2 P6 ?* E" `( L5 V% k
& }9 D4 Y% f% {
2 G9 y: |: T5 k u* A( X2 `
|
zan
|