- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563252 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174198
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
b! k3 A8 Q3 g7 u6 n
( k+ V# ~! P* Z# `. D. W3 ^. c) `前言
5 J8 |* A$ ?( X$ ]5 p1 } Tvue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
3 v; }3 j5 D5 N: DTypeError: Cannot read properties of undefined (reading '_c')
& f$ c C# e- F8 H- Z的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:. l+ W, |: M% j; C S
& K u9 D/ N5 G$ G4 }* l
Z& Q7 q/ J0 n* ]* k. ^' A思路! L% O8 A( v9 m' |% t5 ~/ t
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。, W0 g$ @6 s$ N% z, j- O
+ }2 c- O+ o/ [& O文件目录+ z% U' h9 D0 y g+ B% U3 M% g7 u
! p. p/ ~$ z; P0 G8 l, L% |+ F8 g0 q& c o" ?
使用示例
, m) P. f6 c! {6 ^" T+ U5 r& C, `<CountTo$ g8 b; b0 y1 R7 ~0 }' S0 ]* T6 D
:start="0" // 从数字多少开始$ i& q8 U! B8 i7 i! O' d0 Q6 m. ^
:end="endCount" // 到数字多少结束" W, `: Q5 M, r. c$ p- Z
:autoPlay="true" // 自动播放/ G# o: l9 h9 N% T
:duration="3000" // 过渡时间
$ e% x6 H0 Y& I prefix="¥" // 前缀符号
, m9 \! d% J- J3 z* { suffix="rmb" // 后缀符号
3 a0 X- O" |. `8 ? { /> a% K/ O/ I- U
1
$ T4 @2 i) Y* w1 j/ A, H/ L* \2; o+ N ?; l2 T6 M6 N
3
* O+ E: c3 ^/ i+ V41 Y! \) n* X0 c+ E$ ?7 u9 ~2 B
5
1 v% g! |- n& e4 {6) }4 @3 f/ V" r9 y( m
77 B. { f$ i( Q# D$ `8 S% t4 a
82 A5 H$ [' ~2 j
入口文件index.js1 U% y# T1 K% c# Y, Z- u: z2 _
* V' Z2 @4 _1 K2 |' N
const UILib = {
/ O. F. P/ n7 O* |6 r* V install(Vue) {: m& y- d$ L' j& i
Vue.component('CountTo', CountTo)! E% F! c' b+ p) C
}
4 j U4 X, J/ G}
" A: c/ \* E2 ?% T9 b; P G. X3 j1 p8 X7 O" ^
export default UILib
: ^. P4 ^" X7 {3 l- ^+ M- O# B% ~0 U$ ]$ ~
1
' {+ \* Q3 b/ c/ G- `) Q2+ H. j6 w, G9 r# [) d y& }( @
3
9 Q0 W+ _2 n- d1 I( L, ?1 `4/ e9 G: G! A$ v$ x
5
5 l0 E& a5 B& t4 `/ ^6! v R3 k0 }* l0 j% c
7
$ d! u! T t! }+ G8
7 p! J8 }3 W. M. Y* E9 s% s9
u( ~/ F" }; u7 N6 o" p% Dmain.js使用0 G; r5 ? O; m. H! l
import CountTo from './components/count-to/index';
. t7 B. C, Q, M: u7 [4 bapp.use(CountTo)& n4 k6 z$ G( d! d% ~
1& R- b6 t! D5 Q6 O3 @
2
9 n2 H8 ]$ d4 h2 @% ^$ T( q$ s6 rrequestAnimationFrame.js思路
& V9 \' T6 E; I7 @6 T+ M先判断是不是浏览器还是其他环境
8 O* f8 C1 D1 C如果是浏览器判断浏览器内核类型
) k/ q5 P. c/ |如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器
$ q1 n2 Q. ~: h, H H& f导出两个方法 requestAnimationFrame, cancelAnimationFrame
1 ?! `7 d# W1 M D3 A9 x+ ]各个浏览器前缀:let prefixes = 'webkit moz ms o';
: v4 n) n: \0 f2 p1 }+ \判断是不是浏览器:let isServe = typeof window == 'undefined';" k5 L2 i: E/ t. J$ @
增加各个浏览器前缀:
! ~1 S1 Q, z1 U3 R( Y! [/ {$ | wlet prefix;0 u C& S4 {+ X2 T* j
let requestAnimationFrame;
" K G2 h; S: Z) n; M2 hlet cancelAnimationFrame;
- F F7 \" a( ]7 k! J; }// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
" Q4 ^" {, q) j) U% c2 k ~) d for (let i = 0; i < prefixes.length; i++) {
- B* m2 {$ p2 ^+ P- a6 T s; D- C if (requestAnimationFrame && cancelAnimationFrame) { break }% D* j. a& m0 @( T
prefix = prefixes4 `$ ?3 H* |! z4 _& w2 C
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']) Y& j. A( U" I% u' C- ~6 C4 K; O( a' Z3 c
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame'], Z! W: Y! b( e$ o4 F- f t, O
}. O- ]& y# V2 d* M" \# Z
& O2 C% h5 _. E. ]9 {& b+ P+ N
//不支持使用setTimeout方式替换:模拟60帧的效果
7 }' }/ H7 P& B* z // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
( l1 }0 h+ e- s7 @* Z if (!requestAnimationFrame || !cancelAnimationFrame) {
$ ^+ O. z9 Y) I' a$ x% M- y requestAnimationFrame = function (callback) {0 A" R$ U! K/ |: Q$ V" O
const currTime = new Date().getTime()3 z8 A" V9 k& d% z% l
// 为了使setTimteout的尽可能的接近每秒60帧的效果+ x) e' x) l- G6 N- u1 k, F1 I
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
7 B: T( I- d, b- g const id = window.setTimeout(() => {
, k, y: U- o, V8 M6 j callback(currTime + timeToCall)
, h5 j, v; g0 ]* a- q }, timeToCall), a4 t9 P: P4 N. i0 v+ p5 K) a0 _
lastTime = currTime + timeToCall
; W( M0 p7 s5 ?% G2 _) Q return id$ v1 D3 z8 r( d$ s- V; X
}
: Q7 H4 J( @ e s8 o. w) s$ x( z# P0 G2 B9 X7 |% r
cancelAnimationFrame = function (id) {
4 N( n: f5 a7 \ O( Q7 J% e5 ~ window.clearTimeout(id)
8 m/ T7 s- a6 [9 A& L4 m }
1 M3 b8 P; v3 G }
! g- |5 s. ~1 q% S* D6 ~% F
0 i( x- o' Z, c H9 \8 b1
: f) q& o& r8 _" Y& S2" ]0 p3 [7 [+ _, o3 q) o1 p+ \2 o
3! Y* {% w E; L/ t* Z, s! I) ]
4
' j; r7 _( d& A0 J9 B* @56 @$ d2 X2 e) T
6& t" i. f4 z. R
7
' u* e) `$ i4 g1 \+ D$ O8) T& U$ I8 o$ [# f3 b
9* b" j& ]' ~: ~
10
5 b) r* T- h) O- \# L9 K4 C11$ _+ o2 s5 }" T1 o
12% Y% |5 \2 ~% H$ n& a! g/ e
136 n& h7 n' D# y" l c0 B
146 E; f4 S; c! p. z5 M" p
15, w- T% w" [6 o: C% |* N0 [
164 t r2 {7 V0 O8 i4 W/ E
179 W- Q& J. ]2 K! f; _9 [6 D
18. F/ m. f. i$ P4 U' f& o. A# _) e
19
5 x7 W" J! W0 K* P% I- x20( h( j6 P+ u" J
21
& C1 K0 k$ c6 _( ]22
' x& V* X/ |& u1 }8 Q c- V23) M! m" n; S! F2 B+ }# z& t J
24
8 ?* [( q7 m. @, J2 o2 M. f256 }- L; N* b( L9 Q T' h2 X
26
; d ]4 K& d- n$ A% z# w0 L- L7 H/ |) x27
! A' l/ b$ m3 L$ s3 G: S28
" i6 Q0 m; B, A+ u* K) K8 K29
8 K7 Y- m4 D3 ]: _30
. j( K. a5 |$ @; F31
4 c- D& Q' F% h8 ? _9 [32
3 ]% g$ B( \: {完整代码:! [- ^* }+ j; G8 B. E
requestAnimationFrame.js
9 Q: k, b0 e9 ~, B b3 t( Y+ A: q
! Y. C7 _% O# t% j" j! C- ^$ Wlet lastTime = 06 Q* E+ ` J* `- [0 P7 r6 D! O
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀8 k" O1 C- i, ^/ [1 N
' q/ H7 l9 ^ k* w; I: ^$ Nlet requestAnimationFrame
* I0 w6 t& d! A( E# t. K$ N0 Wlet cancelAnimationFrame
]# p- `# V) w) w1 w2 L" m, E
5 K1 S% m; E3 c2 d$ @1 W// 判断是否是服务器环境
5 b) W5 r F. @$ C4 Q9 Uconst isServer = typeof window === 'undefined'$ ^- I6 \7 f1 L4 D! a8 D- ~) R
if (isServer) {) }7 f. J" {/ A, o
requestAnimationFrame = function () {- p- u, z, H+ x% Y
return
4 h- u8 {( y, h' I! A5 k4 E6 z }
0 {; ^; n) O- ^; g0 ^ cancelAnimationFrame = function () {3 }3 l; U8 r1 c( I
return
2 @3 y9 G" \2 k. f; v }% R: C' n7 m/ A) L" b5 h- ]+ B1 x
} else {
; x! ~6 J( o6 C2 h$ s! V requestAnimationFrame = window.requestAnimationFrame. e3 e* m5 t2 ^
cancelAnimationFrame = window.cancelAnimationFrame
; ~0 @# s( S: J, B9 Y/ R* O let prefix
9 P& E N1 R I9 G c' E y% d // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式) D+ O/ d5 e, K# k, O
for (let i = 0; i < prefixes.length; i++) {
0 A, I, f0 W$ z+ C7 v8 v if (requestAnimationFrame && cancelAnimationFrame) { break }
" U% ]/ q9 J* r h2 o* E s4 X prefix = prefixes! e3 V9 l/ _* T
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']; \: Q+ v- q4 `7 y6 u
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']* `, U. S- A3 Y* ?0 Z( x+ C
}
8 d' a( y7 l* }% d) u' T h, T; r: `! u4 ~ ?9 {# w+ ~
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
: a6 R0 m( F6 L, I1 T" D! G b if (!requestAnimationFrame || !cancelAnimationFrame) {
' Z' I& ~3 l8 u requestAnimationFrame = function (callback) {# a- @8 a W; c8 ]5 v+ ^
const currTime = new Date().getTime()
6 N) u$ Z" Z* e8 N' u // 为了使setTimteout的尽可能的接近每秒60帧的效果$ s) {" f3 M3 o9 X& a4 o% \
const timeToCall = Math.max(0, 16 - (currTime - lastTime))9 w. F3 l7 O+ ^
const id = window.setTimeout(() => {1 `3 F1 f9 y {3 P; A
callback(currTime + timeToCall)$ d1 d& y0 q$ X/ H
}, timeToCall)
, y5 C& r$ Q/ L" h8 N/ y* a. F lastTime = currTime + timeToCall
5 e; B A4 z1 j6 {7 K return id
4 U( |- A X1 b4 A' E) G9 n }$ a9 ^2 T) P5 S, S
5 f/ |, e" _. c# _
cancelAnimationFrame = function (id) {
- h2 y( ^9 B9 P7 o window.clearTimeout(id)
! n+ ?$ E5 y# e2 V& q e) D }
3 k4 u+ d) I% [* @6 z }; T1 w' B0 `8 z
}2 L& u6 j2 ~6 e, R' S
8 P S3 F0 z7 w! O, L
export { requestAnimationFrame, cancelAnimationFrame }
5 d& o3 v; I, t% s: c9 M q' `/ M$ C* l C
9 l0 N8 q. ?) ?# k2 p* d+ \2 B
1
8 D! w$ l" B( x8 o0 g" N2* b% I$ P( q( q+ Y% `
35 n8 i& Z0 m! W+ L/ V
4
' _6 ?9 ?8 x( Y" I2 M$ ~. _5, |' e! F1 C+ |5 f3 h: I4 A) l E
6
9 U( f% S, H5 t9 n78 v- Q" X: g& I
8
5 V: m0 [/ B! H. c/ T9 Q' y' I9
7 H* m( z& \% P7 X3 h8 l8 s106 z( z! @# u2 c1 [7 L7 b
11
; n" f' P5 L! a# _12
, @/ `. }% \9 f% v- x/ c: f131 X! ^! f% ]) w3 A/ ?; F* @( P
14
$ I- ?$ P$ C( j s, I6 G' p6 f* L, {15
' e/ Q( B& w4 r+ `! ~16
% n( P4 z4 {0 W! V3 M: x/ I* Z17" a4 `$ X) o2 R( u
18
4 L! l. @; d& j4 m- @" r+ f19
' q6 F' Q* R. O+ I7 ~201 R' w( t! n- P1 ]
21
; A3 A' Q, H( V, p* I0 G& X224 m8 f! E* R5 h& Z5 n# C
23+ u; }8 g4 b* W: H( N$ ^5 o5 g
24
0 u: _& @; e: [' J- \: ^25
& f4 c) a' k' z. p- e26
8 K/ [ V+ h4 ?" |27
% m) X7 g, K8 V280 u- z$ F; Q E: ?+ a8 _
29
. s6 T; ]& P b! n& B30
, c- L6 ~5 v q" @8 u0 J31
0 S( p! {, C& e% @32. F# f( T g6 L$ K$ q( U$ K$ G
33
$ [+ j8 Z) \5 ]/ t8 o34
, d# y- A# Z) G35
& o5 }( ~. W9 G. W/ @36
; n1 r1 c& e/ w" q7 N- c+ [37
3 f M- \2 O( f. g- K/ N38: d( `) A1 b( B; o. ?
39" L8 P; p7 F5 u& d( M0 T1 e( x9 j
40/ c$ [' z& S- J: j1 D1 Q# ~/ ~* L. x7 V
41
2 ?$ e4 {: B9 _' n* d' j42/ T2 N2 w* x& P2 g+ x3 W
43
5 u- ^2 X ~6 w6 u! `. I44
( F. p6 w/ N+ e3 J8 e' i1 L8 X) { r45. Y4 O( Z" x: r9 ~
469 ]2 w! B! ?4 J
47
4 Q7 ?, J% F+ z48- V" _5 f0 w* m0 \( ^) F
CountTo.vue组件思路0 G" s# R8 v- R; O/ ?3 d
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
5 n, f5 M0 F6 s4 T
/ B9 C$ U" u' ]. s3 I$ h引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
- `4 l, ?% l8 f n* g1 D1
8 t; a; Q) n# L需要接受的参数:0 @3 }8 t% t; b3 Q! n3 c: `
' a( `8 S2 E2 h2 b0 _const props = defineProps({
- m& s' `( ]+ A. Y# e+ R: r start: {5 m8 Z# b0 J9 k( s# [
type: Number,
+ ]& D( I$ H/ k2 l; v) z0 P" A3 H required: false,! ^& q$ R. Y2 A( J: M2 I
default: 04 f# p# n0 ]8 t& ^! F0 v, Z* E
},7 l. S: t" i, m, G' O
end: {$ N! f# o# b9 |* }% C
type: Number,
: C) E; O: f8 K required: false,
) n8 m5 U" G) X ^ \/ Q default: 0/ @& c0 {5 T+ S3 `/ x* v1 T
},8 S+ v2 b5 V6 ~% k
duration: {4 y' {+ \ A @# t9 W7 D
type: Number,
( }0 ~; @) i I R% Y, g required: false,
" @& a2 p9 {# `* c9 R+ h6 L default: 5000) R, A# U. F7 [2 O. I' o: V! I
},
9 {; X7 S9 E1 |/ q9 l4 D; f' C autoPlay: {/ \* Q; V: A( @* c
type: Boolean,; P! \; R8 F7 r" f
required: false,0 O k( M2 i; D. s' y: z
default: true
/ {6 q/ j6 w) y8 d4 C },
$ n* F( g0 T4 a4 u decimals: { Z: a$ E: I$ P1 T/ N
type: Number,6 B. W) C% v; |( P
required: false,
8 U3 q; P4 q2 v( u# A- J' i. u default: 0,
6 I5 D+ r- r$ C4 ` ]6 w. _ validator (value) {
: x) d& A2 e9 Q1 b& M5 t3 Y return value >= 0
' [# E4 _% w- T+ f* ^! }- F }$ I# B( t) b$ {6 o: v: M
},
1 ?3 ?' W) O. h decimal: {
* A3 [* T+ E* T& y3 k6 W2 t type: String,* ]. [) m+ u B& u& G8 j3 W
required: false,
: J6 A& D- T! A default: '.' i+ ~6 r+ g1 _* t2 x
},
( ~, g! [& E/ `4 v2 X; _; Z3 r3 D separator: {
7 k- W( C% j- a4 k U7 G, N type: String,5 y h5 |) g. c) l. i. b
required: false,
% s3 S9 u! o9 ^ default: ','. `) u" ^, r. C- ]: P1 y
},# Z; j) \9 p- g+ J
prefix: {% H( h7 k3 I! Q7 c, W: E( v' w
type: String,& p6 k0 s% J2 M3 k* Y) P& j
required: false,
" @4 B/ i A. ~$ H2 Y default: ''
1 R9 x0 E0 R" b/ ] },5 G4 H& K* y7 H6 A" B
suffix: {
$ Y; L7 q9 K# \9 i+ N+ m type: String,1 }, k& u6 m+ G! n. H
required: false,: @ j0 a& R3 b" s+ n+ S* W/ p
default: ''7 h% |1 S/ ~9 Z
},
! D/ @( X! ^! O& D useEasing: {
5 d- l' k) W; B+ B* t type: Boolean,
M7 c. v, k% j' e4 G& i required: false,
4 Q- s6 ]$ L0 M" { default: true/ A/ ], C# B+ q5 a
},
, s4 J* g( B; Q* _0 E8 }# D easingFn: {& s# |5 t9 \$ c) ?; A9 z
type: Function,. z( x( G O( s n/ J# e1 C
default(t, b, c, d) {, ~( c* U' ?0 g T
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;+ |& C' |/ u% W" R1 R
}/ d, Y# w* C5 T& V7 I( Z; K" q8 P
}
3 W" V# @7 `3 v7 {})
: v" v$ T/ P+ R; j7 @4 i/ m" l
) g5 \2 A% U+ B; ^" J6 y2 ~, _% U
1
) C( K% g3 }' |7 D2% Z1 @/ a+ u7 n t
3) k' I8 [$ p: A2 D' `2 F7 |0 e
4
6 s9 _0 x* |- i7 }) c0 _% ]8 | \5. ^( [8 z7 x! ]% R5 T
6
4 H! y5 v3 Z, g7' {. p7 E7 A' k& L. Q6 [( O2 K a; p) k! H
8
4 a" r( n' d* w7 t9% m2 L* e) f1 s& _
10
. T4 D G. |" ?8 W2 J11
5 B: `$ \ O8 n) ]3 n12
9 r o0 l8 T7 q" p3 `/ N13
; j; w) K! f6 z14
+ L+ ~. C# J: v% Y3 b: }; |/ I/ a( L15# ^0 W% U' E0 Y1 U2 W- S# V
16; d" k# c' }# z( r
17% _: d! H* l) n8 B
18
# P8 ~, I/ c/ Q# F/ e19
; ?" A& |2 ?3 x/ C5 D1 @20& a4 g- K a3 R" H# h/ V: V
21
3 ?7 T- N- i! }- N' ^! P+ ]+ C22* ~& h' G' x3 V8 o2 }# _8 ?
23
" ~* V _6 |: ~; w; d% c$ V24
7 p- N. e& `( R: e7 o X' ]7 i25$ c! w$ @7 d* v6 L: q
26; j( n: U# j" U7 x7 \5 N0 P
27
0 l' V. r1 @& s' A- [& c! \28$ b; a9 P& ]3 a% l' j. b! S% i
29+ a" o# l8 p* a) I
30
5 Y6 E5 F4 O5 E3 M D8 W8 M31
: p2 v. Z1 G. Z322 g% B/ Z. `' j; N% f0 p m( F' `; A7 B
335 t/ J1 Q5 D, ^0 P6 H' y2 r
34 x0 F1 `% S) _* Z5 ^$ b
35
/ M3 a- k" w! O+ l36
9 w& g6 u1 m) t! o$ H- _' }37. \* x% Q( G5 E/ n* k( j6 B
38
( C8 I4 g/ s1 Z# ~8 s397 a7 Q% `6 x; e% p9 u
409 ^" r& D+ p8 V- |2 A% X+ z [. I
417 ]9 v' P- M" K
42% o' o; X3 N# D3 }( W
43- _9 `( E2 j' @% ]4 h4 Q4 A# z
44
( H- q% p" c; @. f+ Z1 x* f d45. }$ i N: o7 c& [' q
46/ j E1 y& ^0 o; }6 y7 E k
47, i7 d; N7 U) a8 d$ w
485 n0 Z0 S7 o Z) Y7 ~+ @3 J3 E
49
7 V; b4 {3 |3 y% r50% Z* H- [ x1 Z! J% o, Y0 x& t
51
0 S+ Z& o! z; h8 {/ Z( T4 l5 a# \528 ~6 z" g# Q M( Q" L& v. K" [
53
4 I- H# E9 P9 {1 S8 y/ H4 Q9 |4 a+ r54
& Q- z4 i: A5 {/ ]1 y8 B555 a( r* K" I, e5 V* G9 L E5 i) \
56 _% l( u9 d h: Q+ w1 C( L
57
" O8 o$ U/ w. ?& R# m: b58
# N" P; ^! G* O t9 a% T! t59
4 W2 D( h9 M- A# I$ X60
+ q% f' i- }; [' s. K610 K0 I4 i$ M/ R' z: y
62
/ n# x/ P6 k( h7 q4 l0 H$ g1 l w: l启动数字动效
4 t, N- e9 _1 W" ?$ p- h' Z" [* [/ I
const startCount = () => {
% ~, ^% u& R# Y+ t9 i: F$ S5 ^1 z state.localStart = props.start7 [! _0 G7 _% y! h! h ^! h
state.startTime = null h. N- i3 W/ W+ a
state.localDuration = props.duration! }2 B5 A# @/ ~5 s$ @) d3 q/ o
state.paused = false
. \8 B; ?( d- n% y8 r6 B9 p+ ^ state.rAF = requestAnimationFrame(count)6 }7 S' g' m- W
}
, t3 Y2 d! ~: o. ~1
5 j5 o& |# N* G; K4 d1 C29 j" d% r; I/ b
3- H5 \! m/ R4 \
42 w6 E" Y; q* J) r, ~& @3 G8 [$ l. U: b
5
8 G0 y! Z3 {! p( o9 {6
4 |: t& |7 a' r" a" U; y7
5 p$ ~ B$ I# T" c* n4 m. n) L核心函数,对数字进行转动 X9 V# C2 O& \ N% c* |% R. q" _) [
# `; s8 b0 i! w7 I, C3 J/ Z+ T. A if (!state.startTime) state.startTime = timestamp! I3 v. ~4 I: b- U% w) o# l3 n
state.timestamp = timestamp7 j; \+ ]. C: D# n; L
const progress = timestamp - state.startTime0 t: e! M6 b( }6 r) B
state.remaining = state.localDuration - progress
% }! l% l( t. G2 F9 y5 p4 V/ w // 是否使用速度变化曲线% @. C$ O% i1 X! Z+ T3 L+ D: H
if (props.useEasing) {$ x8 M2 ^% z3 _' b2 ~( S2 Z
if (stopCount.value) {
9 l) X R2 J& O' O8 N' d& X state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)2 `0 o: L: }; R$ k; z
} else {
0 G# J/ k6 ^/ L state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
- X& b5 g }+ d9 i }
- J- c2 k Q0 {! {$ h } else {
0 G4 `) R; h- p x7 K# p if (stopCount.value) {1 v6 Y6 Y1 P" B+ A" F
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
5 }9 e; N& C$ t4 P } else {
. E$ ~* h# N. D: g state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
+ V$ v& `2 U0 T f, j }
! T. t- d' f8 n' ~9 V4 X3 t5 z6 W }
# F1 d/ a8 p- a( \, @ if (stopCount.value) {
3 D8 H! M% `! ?1 x# @6 j state.printVal = state.printVal < props.end ? props.end : state.printVal G$ H8 f7 ~9 o4 E
} else {
1 x' l9 E. J, ~5 c$ ~/ k state.printVal = state.printVal > props.end ? props.end : state.printVal, Z% |' W$ W( n, Z" X1 l' @ f" Y/ A
}
9 e3 v/ x( C* a. B8 F, v. R
8 ^# x6 m6 Z0 t( ?% ` state.displayValue = formatNumber(state.printVal)) L: C; L6 h3 h: Z3 t2 k
if (progress < state.localDuration) {8 w0 e/ ^) Y2 v' J- P
state.rAF = requestAnimationFrame(count)
b# Y- p p& ~9 E3 N; ]( S } else {
) I8 U) [* {4 A3 P emits('callback')9 Q+ [ A @9 I) p; f/ G
}) e8 Q+ J) h; B$ f" y" \
}
3 C* J- q `% \7 T! N! g2 V4 L5 ]* T1 [% i
; @7 [3 s2 j2 L1 u// 格式化数据,返回想要展示的数据格式0 {" o$ x0 A! }2 N6 S& D
const formatNumber = (val) => {8 w5 B+ j$ l V% b9 u$ c
val = val.toFixed(props.default); Z& G( O/ M; c# X: t
val += ''
7 [2 |- m% [$ e7 \& C const x = val.split('.')
& Y x$ t$ a0 ?0 k) r2 } let x1 = x[0]
6 k& c9 [+ F; K9 s3 ]( D3 ]$ ?% \ const x2 = x.length > 1 ? props.decimal + x[1] : ''5 B) F( y+ Y! J
const rgx = /(\d+)(\d{3})/( {+ y$ `9 N* i9 u7 x8 Z) I
if (props.separator && !isNumber(props.separator)) {( \1 A/ S5 i) ?8 b* M
while (rgx.test(x1)) {
2 u0 {9 T( |" F' I x1 = x1.replace(rgx, '$1' + props.separator + '$2')
: _ v7 i8 W0 _! i0 a; [ }
1 ^, q) S, K/ B$ s. U6 P }) }8 k, F8 I+ e! R" g2 s8 b
return props.prefix + x1 + x2 + props.suffix4 a2 |9 S; W3 V- t" S9 v$ t: \
}0 }1 _/ Z# o! x, m0 [
& R- q" _. H/ H' Y+ w9 X" b
1, ^+ |5 M$ [5 x: k
2
: J. F% D" D2 D1 z3
+ A+ T, I t5 ^* u& f3 u; ]4
: d9 {/ D1 \ M9 W% w6 F5" U8 I- P- d) w) e+ q9 R& m, i/ W
6
# r/ { s# f$ t6 ?; y7
" q5 f P4 u, I9 `( \9 `80 J- {6 s! H3 }, l0 R& f0 [, Y* f
9
) ]6 L1 Z/ U- x. g, N% G, g; r104 o, T6 U( v4 {3 y
11' g I( B7 s" H/ {1 E+ \
12
& Y! S! Z8 X2 ~3 K! f) ?& O3 R( t13
4 j, d/ |) M8 ~! G( e# t4 N7 r14
7 o( @! v! Q* \. v, f15
- i% I: T# |* k) {' F4 d# @16! D' `) n. |5 w0 \" q: q1 m
17, a- R6 Q6 D8 |& Z
18% I% n! i7 ^. [/ h1 O. s m7 R& e
19
7 ^+ M, C; ~' a' ~$ J: u5 c" i20* j. g9 B- B Z$ ~" Z% s# D& y
21. t/ x& @9 p) O/ f5 R7 u
22. v, `$ P; Z: M, Q/ r' H
232 Q' J+ m$ T% P2 E% }4 h
24$ v- J0 Y/ [4 o- Q" {7 @
25; w* T Q h: k; z5 m1 m. a
268 u$ d* s, q- b& F
27
: f0 G5 Z% `: F& T281 A" \: y2 O( j! m* R$ W
29; l% |1 R& U4 r6 D3 B' w
30
! j8 H, ?; O; S31: ~4 U* P- L* S- _4 X
32; v" D2 |& B' D" a `% s/ Z
33
. H( d8 N+ t/ O34& T* V9 \% H) ~) d5 O% |% V
35
: K% o: {8 u/ P7 B N7 k36 t+ k* W& `+ y4 B, t6 u$ a- o
377 ~' n* W9 Z& T3 O9 f+ c
38+ `6 n- Z; g) X; K. }% {$ `
397 \. [! V3 t. t9 b b
40
6 e1 P- H5 D5 m" K41
9 ~. c- e0 i; }* s42
; g$ {1 N \- O3 o' J43
8 c1 q% d+ X0 Z! c' ^442 c5 h2 u4 m6 g' j P
45
+ c& x \5 \/ R, F46
0 S) |, l' l5 S1 N3 ^47$ p% m. c, ?' k
48! o5 F2 e5 E9 ^5 r) o
取消动效6 x) B0 N i. G# l
& V' `5 q4 D. U) y0 g$ O( X
// 组件销毁时取消动画/ q# c5 ~8 ~6 Z* E8 T; J/ G0 S. a
onUnmounted(() => {
6 I; _9 U$ ?9 q5 W1 s! E# S8 D4 [ cancelAnimationFrame(state.rAF)! q2 k7 _& u; R* u1 S1 X( c1 |6 g
})+ |* G0 C m5 y7 q! c* J
1: O5 J: u& L1 r1 W7 }: f: Y
2
* V0 V/ P# P0 t; e; S; z+ v3 L3
0 I- |9 G* ?5 e% \- w2 j8 @4
) u( g( F% Q3 X. G( w& D完整代码
; R/ \, P, ~$ A0 p m) B$ h" c! o8 u
& L2 f+ |3 i. ^) ^, z, c<template>
: |# S/ q, M3 I! | e {{ state.displayValue }}$ B- T3 L$ Z) s& _
</template>. C2 G; R9 c: N* N: n( j
. W4 I9 x1 f* }9 r9 W" ?
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效8 p4 h: N4 R. \ s5 N8 Y4 g
import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
) _0 y. [" v: m0 n% w. jimport { watch, computed } from 'vue';* j8 p( D p) d/ b E
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
" [% o1 R G4 D4 n6 |// 定义父组件传递的参数
! R S l8 y) Z; Iconst props = defineProps({- _" t4 W: a% X* B
start: {
) n. z# V6 V* Z. O& J; F; p type: Number,! d2 a5 w4 T5 z9 T
required: false,# g- T: i* ]1 S7 |+ ~
default: 0
0 G. H6 F9 L3 Q },
4 L' K0 K, a* ]: j3 B8 c1 z: a end: { @7 G; s: X7 f( ? ]! O
type: Number,$ A K' e; L/ V( ?3 o4 K
required: false,
6 @" N# f2 l6 V4 J default: 05 m. U, L. P4 S6 y% E' }. U3 \, _
},
% c% l* a/ i3 R2 l/ [- K+ L duration: {
! n0 [' q& T6 v; |+ _) h* X type: Number,1 `/ j3 Q% c' \# i
required: false,
0 W9 k! @& s) Q8 }. K default: 5000
7 T$ s, J8 ~" ?4 ]9 l. @9 Z },3 b( e, m: M/ ~' u( ^3 G% X
autoPlay: {
5 B( R5 L, c( ~! T type: Boolean,$ M) g4 U" b0 M' [
required: false,
8 [; Y# }3 X# A+ [* z default: true1 r F* ?/ A) L- @/ {, o" d* \
},, O! F+ e' w) h2 A; x
decimals: {7 v( N# o# \ g) g
type: Number,5 y! L& O) ]' f2 y
required: false,- H( n" P( I( h% Z* S! S+ h, l
default: 0,9 e0 K0 p, b- T8 n
validator (value) {
7 q5 t; w# N. }) r. K7 q z# P return value >= 0& H1 W F$ P9 L5 } d
}2 j, U8 M4 j, |7 _" [9 ^
},
/ {$ J; A$ C* }3 |; q/ p decimal: {: u) t0 u' Y8 y7 G( \
type: String,8 O Y7 Q2 F' m, J
required: false,& E' @0 F T+ }4 `* _% U- x A
default: '.'0 N' F& ~1 ]$ n1 ?! a
},! i, \. _( p7 T2 P
separator: {6 H' e$ |4 c( |# m* e
type: String,. C x; j0 b& O$ B- }' {- J B
required: false,. h u& k6 s6 O/ Z) v; F
default: ','
4 `( S, r) r8 B% K4 v* w$ D },& N) ?" l, j/ @0 c2 Y
prefix: {
2 w3 j' t3 R3 G type: String,7 x; C4 U3 ?$ Z
required: false,
5 U' P6 x5 j$ a, T. C default: ''! l! H/ o) P2 I5 o
},
+ O k. H4 y6 g& y/ J) _8 R suffix: {
5 C6 |# g8 Z( D* W2 b) H) K4 x1 E type: String,% Z( Y2 L2 j- [
required: false,# S" d% z7 T# O @' v* c( q
default: ''5 c+ p' l( m5 ^8 L9 W/ }- d: g7 O
},
! J" P: D2 t/ @- H# e/ R* r, ]4 _ useEasing: {2 j2 d5 J1 P1 M6 V5 U! o
type: Boolean,4 h1 \+ @" V* o
required: false,
" h" {/ K' [1 O* j6 s E- w( @2 | default: true+ v) b' H( E+ s# k1 f
}," R! o# P8 W0 W% \
easingFn: {1 D2 m; T8 j; Z0 B. s% L8 _
type: Function,7 ?& @) g' \/ _# f& {2 y1 {/ h
default(t, b, c, d) {
' S: n X* u( v* I: N, s; P) F+ E return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;# q! b9 w( [- V: P* U1 p- Y
}. @ c) d, o/ ?, _0 `7 r" G9 L
}
6 u6 N' }6 l% A4 T, b! E})
, @- ^/ r: B. }3 ?9 ]0 t# [
6 S7 k) S: {4 V6 pconst isNumber = (val) => {
5 a% o- t1 P9 U return !isNaN(parseFloat(val))
+ F, h/ L4 C- h- ]3 f1 J3 A! |' F}; X, U! j, Y6 o; f
& Y8 F3 e+ y: N' w% s8 |, X
// 格式化数据,返回想要展示的数据格式# D- {$ R/ \# N( j* ] g) }
const formatNumber = (val) => {
! y. X! a0 P( s$ p$ Q val = val.toFixed(props.default)
4 {' [7 W: W0 F val += ''
) L4 |3 _7 I/ s o; F$ ~/ ? const x = val.split('.')
6 ~3 U" ^( ^" y C let x1 = x[0]+ j: l; w& R" r6 `. G8 y7 K4 a4 I) Q
const x2 = x.length > 1 ? props.decimal + x[1] : ''
. a8 N& s) |/ k$ J const rgx = /(\d+)(\d{3})/
, y) z$ a. ~: d2 G if (props.separator && !isNumber(props.separator)) {+ q. B3 n4 B: |* T) D; J
while (rgx.test(x1)) {6 }$ N8 h9 j) O. d! I3 n, s& ^
x1 = x1.replace(rgx, '$1' + props.separator + '$2'); b: Y+ O5 B/ _8 |- R7 }* q3 m! @2 }
}
4 o# G3 n' k/ T6 E/ G4 ^ }
$ Z6 Y: w. {3 r# F- A6 l return props.prefix + x1 + x2 + props.suffix0 N3 H* n& ]2 }- S) D# c
}5 `- W! n6 u5 ^ M" v
3 k- `% G$ M: P// 相当于vue2中的data中所定义的变量部分8 G' [9 W7 j; N d& \
const state = reactive({
' ?+ o9 m: X# L! B2 M B localStart: props.start,
( {1 I+ {( t" l3 z) H% w' [8 N H displayValue: formatNumber(props.start),
! v1 M! b0 D$ D9 t) h. C$ b printVal: null,
3 J% {- T! B6 E' K2 g0 w paused: false,5 A, K, J; n1 w; C, z; F5 s5 O0 q7 g( Q
localDuration: props.duration,
5 g( ]" w% d9 ^6 U startTime: null,
- V4 l, I4 H# Y7 t0 d& }" P0 M timestamp: null,
- W% e+ i i. Q+ f2 _ remaining: null,
$ Q1 |8 `, j+ Y& F' p6 W rAF: null4 r4 z) K# F# q5 e b! f& _( T. K
})% G4 D7 l) ?8 [
% N! V0 i8 e# L/ \
// 定义一个计算属性,当开始数字大于结束数字时返回true% i2 E: L6 b# M8 c
const stopCount = computed(() => {" B6 w4 P( p* V, L& L
return props.start > props.end- H. r9 M% t, D+ h4 J) \; ~
})1 V6 o' U7 P( }% C
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
- O6 G2 a) P* S3 t4 n% P+ Sconst emits = defineEmits(['onMountedcallback', 'callback'])2 P# R: P W0 X% r! K! `
) h& P! E2 P! Q" M$ D! econst startCount = () => {3 A- U0 j! X4 T: l* ?* E E
state.localStart = props.start
9 f; y* x( d" ~4 R( h state.startTime = null
! Q) V" N* j I. N% R state.localDuration = props.duration
" O8 C' @: \0 k( o6 `6 e state.paused = false
7 f4 [. Q9 D, a$ } state.rAF = requestAnimationFrame(count)
6 ^( z& W5 g4 ]$ G8 A}" o1 X/ T% W9 x# @4 M
7 M7 L8 i6 F4 O6 D9 S$ vwatch(() => props.start, () => {/ u6 {+ _' u! ? @9 e4 B- n
if (props.autoPlay) {$ y& B' p8 h `% i+ S4 W( U8 i
startCount()8 K3 g8 `/ r/ I1 X; w
}/ x6 C4 V8 B3 K5 w
})3 |. @/ T# {( w$ N8 o, y: u6 i; Q
- w7 A' e2 U4 W/ { u$ Fwatch(() => props.end, () => {, s% F, M8 t; F, i8 @
if (props.autoPlay) {* |* k4 @' b9 s) c; \! w' Z
startCount()
2 e! @8 o! W- \; g' P }# w1 S D, |) Q4 X2 j0 N$ Q
})1 Y" _' h/ T, t8 L7 |) I
// dom挂在完成后执行一些操作0 J9 X! p# r) ^
onMounted(() => {8 _2 I3 B l4 L$ f( E; i
if (props.autoPlay) {
# E# i4 T; Y' L, Y; w, j startCount()
2 S* N7 p" x! f f; E }# g3 T! l- w5 s1 D. j0 @/ l
emits('onMountedcallback')
~6 ~% Y. ?/ r% L! Y- ^( r5 O) w})- l% C3 ^7 {) H) B
// 暂停计数4 K- w! O4 ]' q, f
const pause = () => {
) v) I) G2 ^+ ] n; x cancelAnimationFrame(state.rAF)$ A# t& Q. F9 e3 T M
}
4 `8 f9 p6 W& c7 ^& {// 恢复计数
/ ~- l( T) p g) m( P' I+ T% Pconst resume = () => {4 t6 X/ u( ~+ A( x) \5 {
state.startTime = null0 v+ M' x: F8 n% x4 x1 |
state.localDuration = +state.remaining
" W3 f' v& Z. [( I4 l state.localStart = +state.printVal
; x+ U4 v3 @% M" z requestAnimationFrame(count)9 f& i z( W {: ]9 Q3 v
}* J8 J' I" C* S* T0 N" h
) ?7 m/ T, {/ U# S+ S
const pauseResume = () => {9 V& y& w$ b* l! P( ~ Y. [
if (state.paused) {
3 O4 f/ c1 } Z resume()
/ v- {+ V3 Q, |( I8 ^# M state.paused = false
4 H8 A2 I! X+ ~% ] } else {: `) g0 s0 ?( A1 ~* d
pause()' T' H$ z/ {. f$ P6 B
state.paused = true P6 t5 o) V+ Z
}+ K4 ]1 k# }7 |7 E. \, _
}9 f6 ~* E6 Z% W0 G5 O3 N
! E" G6 t" Q$ t- L6 p3 d
const reset = () => {
/ O! {& p4 _: K$ O state.startTime = null A$ P) c* C: L9 {; ~6 S6 p( l2 l) _% d
cancelAnimationFrame(state.rAF)
; J/ Y9 N# U0 u state.displayValue = formatNumber(props.start)
* T; Q, h" o% w2 J( K}& d' z& E0 G c8 S* L
& E4 X0 J q6 x) D. U
const count = (timestamp) => {0 T M: c) ]5 p* \9 O' V
if (!state.startTime) state.startTime = timestamp8 L8 d+ Y+ }8 Y; G- P( J
state.timestamp = timestamp0 s: y# P0 g9 U: z6 ], R
const progress = timestamp - state.startTime
" p! v! x4 P+ v state.remaining = state.localDuration - progress( c: h/ k% V- E% x4 L
// 是否使用速度变化曲线$ f G1 H2 r5 O P$ c
if (props.useEasing) {8 Y; G. |, r% p& j
if (stopCount.value) {) T9 }) m# I1 d; R8 Q/ `
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
3 J+ A H2 }0 [5 t } else {
; q8 Y$ J& i2 h2 _/ ` state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)) s. _4 K8 E% @9 H4 O
}1 Z0 v, D5 d; |4 D- k
} else {& z9 ~" ]4 m7 ^8 ~+ c7 K& }3 \
if (stopCount.value) {
# m9 Z; o# W/ b V state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
. C) _1 K% e4 h: D# l2 u' m3 B, @- ] } else {: a# B5 c0 W9 f" ~$ [$ e1 d- G# u
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)* C) G3 Y: T8 R/ L3 k
}4 G% e9 j& s2 W( V" x R8 Z
}/ E1 s/ O/ \7 q$ ?' h' G9 w: x
if (stopCount.value) {6 C4 E M0 a! v0 _1 r" V6 o1 s' g" X
state.printVal = state.printVal < props.end ? props.end : state.printVal
1 E2 U; ` K! U Z/ r& c6 e } else {. Q" i0 j3 K% X+ G0 e3 N) \; Y
state.printVal = state.printVal > props.end ? props.end : state.printVal" r+ f3 \' i" P/ N& u% Z
}2 Z% r( u# P5 s. R1 g) N
8 ?5 W5 M( q# [" E+ d state.displayValue = formatNumber(state.printVal)
, a' b/ Z8 K# M2 _9 Q% @; }- j; b if (progress < state.localDuration) {
/ Z6 F8 s3 X% W" }5 z7 M: N state.rAF = requestAnimationFrame(count)
9 I8 t6 v' h6 E) t } else {
8 m' p! c4 f C# W# n emits('callback')
& `; ?2 v# N( K/ G% R2 p }7 f8 F4 B4 [# R# C& b8 p! D
}
4 @- G. \' Q9 ?6 G0 k0 }; R// 组件销毁时取消动画 y# O s: s5 ~. K3 V) r# J
onUnmounted(() => {) L3 f9 h8 K8 k4 t( r6 K
cancelAnimationFrame(state.rAF)
( }( R7 X4 \2 X+ P3 ]/ q% D, G}); D8 \8 G3 t4 ^: ]( `% i; g/ h4 o! O
</script>, Z! F) z8 C$ {* D2 q1 g* a# C0 n
* v& K4 _* y$ r
1
) k H) k O/ \1 p2
# c: i. x( x2 U( Q2 X# Z9 X# T3% u7 W7 h( ?) b' B, L7 e" Q
4
+ \$ g9 H7 n7 G2 t5/ _# T4 C/ F _- j$ b/ o8 t( ?
6
; U4 @1 ~' \/ W" |6 ~6 O78 v1 b, J# Z+ l- l z2 i
8
0 b5 G# U& P, t: l. ^9
- d4 K+ e$ }# { y4 ^5 K& k10
2 C) M+ o* e2 }+ s; o, h/ x11
1 a" E" W& l! _2 e7 Z12
/ E% D5 h- S. c132 o" T d3 z$ x- [
14" K5 ^( I% j% ^. s( Y; c
154 ^2 r/ V7 r0 H* ]4 p2 G
16% P- q$ F3 U0 t
17* K: C% N+ z% p2 O2 r) W
18
0 `! p+ D& v& v* _% k, |6 X' V$ O19$ \3 n2 f! t% ]2 b7 A
20
/ I' }4 I) R( R21
# }# z! q# J/ n* M/ ~7 T22- z9 ~/ z7 \/ z+ G
23
9 e/ E! h) L! F* C) g, U3 }24) z1 q; s. y5 m$ t2 K9 z, e n& X
25; V) e7 j. A1 }/ W
262 C! }. ?! H4 c7 R
27; Y5 G# P/ {. v7 Q" F
28
# i% u' J E3 D$ k+ c$ x29' p; P Q* C" Q9 a/ M3 [
30
9 H% p7 H( F7 l1 t31
6 C; N) i( V8 P$ X# H" g32
+ O5 N7 P" E9 x33
8 J: z8 w3 t! n" q: ]+ g344 y5 b+ F: P1 b1 r1 ^
35
& @* N* J' D( W- D9 g; C4 o1 H36; d2 _7 t5 } _ s1 W# O
379 T; C3 V# I9 A, s* x8 g D( X1 e. ^
387 ^, f, L9 b. T+ \# u8 ?9 ~
39/ I" l3 ~; g/ M4 y3 P1 Q7 y
403 j( v* r# ^ y4 E3 p( x+ L, \" m
41
5 X) K7 ^$ |6 `9 Y0 P42
9 W6 l0 E7 N+ |- S% P/ N6 J43; L- e _" u! l
444 J/ e3 a7 k& w6 k$ E, C7 j
45+ G* H8 q7 b6 i7 H, H) W
46
$ C$ r: X: r% o! @' d( @( F9 x( j2 b47) k- B1 h/ c, a% @ B' Y
48
0 z; x' {! K3 Q8 H49
4 s4 y$ V! B/ v/ E/ s: U5 p1 s& Q505 l; E( W; M4 [; N1 y
51$ w8 {1 w" t/ R/ i2 n% l3 n! ~9 T
52
* e' f2 A# w0 O( x$ b* {* S7 e9 N53/ X4 Z% I" [& a' s- ^( |$ B- |
54
/ t d0 O u9 d8 L$ ~9 Y555 J) u( j. t7 A* K: h K! U( `
56
- _( {/ u1 A& L; e- _+ k' K57% F8 [* [5 K0 A7 H- |
580 [% r- q0 h/ |
59
& T) L) p0 P! Q5 ?3 L60( w9 u( `% l/ K, L5 c
61
& z+ A) G+ t- ]0 \( w6 R0 b62/ W* k7 o! _0 n0 A+ g6 p& m
63
/ Z. @$ Q0 I5 n/ I/ b9 B8 g64
7 V) e) K3 F* B& l& _65* m) F) `! b3 x- k& G4 U$ {& V
66: a) T/ q" J3 O# Z5 r
67: h, q+ o- R6 ]# v% L
68
* x5 w' {% r) o/ C69
" I5 y4 M: R& A/ ^7 f70
/ T0 z: c3 ]& m71
# ?" Q @0 e9 E7 ?8 {72
/ R- S$ D* v" M9 [. x73# B! T6 X$ w. C: b
74: z% B2 R. O: J
750 ]/ a* N7 D+ G6 K! H
76
' v, s. s$ G W2 k77
+ c; R T3 u E3 q5 E9 k78# A' }7 Y* z" R' D3 H% `' L
79
8 z" W3 \9 Z# c" f. }80
( i( p9 j7 @' j81+ ~+ L' W6 Z: S
82* x( m7 P1 ]3 ?' p$ b* ]! C
83& R9 D0 d- ]2 ~) h* o
842 K! s" M; i9 V' X- U/ X/ I. o
85' B: ?, k9 u9 k) C$ ?! E) K
86* G3 R" @# `# x1 M
87) L+ n1 K. l8 A. b1 f4 C
88 u, o$ s2 A" _& T+ C
89
- t( x5 | ^' k& J: W906 ]0 h& E; G E: u+ f* O
91; Y1 w3 y7 M8 {; N# [" R
925 x4 k: P' c, |3 x! L
93
- D* {7 ? x: C5 E9 s( \# P. l947 H4 P2 u& P0 |' `0 J! e4 [
95( i! t4 V# N2 A
96% N0 t j5 L/ S5 R! k
97
: j' C/ }( j& b8 f$ D5 G* R98/ _, H7 B; B; S2 v
992 v( x+ V/ g5 t! `6 V5 L8 a
1003 h1 V8 w' W2 m& K v6 S# ]/ A
1016 H5 e N; P, n, G
102
7 J" I6 R! J- D) G6 D/ B1 T103) n% \1 t' C1 ^
104
$ R( F4 b7 T1 X105
; W& H; z8 E1 N* i9 v4 ]106
* t9 k& X3 U( m8 l1 u, ?) B107# J9 E7 x2 l6 R. ~
1089 B6 \! V& V8 ~
109
5 K) x' i: A9 {* F110
# G, }- s& `3 L3 O% b2 z2 ~ X1 J! [111% K" A+ `9 f/ S) q
112
' E7 D! W% P! E$ [, E0 e1138 a, \, \7 Z+ n( Y
114# U, i8 {5 R& w3 d
115
. `* T; j% m, Z o6 c; B116+ n2 @4 w; M+ K
117 m8 Y# l# w( C9 E
118
. \; y u, v1 F0 @% J2 C119
0 ^- B4 q! ^- S! W. J120
: E5 D$ x! X' Y121# ?3 g/ z. g" {2 K8 y$ Q. h
122( g0 v% v) Q& }* N
123
$ s; ?7 f: p& R( P: V+ u* W- f& u* B124
# H& u- F/ R$ ?2 I0 Q" Y/ z8 W125& v" R: q4 |- I/ q0 G. x
126% c1 Q4 h" i! c$ N* n
127
, t4 U: ~2 K& F: ~9 o4 @1288 n1 `& w* C- {0 H7 q3 T& W
129( `5 ~7 m* D6 ?9 a o9 i% m
130* w& b" F3 z+ [5 [# H- c6 h
1314 G) r, j `. u, b* x
1323 [6 L( z) q( P% t
133; O4 R! O$ g2 E& o% f) L% l3 h
134
$ }; [! T; Y5 U135; Y7 S' D$ K( R2 ]
136
$ j' N/ k! \8 J/ ^137$ t8 ^5 V7 Z, N h
138" I3 @. l u! b, c
139
& t- j# ~& { w! Z; b1400 r& N2 T1 ^$ i1 d* A
141
" c, x9 i: @- N+ R0 i1427 t2 b5 n$ ]% A( M1 U5 e, x
143- W: U8 U6 Q _* `7 h
144# ~8 A2 \$ c$ m; B# q0 l* M; O- R
145
- H0 x& c6 S* i5 w, ]5 E146( D6 E4 \) y8 [! |( E3 @" Y1 b/ F: \$ S* c
147
" ]! g( }, e% V1 r148& O) l) t$ E! E. i! C
149% g3 C3 b3 L1 J* w
150
. d$ R, i3 ~& J% \7 ^0 v" X! _151
# V" a0 @" y; _+ p* j0 [1525 N H I: h" S9 k' A& }
153* k; T+ w( M# ~5 K8 {0 @- g8 U
154( q9 o+ M- p% \' s# Y
155
, U3 V- W2 |4 {2 e7 [8 o0 E1562 z0 k6 O( I r7 h( y
157 I' ^% j5 O2 b+ V4 D0 B( S
158
% S! ^2 [; q- e9 c159! F3 W1 A9 m# b' h3 }4 E
160
. i1 h0 H% t1 z* _: M3 Q; d G8 O$ q161 s( j0 t2 o6 W" {
162
, z, e# h$ U" ^163: J, }: y0 T- @ `$ N# Q
164) y) S' q; ?5 I; b) q
165
9 ^0 ~# a9 ^& z/ [( o' x166
$ }5 R, C: D( G. ?; j0 u167
4 ]6 ]7 c5 ?! O1 O5 R168 u$ ?/ f7 p& S8 ` \
1696 A7 P8 x! z& A7 f
170" k/ L& W# a" L& p1 f( F9 e7 g
171
: p: T* z7 I# j4 c( h172
9 O; @! a% L) }. t173
+ [0 S5 w2 w8 A0 v8 l* [2 J3 x174$ S- R/ t( O9 D0 a. R
175, Y. K* ^5 M- B# o
176
% F% G. Q% u9 O$ p" T177
5 }6 E8 {% q a! F9 y) z178
' S. @% v2 G5 X5 O" K7 V' P2 s179
, V# [# F ]0 H9 D$ ?4 |3 s# _4 F180+ P V( Z) t/ t# X8 S, E, w% v
1810 `5 X& E. L! L0 N" f
182
& A: v. l# t/ ~ a; H; u% q; d2 Y8 p1836 k2 a2 h2 b- ^( P; L6 ?
1845 R" s0 X: X7 A0 W+ Z
185
& W0 @) P) S% A" \1 a- u# }186
7 f; }: `8 O! `1 {+ m0 S187
6 w1 `. t( f7 J. F9 z188
9 I; V4 P% Z- V' g @& F# f189
+ p, B$ z0 |! l9 ~" Q; V J190, E# b4 b/ ^* h- X( s7 N0 @
1919 {4 g( H- n8 v7 m: Q h- Y
192
* r- K- w) c- q* j; C5 \9 k. q+ I0 `# O193
* ?( t3 t; r6 {. W- r194
; K: r) M0 Q5 P$ I h9 [( i7 A) X195* P1 @* I, s P+ g8 ` R
196
$ a4 c+ G: x. Z5 |8 Q197
0 [5 P& m7 S* I) o/ E7 }198+ F# G/ Z4 s7 V s
199
; t* m: N7 K5 ?200# w3 T4 M3 j9 ~/ D. Y$ h, i
201. i) k- Q5 X* P3 I- C3 i
202
( w4 q1 G% N+ n5 f# ?总结
% q; w' c" g& |: |自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️8 I+ u3 c1 ~6 J
" d7 Q) d6 r& @( U7 l+ y4 N
demo演示
3 ]* B. ~7 g8 ]8 V4 B后续的线上demo演示会放在
* _4 s! m: k+ M6 C8 ]demo演示
' ]" X3 l9 ~4 }$ X完整代码会放在 x+ F, B) D3 g/ c2 d; U
个人主页' |) a4 ~6 S/ K! j# Y' a% f
; T8 ?! J2 X7 ~ J+ w* R/ |, o
希望对vue开发者有所帮助~* L5 m* Y. m1 k1 s3 r6 P3 _. a
1 ?6 u( M% o, u6 a个人简介:承吾+ v* Z# J; D( p5 y
工作年限:5年前端7 t4 l$ _ d+ f3 T+ O# V
地区:上海# F, W! \" A: b3 A% k' @* X! k
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
( T& u& @) j, s9 q2 {) W2 M7 a& J+ F2 p; d) Q1 P
! x/ Z1 r7 s7 N7 E$ k3 b% N2 I9 F0 W7 T6 v
5 R0 v; K( ]" i" U* z————————————————/ g9 | d% O5 g; z& V
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
) K" x# I& {; Y( K$ b原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
9 J, i! A; f* W0 [( @9 t( i! K: q" S* {1 T: D. M$ z
8 }) o1 ^; c+ I. S0 ? |
zan
|