- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566250 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175098
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效/ N& Q+ n1 u) M! T
7 j2 q: ^0 S4 u1 O8 a- M6 f, t7 y* V
前言
% \: L" u2 W wvue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
9 R8 {1 }+ j: W( QTypeError: Cannot read properties of undefined (reading '_c')
! I0 U' V5 d" p& p( [) @0 G1 |的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:* s; u5 ]- ^" h' \
) u6 u8 J' P2 y) f. _: ~% p+ z
; \; z2 K' j0 a& G思路: F2 _) w+ x1 W# \$ `
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。7 `& T: \- }$ U3 E# p' {/ A
% u* A3 [9 [( @- A, c* z
文件目录
9 z5 J, |" |1 ~, L
# f& [/ x1 }7 x* t) ^5 G9 W" e
$ e1 Z' }1 F c$ j% @" d4 D使用示例
+ n. [; o3 O5 g9 F5 `4 X$ @8 ~<CountTo
+ n" a0 z# T) J* e7 e :start="0" // 从数字多少开始+ X8 u9 I* D1 W& z. J$ r
:end="endCount" // 到数字多少结束
, l- y1 z, p2 n' {: B; u; p1 i# X :autoPlay="true" // 自动播放
& }( A7 V! p% t9 f :duration="3000" // 过渡时间
' w* C3 r- M! W- T. U prefix="¥" // 前缀符号
% F8 Y8 @1 o/ S suffix="rmb" // 后缀符号
" |- S6 h$ E- E) Z" w />
* R0 n" L" W u) K9 O- p12 A% e0 b- ]6 V- |5 t
2
( B |. x: R; ~9 p" I/ L* \3
c, K! Y# `* N' m43 f( T$ H& E( Q' N! k
5! @3 _2 L" ?2 }1 I t4 E
6! A9 v. y+ h6 ~! U3 C
72 b0 G% [; K3 |. Y* |
8
+ e9 b) } P1 E: J; h入口文件index.js$ n, `7 X3 @# Z6 B
; [0 p" F' s2 L0 ~: G& m
const UILib = {
1 g) g' k- }4 E- } install(Vue) {
0 A# w8 k& {1 L: y Vue.component('CountTo', CountTo)! Y3 ?: h# L% x
}4 Z) c; x6 u" d) k/ s7 H' N2 e8 Y
}8 y( N$ K9 q O6 N e& H
* f2 U' [6 \6 n5 l) F% o6 e
export default UILib
6 y& J# x! p+ u# ]$ U8 @: f6 u' x0 Z( Z' s/ W/ c; E
1, W$ g6 [8 T, _' H& D( S' I
2' ]; A! t- e) ]- H, G0 |& O
3, }/ F' X8 r$ }; M2 E
4- W+ w8 ^) d. y- d8 Q/ M5 P; N% ^2 t
5
+ K5 N2 y4 Y9 E+ j5 d e6
. T4 q& J. Y5 X& g5 k9 |7( X" T3 F5 K% K+ m) H, U
82 Z* A+ j- ~1 p. [& C& J
9
% O: v L6 @" q, O# L& t3 b" Ymain.js使用
6 b# }% ?$ _) M' y, e: [; l2 n5 Wimport CountTo from './components/count-to/index';
9 [ `9 v0 g" \2 a0 x# Z$ o, yapp.use(CountTo)
: _, }5 ~% V% T2 u8 [1
% ?( I8 A0 v! X7 d9 Q& G9 |2
$ ?- j7 C6 e3 t+ V6 X% @$ A2 ~- arequestAnimationFrame.js思路! Q u$ V/ |4 b" M; G- A
先判断是不是浏览器还是其他环境) b% k+ z$ [ z$ ~ h
如果是浏览器判断浏览器内核类型
! z$ N. ~, F- w! f- Y9 c0 s9 v如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器1 y5 h' @% @- Y
导出两个方法 requestAnimationFrame, cancelAnimationFrame* k6 C, \: ~. t; D" K: D& R
各个浏览器前缀:let prefixes = 'webkit moz ms o';
& C4 ?5 ~- o% \2 O8 c4 {5 m- A判断是不是浏览器:let isServe = typeof window == 'undefined';
8 L. B/ P; w# E0 [6 z增加各个浏览器前缀:
1 O0 R: [ E/ hlet prefix;
9 K' |- N6 \; X+ {$ W$ \let requestAnimationFrame;. x* B- |# y" l0 P# c) U
let cancelAnimationFrame;) U6 K/ A; z" z8 a, ]2 v' P9 K @
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
9 H% T: d# D- B+ t for (let i = 0; i < prefixes.length; i++) {! H/ [. n0 _5 ?) ^, _" j: y
if (requestAnimationFrame && cancelAnimationFrame) { break }& Q7 j# M1 I; ?
prefix = prefixes, G" W# d# Z4 f2 h5 ]
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
% t: s7 G- ]& Q5 B& l4 H6 B cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']+ h8 k* E: z' N, q
}
/ i S4 ?0 w6 e9 c4 c+ w; W/ W B7 N0 g) R& T& p
//不支持使用setTimeout方式替换:模拟60帧的效果
1 A8 l/ L% O; [. t3 \- L' A // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
7 s) t, f/ b# i! g if (!requestAnimationFrame || !cancelAnimationFrame) {
+ q W8 r0 t( [' m8 t7 q requestAnimationFrame = function (callback) {# L/ S, j' H% b/ G/ }: \
const currTime = new Date().getTime()
# A1 e; B: r0 r! f // 为了使setTimteout的尽可能的接近每秒60帧的效果( i1 N; p7 Q' U+ \" J9 l: W$ O3 q
const timeToCall = Math.max(0, 16 - (currTime - lastTime))# Y c8 w0 N4 T. D- Q- n
const id = window.setTimeout(() => {" V" I/ Q" P9 K9 |) t$ }# k
callback(currTime + timeToCall)
- e R) a1 s$ }2 d }, timeToCall)
. `( s: z: G# E! f! }* ?6 f) s9 @& c lastTime = currTime + timeToCall/ q, ~" a" l1 U4 \. r+ x
return id, }8 l# Z, f* C3 k. ?: W% J5 b
}/ E) z: {' j! x
! N( z: Z" M5 j' {/ z q& w
cancelAnimationFrame = function (id) {0 J3 x9 m5 d7 M7 C
window.clearTimeout(id)
$ z" Q- ?7 @, D }0 d5 P+ \ k% O" W* x0 t
}
1 c8 Y4 t2 K/ m3 l( {
" E* ]# c1 _4 y" T3 J1
+ B, H q! x$ W* O6 d/ Y6 V' Q27 K1 V; _) c7 i+ }7 D- b, @3 ?9 w
3) t5 N# R0 c& G) q4 T0 B9 |
4# O5 e: S+ M# _7 `8 Y; {5 |
5+ D# K0 w: y3 Q6 \; c5 Q1 L
6- G! p. K3 Y. s4 ]5 L$ _' j1 l
7# l! W0 B* V5 ]5 m% W
80 c) Z8 W) l" j7 v; R3 @
9
0 Z4 G# a% B4 l. [" j10 ]8 V v* c8 O; q6 X
111 k5 Q) H3 r; {% X" G, U- k, e
12+ V' @. h5 }+ S z) |; d& g
139 V% E S8 v! r2 L
14
5 n, J- h: m4 R4 L4 r1 W5 A- r# n9 g# P' |15
$ X& S5 A3 @6 Y# F; \8 u16$ p3 G( ?* r% P. w; R4 [1 Z
17+ }- u- `: T4 S$ U& h( e; U6 P
18
6 c# o6 Y% t6 f/ V% N+ V9 t" a19& y [8 l% Z2 a; ]. R3 Q
209 n, T/ Z! L( b, b8 X+ T2 M
21
7 U- B) ]3 U$ g9 ^22! I: R" G$ f$ J6 U- y7 Z" C. F
23
4 j0 f1 ?4 T$ m242 S1 V/ q \1 ]% M
25, e0 I6 j. r/ \3 b4 U& I
26
& w, @. Q& f+ L3 f! s0 Z! E270 p) e" c4 v& \& |
28
1 P% ^$ ]$ A4 D/ n# u& B1 Z7 |5 I29
7 h: s5 L) a0 g4 A2 F30/ N4 @! Y( K2 v
31
& D9 Y# ^4 p, G- v# c327 ~/ L/ z: a& s2 q5 V
完整代码:
7 `- L& E6 w- y; o# {# krequestAnimationFrame.js
& \: i: b* V( r2 i0 S. N, U% D
$ ^+ o0 E4 M% wlet lastTime = 03 {3 i# d, v% o T
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
1 Y) P7 _' G O" i9 W
" X' B" c8 X5 p& w1 ]. ?! q% Mlet requestAnimationFrame
$ E/ Q& G7 e- ~" elet cancelAnimationFrame2 Y. ]( y+ c4 X; J/ @5 F& J
" e @+ I5 x) r Z// 判断是否是服务器环境- g0 u/ C* b' y* G0 p1 l
const isServer = typeof window === 'undefined'
4 ]( ~& \% F ^" n5 k& [6 K& N' Bif (isServer) {8 f! e& N( Q( o; A* e3 E
requestAnimationFrame = function () {% f& r$ v# h: s& R! j* O
return
1 S7 D& }( x; J }) } U/ A- B: U. w3 n: s
cancelAnimationFrame = function () {
S8 k5 ]) h- S y1 X, C return
( D; H7 u) }7 T/ i1 n/ E5 p }
" |5 b1 Y4 v5 D" b( }6 H% u3 O1 c8 n} else {
- w* E) A) f- p, ^ requestAnimationFrame = window.requestAnimationFrame
" y+ e, {4 O0 O8 I# p cancelAnimationFrame = window.cancelAnimationFrame
+ ~- `4 U# K& M" x5 p1 Y _1 }/ A. @ let prefix# {& _3 K# P5 \- w% R8 a5 z4 z
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式5 \6 R ~+ ^3 o9 y2 M, [7 [3 E9 E. ~
for (let i = 0; i < prefixes.length; i++) {$ H& v0 B5 j% b5 V1 ]6 U5 l% }6 ^
if (requestAnimationFrame && cancelAnimationFrame) { break }5 f6 l* R3 [3 w' f/ `4 J0 `/ I
prefix = prefixes+ D1 w, E8 y1 w* q. h
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']0 M& K1 H9 Y2 N+ H5 b3 s' M
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
0 I9 Y2 s6 v1 g2 E3 m" D7 B }
0 Y" H l5 q3 E" h$ J
" L4 h0 f: M# y1 O2 g; V' U // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout6 N4 Y0 t; r2 E& J3 k o( j
if (!requestAnimationFrame || !cancelAnimationFrame) {4 Z; K# r8 p5 Q+ E% E
requestAnimationFrame = function (callback) {+ e" s: K& r/ t
const currTime = new Date().getTime()$ n5 }% p+ \8 y# Y( z' h! }3 S
// 为了使setTimteout的尽可能的接近每秒60帧的效果& q& h- a# h+ s0 m0 B- q" B$ |
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
5 D- K4 h" t: C! C! A7 v const id = window.setTimeout(() => {
' q3 J. k, }0 P+ t# F* c" ? \ callback(currTime + timeToCall)5 k! Q3 g, x8 R
}, timeToCall), e) U$ A- f) K0 E @) t$ j& ~
lastTime = currTime + timeToCall: R1 y" B3 b6 _: U' G- G. Z9 w
return id% W( X6 M6 w3 A# Q2 I1 D. M9 b
}
, L# F/ q) j- a' n7 ?7 Q! m& {* w, U, t" c j
cancelAnimationFrame = function (id) {, s: K0 S& X9 b5 s
window.clearTimeout(id) _% _% @, W w' ~( W9 |/ L; @
}
9 S/ X `# Y( U l. b9 S" @- v( m }- R- W9 E: p6 J/ [ u- x; b
}
1 i, ~$ ^4 K7 o* B- F% u& H6 {: \: @7 ^4 Z r8 B
export { requestAnimationFrame, cancelAnimationFrame }* L% k' S, s4 @- ?6 m7 l+ w4 d( r
5 W2 L$ E# a+ P! G- M# k! P0 g2 ~2 O) n
1
( Z" Q' l- G5 ? v% ~4 b2( H) j3 ?. N, |
3- U3 p# Z* K9 n+ t7 ]+ P
4
) \/ U+ @5 ]) ~4 }% ~5, ^9 S% G2 [5 T' S# g0 n& z
6
e- C0 e' \# ~1 E2 I77 u5 m" _+ q1 O9 I% |
8
9 f+ I6 ^3 f" X1 p0 d* P/ {9
_) T$ ^! |% t- E& n103 b, p! W* k9 k: S' }9 c- e* Y3 [
11+ C9 u2 ^ x z) w& q6 C7 i
12$ Z% B& P. B/ N) C3 f! C5 V5 y
13- }' l6 L6 f$ q8 N2 Z/ W
14
$ @6 |6 [! P3 v+ l! j153 O$ O6 o# R1 _' {, u$ {) X1 p
16& E, P. R' C+ b" l+ X
17
% D. e( x H% Y" K5 o- x8 L18; U X9 w1 f! a9 v9 O
19
2 }" v3 v2 @7 b& a4 p4 Q20
/ O" g4 Y. [7 t+ v, p! x4 z$ M0 |210 h8 Z, ?& M# e& s* R
22* h$ G7 R3 t l: N6 K3 J
23
9 E' F' v: P# m2 G7 M! E24/ h+ X6 U# ]0 u1 S4 f" \
25! P2 y+ d/ G9 T$ w: R, F. R
26+ G* K8 {$ y$ t+ {6 K
27' f) l# V& w& Z2 }; z" D3 H
28( g8 H8 F8 F) O6 t+ w
298 p6 i$ d6 D, {; _2 d7 P+ I) U& w: i
30
8 B0 Z$ e& g+ a9 B/ x7 R# L! V31
% N! v {! L" C/ |. L32' c+ Z9 J/ }0 P' ]
33# D6 q1 l+ V. j. N
34
- g6 g w }% V2 E. N35% o+ c+ ?6 J, _0 s/ u# e
36: p+ M% [6 `2 Q5 f) k
37
: c$ r6 ^& {: H& @; k1 [6 @; ]38
, ]. s0 E8 H$ F7 o1 Y& [3 [! e+ F39
8 Q$ U2 v) i4 E5 A$ w; v" w8 h40
5 z+ N8 ?2 c/ B/ o/ w6 _$ l. [41
( L7 R5 M' u# Z& J& r42
8 ^3 k8 }1 y, `6 B! f( F43
/ _+ _& ?+ M0 j1 O2 O( I2 d44
% k+ F/ L: ]$ F4 Z0 _) }45$ B1 }& p7 T7 [" v9 {' C3 c1 T z
46( R, A8 _3 }4 s9 i5 T4 m; y( `
47
: [" W0 i# E7 l& o% |3 t48
9 k6 H0 l6 D1 ]# x' v2 ^$ [; P+ RCountTo.vue组件思路
, J6 B( n# {- c% N2 z; x首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。8 [1 V- G" A" O( f
8 Y. q0 p, }/ x) M, r7 ]
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
1 S4 B5 P$ O$ P% w( O' o# Q1
3 ~5 y+ m' A# K5 D; u. ~" o需要接受的参数:
# n* s0 ~* t. @# {7 D+ e5 L* ]
* B" O( A% r' \8 Kconst props = defineProps({
9 B$ m- O8 L7 H6 Q5 ~9 N start: {' f6 e. A j* S/ e9 D
type: Number,+ d4 _& r* ]( Y% \: \' b8 a
required: false,
/ x) }" {( E4 ?9 J default: 0
: F/ @3 U, F! m, Z s% @1 q1 J) @ },9 M" {+ h. t* q( I+ k) O) d. z
end: {0 Z5 k! z: l6 [2 j/ O% Y V1 Y
type: Number,
+ Z+ `+ T' c7 N, ` required: false,$ }: d' j0 D2 t6 u ?
default: 0
+ I, w b0 R+ S9 r- i },* n: o& C( r0 M0 _0 H+ _ d" c
duration: {; o5 I- z$ P8 M1 V; O4 l. H
type: Number,/ T$ Q8 ]; g+ L1 X! J
required: false,( l: D; p: ]& s$ h3 X
default: 5000- q% R, v/ p K, c
}, M4 w, [* o8 Q* ~
autoPlay: {% M5 d3 x0 D9 n/ l1 r2 @
type: Boolean,
4 } q; B6 t, f- I3 w required: false,' ]2 q* |5 ]6 I0 d" i2 ]( F
default: true
$ W f, Y) _. |6 c1 U },* X1 b* T3 \5 e) \' y
decimals: {- k$ `6 ?3 `& M' {) [! ~
type: Number,
8 ^/ ~1 y1 T$ B: b& e6 A% { required: false,& p) V9 ]3 D; {7 R! ^ m" C
default: 0,
; g$ H6 s$ N$ \" r& O, T validator (value) {
# F3 u1 g# ^0 _. `( k0 d return value >= 0) R, ]7 S; @( i7 T: V' M2 Z
}
! e' N# }. V; G" D },$ {7 g U0 r- g1 c8 S$ k
decimal: {
O) F3 } @, s, m" t2 V8 X& o type: String,0 r ~$ A9 | Y% e
required: false,3 }+ f2 Q' m* x' x7 A ]
default: '.'
* t0 S6 @1 W* h _6 ~: k9 j },- B1 |3 g" e' l& B @. _- `. a1 J; i
separator: {6 P- h( H0 _( Y% }0 _7 X2 }/ B
type: String,
9 _" } F2 e8 V. Q1 N& b required: false,! ~4 J I$ X* w
default: ','
8 U! F7 h: N- W }5 J: r! e( ^# h8 l },* i. Q2 j+ j) r# E- I% P4 m0 r
prefix: {
8 M0 i y1 t; D& J( i2 m: y* n# \4 ?/ K type: String,
7 d' N J( j6 U9 Q7 O) ^- O+ C/ o' [0 V required: false,% F2 K4 }* Y: f# x- T& F
default: ''
8 \6 o2 l, {2 T },1 \% {+ T9 [- b& O3 {& b9 Q% `! v
suffix: {
* J: O1 d2 L4 B5 Z) a type: String,
( b/ N1 E6 U+ g1 A6 v required: false,
4 v, X' i* `. ?/ y2 m default: ''
9 M% L# M% J) u: R },% m( u- @" ?$ {. F
useEasing: {' O0 F/ m' h5 `' S9 c
type: Boolean,
8 A7 [& u8 U, J' J; U: o- O required: false,, H( {) X- R$ ^2 i
default: true
/ X# k$ Y( r- q. ] },
( S1 y. ?( [& k/ z6 Y- g easingFn: {
8 A' j7 G) |1 W type: Function,
- I" R' R. P& P' S4 N default(t, b, c, d) {
9 q$ u ?6 k& b% k" {- k return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;- }+ A3 V) G1 B& E
}
9 D+ [( Z( K" e) | J3 i- K }
! \9 j$ e1 ~1 ~: }& q* \})
0 m6 g/ \! |+ Z8 Z. [8 h& K1 f, l; M& `3 d1 @( n
( M3 H+ {/ y5 l
1# w! Q1 |5 L7 V
2$ T- ~+ R( `( X6 k
3 _0 ~; n/ \ X- w; O/ p
4! s H# l1 [# H( ]7 @& K
5, F( O r5 F, ^) Q; x5 Y9 ]
6 [0 T, z, J" f, [3 M
7! L* Z/ n/ R( I# m
8
2 H6 k( X! V6 Y6 i9
. }; W2 ?9 y0 ^/ S( e0 M9 P10
0 @, ?- ~8 y) O6 u$ e. i+ V11
% ^/ f' @0 T* s4 M9 m3 q( t, a12# _' k3 E" I. s) X9 B# U
136 ?& F7 f8 i9 X8 w, [" x9 [- t
147 P0 C& @2 P4 O! S( j. o. v
15
3 m- z: ]6 X! o, W0 D e9 U6 o16" g$ k' q* Z9 r9 M1 L) m9 C4 l
17- ?8 V0 _, H1 j
181 k1 l( g% S9 Q1 K' w
19
0 ^ s# E# k8 p+ `$ _20: l6 O% C2 P! `% j/ n3 _0 U# l
21- ?/ P$ o9 e7 v1 c
226 q6 c2 u. ^+ A" L3 j$ |
23" e p9 H. }% g- g$ w) L* W
24; T5 ^! r+ \) ?& `
25
3 B1 H9 o$ p; l; }1 W' }& E% a4 A264 z0 A+ f0 i& t- m" L
27
* i& l8 H- @; i) p28
, y! ?" q2 M$ q5 P298 M r% H9 M: x0 ?2 C
30
* X! ?- \, @# @& a5 z31. _) m6 ~9 p% D) Q3 |/ C- K
32
$ x G- S" X1 o, ~6 N33+ Q9 @) Z5 r8 H! {$ L) B H z- r
34
1 S9 y4 l& z# c1 @6 f# v6 x) \358 \6 z% W4 t2 Q; B6 b
36
+ |& D( ]2 Z. C# F37/ n+ Y( ^- D- S- i/ _& N4 g
38) \, e4 V4 O" _: a _' T6 [6 H
39
n$ A8 X: J% {$ i/ J9 d* `$ X40
- ~. n' |3 p* w3 v416 k) k& Q$ W9 ~7 q
42" h, `- U4 G1 C. W
43( E+ }! H4 O$ C w1 n
44
- A0 m5 N" k( ]1 Z0 k/ k45. ~5 t0 Q! H0 g5 L
46/ u& T2 z" `& @+ F5 F; I* V) r
473 X9 j6 ^: b3 X% O- q8 e% z4 [: A/ p
48
3 G3 b/ L( ~; P1 D' | F49
: i# K3 l) B( w# J504 Q' O, P: \ Z3 e( x+ E
51% @7 b: N1 z& h% F- Y
529 ] C7 X! C) O( p$ w) ?
531 T0 l# Y0 k. U6 ~' H
54( g I3 K# |; x
55
$ K* C1 u8 t! {56
% u* E( u/ y5 e& {. z) e573 f. h) V/ M* m2 `
58/ l5 S: R% h o9 [$ ]/ d
597 W5 j& X4 p3 Y2 x a# C
60
; z4 k: f( a& M$ l8 D9 t5 d! X61
9 X4 M1 x& `+ V0 a62% R$ ]* J/ y0 C+ n
启动数字动效0 [4 V( u4 J4 O' T7 p/ `! X
5 K) \5 M$ z, oconst startCount = () => {
% J4 U& a+ b! i9 b- A state.localStart = props.start
0 t) l+ L' f8 o' A state.startTime = null" E# T8 ]' ?0 p
state.localDuration = props.duration9 N/ Z6 _$ m7 B8 n
state.paused = false
9 \8 U t5 P5 K" e state.rAF = requestAnimationFrame(count)3 f6 o* P8 E. `/ ^: p2 r/ R+ N
}
9 i. u. G. A' d& y8 n( ~ f' T! r4 j1
2 Z4 z6 u9 k* C5 w; e7 ]2
3 G. i( ?* p7 w' J* J3, [1 U8 e$ f; ?+ m
4" }# `" j. {1 v/ Z, K
5
/ f* _! o8 u O64 T" |1 \4 g+ ~! n5 o8 w( l
7
) h. n* K. e% z+ o1 g核心函数,对数字进行转动, x2 F9 R1 g7 m Y$ B
; z# V. G! A& k4 F
if (!state.startTime) state.startTime = timestamp; A) ^+ ]: s' k8 L, {
state.timestamp = timestamp
5 E' q5 c( I' {; ^0 p const progress = timestamp - state.startTime5 X$ j/ Y% s* X" Y: i* @
state.remaining = state.localDuration - progress
9 C- K+ h" D2 D4 ~# A4 q // 是否使用速度变化曲线+ L$ g: e/ S1 \. g' z( {+ n
if (props.useEasing) {
" R9 A4 n, k i. E; [2 w if (stopCount.value) {
9 ^9 d8 x) l4 Q0 d6 ? state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)0 M) U$ n' O5 P/ J& E1 b
} else {. m. c7 u( W8 _6 d7 A* f2 S- d
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
4 @1 C$ k( v; I }
2 K; c4 o+ f) |* p" O2 i/ E4 o4 k } else {
. k+ I- a. G4 t8 l0 f0 G( P if (stopCount.value) {
0 P. N) V5 Z" n5 P5 L0 K state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
1 }. T! D0 p# s1 n& R0 V8 e% } } else {6 ]# N9 r- q: D/ C9 a2 d
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
( z* E+ K, m' X# Q3 m& U; a }2 s. A; w6 M# u
}
5 ]; l* x0 s8 q$ N& l if (stopCount.value) {# Z" l C( F7 E
state.printVal = state.printVal < props.end ? props.end : state.printVal% t- e& ^" H3 o, ~/ E: l9 `3 p$ H# m
} else {
; T6 d3 M) Q7 S) O$ l' O state.printVal = state.printVal > props.end ? props.end : state.printVal
" Y* X4 A! H1 g- Y, P }' A2 [( `" @+ v
3 a' X4 g0 W5 A% `7 A state.displayValue = formatNumber(state.printVal)8 Z- M3 h v, F+ ~
if (progress < state.localDuration) {
5 G6 Q- ], M( X3 U% \+ l6 I state.rAF = requestAnimationFrame(count)
( [4 U# V! J% E; q+ Z } else {
. t) F* T. D, }, d emits('callback')
2 P/ p7 e) x6 G; H, G5 J }
& g* ~. I3 E, m! n6 w0 ]$ l( _2 |; l}) b& e6 ? ~7 W) Q# v' \
# ]+ d$ P* R% w: M
0 y1 ^* E o; N6 L: O
// 格式化数据,返回想要展示的数据格式
# _" A, q" ^1 I6 u! U* `const formatNumber = (val) => {' z8 H9 e& x, z, V( S/ x* d
val = val.toFixed(props.default)
' A1 W" H* [8 R val += ''
8 O u M1 ^. p0 E. z7 v const x = val.split('.')
0 ]# s, q. F) P: u let x1 = x[0]3 H/ I# s0 ~8 M1 p& K
const x2 = x.length > 1 ? props.decimal + x[1] : '' N7 y' p6 t" y- P
const rgx = /(\d+)(\d{3})/! O3 } \+ H+ e' Z
if (props.separator && !isNumber(props.separator)) {
% u4 B5 l$ h( q( y. _$ h% u$ d- ]+ c while (rgx.test(x1)) {2 R# o8 J* k7 d
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
8 o: \9 @& w4 B3 e1 d+ j }& z) P/ Z" P0 y: E% d0 a; |- S
}4 R. @) U$ v" q R5 I" m
return props.prefix + x1 + x2 + props.suffix
7 ?3 y* r$ x4 Q! n}9 n' w& G7 {: e+ ~
- Q0 }+ z# b4 X: A% T6 p/ ]1
/ y! W3 i! G1 ]; v- P* `2
4 Z9 h, q4 f( r2 R2 b! V3$ T4 V: {: N- e; b) G/ Y6 a
4
^- R( h& q) C9 w- P, x; \5# `9 O; Y _$ L3 I9 `5 a6 W
6
; \% ?, b' _7 C) ~8 `78 @7 x; u, X; J8 i/ @3 o! o
8; O" x9 ^/ _' B/ b5 R% l
96 R- `# S+ W2 }
105 d; f, d9 j' V0 h+ X& F y
11# j; c- n/ y0 I! H4 m
128 Z) y& B& k4 T0 D e
13# Q. R, H( D% j* \2 ^1 K0 O( ^+ _, ^
14
) `; D, t6 _/ [9 @2 ~9 @155 `! \: g! i7 G4 Y
16% g! m! q# h4 J; H, q+ M6 h
17+ D; r0 V3 @' v( H! |2 C# n
18
' y& y2 g0 X _8 ?2 g" M) s- H" ?* a, }19: `, d1 j- V+ `& z
206 e/ z/ Q! ~5 P. b% ~/ u
215 u0 d7 y! K7 P
22- t8 e( s$ y5 J6 T9 N1 P9 B- a
23; o5 y& B( f2 M. I/ q W2 E" ^7 ~
24
- A' k# r) Y, e5 K250 W6 l. I7 L9 z& c+ }5 u
26
; l1 O1 q7 D; S0 G; K270 q% m I: Y4 a0 B+ r( L
28+ B X/ a% Y1 D8 M( d+ o
291 W- i9 R+ H% u" Q
30& U5 {( U0 m% D' S7 v1 p
31+ O5 i* b% p1 a/ V6 ?
32
7 [0 t1 H& X2 x. A33
1 H: u$ J& H, l1 `4 J34
3 W/ h5 T' e/ d( g1 p35 c, a5 s0 }1 A: M
36: ~) h$ G9 o0 ^8 c
37
" T, U5 C) S6 y38
6 h7 y& v* z$ L& c: \, \39; L' F% L" r9 ^$ D P; y/ v
40+ c0 Y7 [7 \2 K3 ?2 l7 d4 ^
41
$ G& V3 [ F6 J2 _/ j9 w! h42
' {1 p" }5 |! l! K4 ^0 Z) M9 G) s2 z; S43
. R e' q3 r: O4 w8 g6 @# p* D6 j# X44
# e# }$ V0 W* _- O9 Q9 v45+ {( g8 L) F( P1 n I# u, d
46
* r- ~; U; x' Q8 W47* z# @# N. w; R% ^8 h3 f
48
" Z8 D0 H1 f! X" g! B( V* ~. J9 N) F取消动效
5 x$ p, I1 n7 s
9 D6 g* P1 Q) g9 U// 组件销毁时取消动画
; W' f0 W# v, r5 d7 g- g7 _onUnmounted(() => {
, V% B5 C. [3 t cancelAnimationFrame(state.rAF)! Q7 w! K$ y# ~& i* U6 ~( z
})
* u8 Y+ ~9 Y: N$ t. g; F) b1- W7 S2 k7 ?4 V. I
2
" \$ s( L3 K4 U6 h3
% g8 S' Y! y8 v p+ Z& L! K4
7 `" n0 g% w$ e0 J: {! B完整代码
- G( `2 X) V% w+ e$ V0 i4 n! s d9 L5 V0 K" j$ u
<template>* i. k( D2 r. w; m
{{ state.displayValue }}: ]4 x" e V$ R8 f" ^
</template>4 N( i. S: R% T6 l/ C5 l( X1 [
6 C% U- M8 d M4 p1 S9 L! T; ?<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效& N1 B; i8 _' t/ G5 ?
import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
! \ [) m+ @: i+ Nimport { watch, computed } from 'vue';
& D9 x! ^6 \( ^import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
) H* u. w/ I! H// 定义父组件传递的参数* g- x( \( g% |' t
const props = defineProps({. @4 }) }8 I& K }7 _( Q7 m
start: {6 F, m/ N7 S8 A7 V5 V9 y
type: Number,
0 d" E4 i/ S$ H( T required: false,
9 Q3 n/ M3 Q- Q5 V/ G" W default: 0
s5 C( e/ J) m4 y' _# a( H/ A },
7 F1 O. f- l* j2 j. ^ end: {, @# K, c% ]6 Y5 d
type: Number,
5 W1 Z; X. V! M4 A8 k required: false,
R7 e# F E( m1 ~ default: 09 A+ b8 W9 n0 l- x W7 Z
},
& f8 O0 m, E+ m duration: {# o! p% V! M3 r4 G; v8 @( V/ b
type: Number,
2 ~$ @3 `: v) }& ^( G2 `# H/ A required: false,& e; S) T8 E- H( J, n) K2 `$ z
default: 5000
% x2 i& |9 @: G2 J# Q& K },
' \; Z: E/ A; _9 z p autoPlay: {
3 Q3 O2 l5 C/ N+ E type: Boolean,
5 d( k$ p; L c, P* H I) ^+ o required: false,0 Z! F3 I0 d" s# K
default: true
8 B! E6 Z2 g* w" a$ ^; r },
" T: q* T" j3 `; c3 x( P decimals: {
$ z( C! X: Q" f( ^) A3 \# E& P' ^ type: Number,
# p( I) G# P/ R. p, }/ J/ l" X required: false,; ^4 ?/ `9 s8 ]2 U
default: 0,; l& D8 L; S& C, q r
validator (value) {4 Z; U8 L6 ^2 R7 ^5 G
return value >= 0
4 {5 y( @. s4 `8 z0 t" \, t) W8 y" h }
/ T2 K4 C' n+ C. M" o },, X% z: J3 C8 D/ ?9 L* b
decimal: {
! A9 a& m8 q1 ^. q4 h8 k# R type: String,
% x# `% M' l5 r. I required: false,2 H/ B7 R' x( [
default: '.'
, j" x! j7 L8 S0 t },
! S: v3 s$ Z# j) m* Y separator: {( ^2 n: O7 I8 y) w3 Z
type: String,
# X: h9 }' |; `; J required: false,
; M% t( F9 `' x; y* b default: ','
5 E, j" W4 K, ~) e+ g4 y- a. B },
2 b: \* v) A" A( Q8 h prefix: {
1 q" y: O5 a D# q( s: j7 k type: String,' V$ X4 z' G% S4 z+ k* p! j
required: false,, t9 H- j3 t! V4 A1 }' e& [; e
default: ''3 l, T- ^+ N& l- v' t9 A
},
2 j) w4 y& ]. U/ S8 f# E' y7 b1 N7 J suffix: {
, C1 ^. l+ ~. S8 n4 f type: String,
( E P5 X4 e& D1 ` s required: false,
0 ?4 l8 [7 [. ~( z default: ''
' P4 Q" M* l' k0 b3 i* S6 G },
5 U8 }0 p: [1 t. [ useEasing: {) J% D# Z' |* d" M6 u% r: }
type: Boolean," t+ w) K% R6 X4 I
required: false,
5 A- f- g" G/ c$ T' ~ default: true. U& B. Q# e( g1 p5 Z( V* V
}," W+ H! B: {8 F! n: w P) T/ j
easingFn: {' M: j/ ^- f/ l- a2 p1 ?
type: Function,
" W% C' h- N, G, b) s( r default(t, b, c, d) {
& u# A! D$ B( R0 b% ]" N return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
7 R# p8 y" g0 o" ^+ S ?$ ? }* G u. L5 [2 ^0 }# X' A/ T
}
. `$ @2 [) P3 _! @+ |})
|) G2 t( |& Y G
4 @- v* q( r% d. r% @const isNumber = (val) => {
- A! X/ m, k% p6 X/ z return !isNaN(parseFloat(val))
, ?) O* _( Q: Q4 B, Z& k1 s0 C& C}
9 H0 {+ ]4 z X( ~' B7 T) N% I* i7 J
+ B& z- J9 l4 K$ A// 格式化数据,返回想要展示的数据格式
2 I; ?, B9 Y! [/ lconst formatNumber = (val) => {2 W" ~$ @8 K* Y" p) i
val = val.toFixed(props.default)( @. [; C$ v- }( p$ d
val += ''
2 @$ p) c2 N. t2 R* d/ r% d; m const x = val.split('.')
3 C: g& o* h6 j9 p" u let x1 = x[0]
4 [& z! N5 i7 h7 [! q! B const x2 = x.length > 1 ? props.decimal + x[1] : ''
+ w2 b0 ?! K" i, k& e7 q* y const rgx = /(\d+)(\d{3})/
3 l% B, v+ [' N2 g/ z. D' j if (props.separator && !isNumber(props.separator)) {! d5 O( K6 p2 @6 A' d5 H( n, D; k K
while (rgx.test(x1)) {7 J8 [5 g1 }# R) `1 W2 S, L
x1 = x1.replace(rgx, '$1' + props.separator + '$2')' A; l9 |+ @. @: ^# D$ g
}
. |) f4 L; }0 E/ x, h$ [- y* b6 x }
" A3 V0 b6 m" j- A return props.prefix + x1 + x2 + props.suffix2 p7 E$ O D7 |+ y, `
}; C) L/ q) Z$ x- T$ ]; c
# E( _; G2 |6 p( l: m
// 相当于vue2中的data中所定义的变量部分4 c$ q+ V2 E3 Z- M4 T
const state = reactive({3 w! A8 \7 M+ G1 L5 R) R5 T. W* i
localStart: props.start,
3 b( Z9 v% Z. D* V' _( Q& _ displayValue: formatNumber(props.start),6 h1 W5 x: x. E5 Z3 a" h
printVal: null,
s7 g+ T8 M/ n; O paused: false,
3 O Q+ {& h- H% D0 k localDuration: props.duration,1 ^& g+ y! g* h
startTime: null,
( `) r. `- f* Z" { timestamp: null,
3 Z$ Z0 l& {; z remaining: null,7 e2 x$ w6 k7 f9 W: d+ e' d
rAF: null
# p0 {, Q5 q+ k1 h5 `})
& `" `+ W+ g1 ]7 T5 E/ m
( |9 X" n% c0 I4 Y) m0 @* ~$ w// 定义一个计算属性,当开始数字大于结束数字时返回true
" e4 s& P* U' u# V4 x6 Dconst stopCount = computed(() => {& r8 @8 ~. g' m `) \. |
return props.start > props.end
* ~5 y' P- l3 c9 @" r})
, m' [) r1 v; x; z: `// 定义父组件的自定义事件,子组件以触发父组件的自定义事件' o* ^% C% a, ~7 M
const emits = defineEmits(['onMountedcallback', 'callback'])' ]( u6 s* A1 x& Q3 s4 W
6 Q& k1 x$ `' v4 w; W
const startCount = () => {8 x& Z' {: E( {: x2 r3 d3 ?
state.localStart = props.start
6 G& R n& G9 P8 U state.startTime = null4 Y7 B* ~5 b+ T5 V5 K. @
state.localDuration = props.duration2 ?4 D, d6 b7 L2 L P `
state.paused = false% h: Q. \# w5 B
state.rAF = requestAnimationFrame(count)( ^9 u' i0 h! R. }8 C4 u) ~
}2 d3 n; G) _5 I3 Q' G* p8 H" T+ _
/ v* ~$ l; N$ I# k8 t' e* {' ?watch(() => props.start, () => {! |9 O+ I- s/ @) m: ^1 b" H4 K
if (props.autoPlay) {
0 ~9 K# w2 ?& H startCount()# r3 T, }1 M7 D4 C4 G
}
' Q( p, G- ?" ~ X})
7 n |2 f. w4 c8 z! t7 n) k) }# a, u; ^& @
watch(() => props.end, () => {
8 F* S \) A p) s if (props.autoPlay) {
6 W% o; O2 t; l2 m+ D8 v startCount()' O( |; B8 j8 T- s- ]0 u
}: C8 a b; E0 Y, h0 e5 E. E+ ^5 y
})% S, s1 L1 {* D v7 U
// dom挂在完成后执行一些操作1 j, F0 o: g6 {( S% p
onMounted(() => {! |1 T8 z; Q+ N5 B8 a
if (props.autoPlay) {9 P$ A% m3 V5 e0 N
startCount()
7 F+ K3 ]: z7 x6 e }
3 j/ q8 W) X! S! w- z: r6 C6 N4 z emits('onMountedcallback')
# t E! Z, ]: G% s t7 l})
3 n9 ~6 H7 B* q( p( e9 p// 暂停计数7 B& q# E" M Y- j) f
const pause = () => {) o1 z. j7 x( P- l4 j9 l) L* n& w
cancelAnimationFrame(state.rAF)
, l6 S& j' C" J, L: M}
) r% @, A/ |, a& d$ J// 恢复计数, L3 J/ N3 B( Q- ~" ^% g( Z" U' i
const resume = () => {
2 s+ [$ L& e4 S1 ]2 i state.startTime = null9 f; z7 \0 O6 V2 C- @2 `
state.localDuration = +state.remaining
: E' `& ?( C4 O state.localStart = +state.printVal" j( Y) o3 }! @: D# \8 w
requestAnimationFrame(count)
$ {" W& q! `+ d}
/ d$ C- L! \$ `6 T& j' L# L8 T
7 z! F0 {5 B0 u5 lconst pauseResume = () => {
3 N& m: b: e! n0 }+ I: N% `7 @ if (state.paused) {: J; d6 r0 i3 w5 C; _- C7 P
resume(); S7 N7 v( [ |3 q" H3 L
state.paused = false
: x0 ], w- u# c7 ^6 ^0 o: P } else {
4 c. n3 X) C1 t6 q& J pause()
' F+ q7 o0 R! i3 a& ^( p) P4 n6 m, |# B state.paused = true0 y9 j9 O3 ~& h1 k
}$ B1 e- q8 ~+ T+ N/ ^
}5 w& M4 O8 a+ o/ D6 q
8 o; v( R3 f4 P- X
const reset = () => {* `: D* K5 |8 M2 Y1 q: n
state.startTime = null
: }# e8 v# c* {" P" D1 D cancelAnimationFrame(state.rAF)
) I* D4 r7 K" R& H. F state.displayValue = formatNumber(props.start)" s) J; h" W# a+ V% }- f) H8 _2 M
}
5 ], }5 r$ t- s6 i- f2 o' f
; G5 |1 G) E- ]9 a+ t, I2 ]+ u8 Wconst count = (timestamp) => {- n; z6 w1 c' \1 b" l: X G. P
if (!state.startTime) state.startTime = timestamp( ^: N: f; H' M% `& V
state.timestamp = timestamp+ i( J% a# N2 l6 r# P; v$ W" t
const progress = timestamp - state.startTime6 t$ L, ^* r5 k+ ~& q8 p# x# ]# n
state.remaining = state.localDuration - progress
: H1 {$ r6 F7 Z // 是否使用速度变化曲线
0 R2 B/ N" @$ S7 }: R; I2 E if (props.useEasing) {1 H2 {1 M% S) u0 r$ \5 z: z. ?
if (stopCount.value) {
* o3 Y& p4 S0 L1 T2 e) U* m state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)1 j2 c M" a4 F0 r& C# G' @ o3 g
} else {4 @) S* K. d2 Y- K1 }
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
" A$ d3 ?8 s6 m% j6 }% V, ^ }
8 a6 k7 W/ b! G5 _' y- q) G! } } else {2 k5 W5 p5 l7 w: y' V, {4 s
if (stopCount.value) {
, k1 ~7 E- C: j" p8 |9 ?, ` state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
2 B; `6 F, g+ c6 v } else {* C j2 Y$ B3 z$ J+ W4 c
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
' E& h, k. h9 @4 i }
8 |, B% }; [: T6 V }9 J2 a" z3 x5 a) y, |4 I) E
if (stopCount.value) {
, q! d4 J# s) G! |& e state.printVal = state.printVal < props.end ? props.end : state.printVal, @+ k* F! g3 O& u( t
} else {
- q& P! U. a1 d) |9 `3 k% D state.printVal = state.printVal > props.end ? props.end : state.printVal
. `4 [2 P3 J! W5 n& F }
3 e9 u j) p8 p* g8 w' v' K4 ]. _5 N D- k6 \, s/ A
state.displayValue = formatNumber(state.printVal)7 x6 f$ b& n( K2 ^9 c
if (progress < state.localDuration) {
5 X7 Z |( a3 s0 P7 `1 v- } state.rAF = requestAnimationFrame(count)) o% X/ A8 E" a
} else {
: Y! b7 o! [ P/ N) `" O emits('callback')
. b; C9 p3 J4 t }
; I+ }6 X+ h( T4 h: A3 L}7 L8 P+ M9 B! v N6 C
// 组件销毁时取消动画7 N j' H, L+ {- D2 P" D& m
onUnmounted(() => {2 @% h5 q# N1 r0 ^3 k
cancelAnimationFrame(state.rAF)
$ q* K0 I3 ]2 D' U7 y1 U& _% w" E})
. ^4 p \+ d% h$ S</script>
8 u$ ?: N) Q' M$ f& d
; V6 p; k* Y: U" l# K% R3 z1, Q* S- a* G7 W! v) Z
2; q6 A% _$ U8 V+ g3 ~1 q
33 }, F! P0 h% C+ k \
4
" S; r# D9 d/ m* c1 h' n& ^5 h, L59 O7 ~" ~# S* p7 W: S
6, n4 d+ V1 x# w3 j6 v4 v
7# L l/ P8 K5 F$ _ f% E" a, _) F
82 n+ Y/ z e9 E- g5 K
9( {7 Z/ W% w, {
10
U3 ^* E& U- }# [; }1 C- {1 M9 c11# f3 _: @+ x4 F/ f9 J
12
+ y5 @% i' u: P# }; s5 {3 [13, {3 l+ I* R/ Y% [$ H
143 i7 `* H7 T7 n. b3 G
15
1 @9 I4 u) _% ^* n- ^169 @- O. K8 M7 y# ]
17
* ^! F6 | D* v- d18- |* J+ Z% Q u M7 n! j( [
190 H6 P4 u# \* [1 J
20
3 ^* m2 Y a" I" ~# }0 x8 i218 Q0 i4 A/ @% I% z6 I5 m5 J
22
]; `/ z. Q. ]" U. k6 `4 o23
% Q: `8 o7 L. w; r/ F2 `1 V24* E" i# o5 U- D
25
5 Z3 U! J$ q$ z" L. |3 s26
. `' C9 v$ V4 P t27
" ]4 R1 T& {6 P/ t; Z* a28' C! O) ]) C O" `
29
$ n( m: h7 e+ A$ x6 W6 x. K. r30
2 G+ L3 r# R: W; r0 ]1 Z: X. p316 q1 }1 N& x% ?2 i9 v$ e4 h* A* W; [
32 _ m5 q4 |7 T* r1 Q
338 {1 ?9 @7 C; }# `) H M
34
+ N/ f+ d6 I# C) ^' Q35# p" Q8 M8 _+ k$ V' \
36
& i* ?7 r8 V7 x8 p37. h x; ~2 O7 u7 n; w
38
, ?$ l' l+ |# W; e' ?5 i39
' T2 Z6 s) W& \0 Z8 m9 h% U40
4 @) N0 _. Q' n" _4 ]! T# X1 k417 ]2 [' @3 D- }. m3 m+ z1 R
42$ f$ \1 I& p/ b; L2 t
43! T7 X! r" B0 p
44
- i" v! z* {, D# Q45
% R' S- o+ f# w s* W! ~0 E0 ^46& O0 o( `! M+ G ?$ C
47$ W6 N9 W+ C! E: k6 \
48' G2 ^* Y! v0 a( H5 o
49
; C' `3 Q0 x1 i0 U$ P50
2 Q, w3 q6 y2 t. H0 `" c- o518 m- h& Y2 I& {* {# ?8 f) e B
524 `1 S- w- O$ e) G: J% K
53; R }% S, l! h) o y
54
7 s0 M7 t3 \ V" B5 w. j" o& ^55
# b# g; B# x: S1 h56: j# w: e. c3 z Q, I# D' F
57
D# t% F, v( D588 j$ X9 f6 m0 V" K' o9 x4 P
59
' x8 H. v; g* Q$ M0 K4 W60
* j- o, r1 Z5 a8 h3 [61
8 \* I: a! L( S. o( e% ^62
9 e m; _' I, @" g1 Y" f63
! J; c% g* h1 D2 V0 ~2 l64
% D' z: e! q9 `: y9 a$ D2 Z65
7 j( t6 B7 Y5 R) X n6 B66$ H6 y# U' S) ~) Q
67
! w$ f" W+ ]; h& Z* K( M& Z68
. |" T3 ^/ |6 d69/ J' @ D6 {$ z. x1 a& |& H$ G
70
/ z, Z% U0 }0 B71, i/ _* b& r6 n8 ~
72
4 a# N! Z2 x* ~" U8 T73( s1 y: g+ A# L3 j. \% @. q! K& `
74
5 ]4 }' y2 M3 R; P4 v75
6 \2 \* y: E1 S$ F/ y76 | V: v! k5 _* N4 }: a
77
) t# r7 v% P% g% o l6 h- q0 S78& H, O" N# x0 f0 {) P2 |2 u
79
0 n. z, I2 u9 l% d+ C80
4 _4 h4 r5 O7 i* j9 k0 ~, [81' l% c# h7 Z% c9 P* Q" g4 W( a! m3 w
82
$ @3 S; X* \; a! v3 E83$ l/ G r" {* o, C
84
7 z; K5 Y; [5 i# B! ]85
3 n# r- |& h" h$ D86
! H% b7 Y' w8 @87
3 T* A2 `# D, n( k2 A88# |& z, K K8 D; L2 j1 q
89
* u4 ^5 r% V2 m& b( d" Y+ c90
0 U$ \5 v( h" l, g% l4 M91
4 E4 C) P% D; Z8 R; t7 o92% w" N( w: a8 [2 B: }
93
* o; J0 s1 [2 T942 V2 I' Y( i3 i* f, r
95
6 E$ G5 H0 c; W4 V0 O96( B n% Q+ [" z/ B( Q
97$ K+ r' q8 |, R
98
3 }, B4 I% I6 M9 @; t/ x2 d99
7 _2 V, s) T2 w100
% v \7 ? w) l101- ]( Y4 ~! X7 _3 N. J$ ]/ P5 G
102
; V: ]6 i7 B' u9 o$ g103& M6 L9 x' n" @. W, {. O
104$ V( N& g% Q5 ~+ m" c" t/ v
1056 U: l5 `' H; y. M* V
106
! x: r6 z: D2 C7 p* h! P3 r107
5 n- F, K5 T% K5 F108
& d8 s4 y! P' n3 T" e109. U2 ? Z1 A/ D+ }, ]' ~) s* X
110
4 J6 d( d5 u- q9 y0 p6 ]9 \& i111! i8 Q w8 J. P9 f, Z
1125 w2 b0 Y; Y/ \6 B) |/ c6 l. r
113, [" I$ h0 U" h: X4 U* p- Z
114) L) a( s1 @9 D0 ?/ y; x, ^% ~
115' i. h! v; M# y: S
116$ [" u1 b& R( H: W: o
1173 [! d5 }# R! n: V* ?
118# F" Q" P/ A7 Y" |3 {" k0 X
119
! S' C, N u6 l6 Y$ D120
1 E4 [& y9 E1 _/ s7 y" @- V* ~' ]1212 m& |1 \2 j! Q7 q6 V
122
/ I' y& ?- ^. a, \1235 L' s9 x% C; ?, I" Y7 [
124
" f8 C h' x I- I; b7 A8 y1258 x5 \3 D' B5 {
1262 d6 i) k4 e9 c* U& a. s+ J
127
- y/ \: R1 `. V5 k: [# ]; V( g& [4 g128
% Q4 [6 t+ K7 A& ^: C; m! a2 Q129
9 y# Y: l# w. `130) Y$ K& q: \' F& o
131
6 j- k# p( T+ U1 u, c- Y9 G132% n" H, V+ I8 V: Y/ T/ z
133/ S; M$ Y: K7 K& _! t. y. Y
134
% k: [ B r8 w i7 W135
# z+ q& r% d3 m136
7 W. k: K. Q6 d" ~" ~* |6 c# ]1374 a9 ~5 o- m1 i- n! c
138
3 y! E. ~0 M' y2 }& p/ R139- l& K$ O. D( S2 L1 @+ x5 q1 E
140, v" Z, @3 ^/ K9 e) G+ U
141
% a+ x2 z5 w/ a+ M3 c* A142
! x0 k& q0 K( J1430 D) Q' w% d7 i: N) r) }
1447 m8 s0 X! R R0 R9 W- S: G
145
; i! ]1 u* g; I* A146
; y" A* |3 c6 n" h9 ^$ n147/ b% s0 P( \. ~# |+ z
148
. B% Z0 N2 V! x0 s5 y149
o$ H$ S# s! s. @1 ]6 {. w150* o. s# i# i7 b. Z( V! ^: E
151- p" S1 @# f/ S
1522 a! x" }, ~9 `
1531 i) k% w( V1 k$ Y* Q
1546 k& t+ [9 F( L; A7 ]
155
2 S0 z( j0 o' J& B) f: z6 T: T6 v156
' z4 O. R! y( j1 ?+ J* @157! E5 h/ d6 F/ V% a% g
158
' C+ i; P z1 S$ i1596 b$ G) h" I3 N4 c5 \$ @5 G. h
160
$ ]4 c! X. n+ e6 ^, ~/ p1 @161' E% i+ j. @6 A3 G
162
: \ a: [8 d0 n' |" T8 r |163
z+ k1 W. C3 Q# L4 e' v1642 a: z l! I; N3 h( e W
165
% f8 i+ v. R4 i0 Q7 f; J3 s8 e. X( R166& \& T. u5 {2 K; n) e5 D0 ~( U& w
167% _- s) m. A. [% l* O/ s! P
1681 Z0 G, ]& \3 d: X' J4 @
169# G, g) V$ s3 ]" W5 _) J
170
9 }: [) \ b7 h. k; z# b7 |* K171
6 {/ t) ` Y3 E$ w" Y! w172; b6 A$ B6 M; P( j' |
173
) ?# L# s: c8 A: j. L174
2 z ?- T( u8 X" N% V175& d. v, o+ U2 y0 D
176
5 f% B) q' Q4 J+ }# j2 e& [7 Q177$ T, H2 x8 Z) h; P9 X
178! j" L% F# |$ E; H2 q" z) n
179 e- y" c0 V& ?9 N
180/ V8 g3 I& u0 G, k( `. Q
1815 `$ w+ t% R$ c
182& z0 V4 E' [& N$ v1 u
1835 J2 L% N! C! J: w
1845 ?2 y; j1 }9 z0 x- u
185* X) W! F3 r4 r/ b
186
" T) @! ^! \% w- `% l( W. r* {1877 x; @- ^- c: b* F
188
4 x4 u' Z6 U2 U4 r; u) C, x1894 Y: J2 V/ t- L. D: [2 a
190* i' y" Q0 c- Q
191* P! E! b; K/ {& U, r i
192
6 G# ^* Q( J" K0 l. C* p9 k- D193+ a4 c/ ?& z3 g, U
1946 |) X) X8 m9 e+ ~( |5 r1 W
195
. X( _2 D5 Q1 Q4 B) `1964 ^' u6 ~: ?3 `5 C
197
" [4 `* [& Z: Z' z9 b, u; D: _198
% P# q2 F) a+ D9 G0 D' l2 Z1990 x! T i$ s* |$ Z/ a5 z
200
4 q' P" K o: m; l7 ]201$ X* Q% W4 N6 J, U; d$ s4 Z) Z# f$ D
202+ C7 l. b! d* F0 w; d; n& Z% T) ?9 y
总结& z s8 t- Q# o' T5 l+ ^" p
自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
4 ]9 f7 h" h# `$ u3 ^
! I+ c1 Q# {6 t$ ]/ ~demo演示+ J3 m7 j* R- J# Y5 F# O
后续的线上demo演示会放在; S& m6 B$ C! g& }- u. `6 ?
demo演示
" S t8 a5 q7 m8 T完整代码会放在% X s* \% r: H) o3 R! Y+ x7 D2 ~& S; i
个人主页
. { W9 n7 u( K
; ^! j6 ~& A2 p% L# {+ [+ [& e. M( e希望对vue开发者有所帮助~/ {$ U5 O3 ~) ]& K0 L0 A- P
9 ~5 N; M; ^( m) I
个人简介:承吾% }1 @2 A) m6 f8 W8 R% {) E
工作年限:5年前端
0 ~+ x) l0 z# Z8 u+ D. }0 E1 r地区:上海- B- H. a# k9 u9 w; I l
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!8 A, a8 E+ L5 r; P5 H4 J
7 h/ p1 X" ?6 }7 R; P7 k8 N2 m& b
! r$ h& D, t. V; v% [2 X3 j) Q2 e; ^7 o' k5 j7 h& X. ?
/ D$ `9 s% j, O
————————————————
6 X$ D" a/ d5 ]7 ~* ^0 j- n版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
9 `' E1 Q* o7 v8 m% g" y: d原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
& d: Y5 G9 ~9 v( K `
# X; j3 w! x# T* Y' _ f. d6 @$ Z: ~% a5 X9 T& t1 C* P
|
zan
|