- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 558490 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 172920
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
! N' \3 G# c: e4 k J+ p1 I5 {
1 d# M* ~0 K/ d前言" i( ]( j, Y6 a
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:5 I ^3 P4 Z( k4 t; O4 J
TypeError: Cannot read properties of undefined (reading '_c')
4 j/ U0 R) i U- d" V2 P# L( ^的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:# r+ {! U! d T' y$ ]1 ~
' r7 ^2 ?3 v/ @
3 Z. \% j/ e* K& {思路
( O+ c* |7 l- @使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。8 [+ U- ~% H4 F
0 R4 X4 q+ z0 L! B文件目录# ^7 e( a; y' n- S, X4 A
8 [* |& G' e6 n& Z. Z) J
% U: X! C! W9 J使用示例* C- ]/ g6 `- {+ }, N
<CountTo; I# V) }1 n/ j- @5 W' @$ b2 Q
:start="0" // 从数字多少开始4 S/ `" `! l0 G1 s
:end="endCount" // 到数字多少结束! J; X" z1 O2 Q* e3 e l
:autoPlay="true" // 自动播放) t s/ T( G+ N2 E) U8 A6 U
:duration="3000" // 过渡时间3 X0 v6 ~$ p+ ~5 v. p, v6 I, O4 P
prefix="¥" // 前缀符号
$ E) h+ J( Q# T0 Q% X; P suffix="rmb" // 后缀符号$ d( ^6 @5 D: I& A3 Q! M
/>8 b2 w5 A$ u- r: _. z: `: y5 S
15 I* J& d8 A& ^# b" P B
2! x) y/ M, q4 {& A+ X) Y6 g
3
9 l- \% X! i7 A: r3 _4
' S4 a- Q( b! D* b$ f5 D3 h5$ o( ]& Q$ h5 y' H2 a5 u" _) q. p
6& ]. B/ Q* @ k* j5 ~
7+ P0 X+ w/ Q3 C) G5 e2 l
87 x7 V8 y& t1 i5 N) r3 d
入口文件index.js
6 ~3 R( V" r$ Y/ ?, |. F1 g: S5 y% w1 p, N! u2 D) J. X
const UILib = {% p* h* y7 y7 o0 w2 _6 m f
install(Vue) {
: ?9 j: |# R F5 T) m Vue.component('CountTo', CountTo)
2 |, t: `* h% ~ } I) H' R3 E. r" r9 s# s: F) S2 L* H: e
}
" Z- b+ w: H& \+ r% _3 v& q6 P4 D3 a
export default UILib' @; X* k" Q6 P/ `0 T# q- d
5 T) [! r" V% [' e8 I: L1
/ V- x6 j2 ]/ p2 t/ @3 Z* W21 V% U, {" n& e# e
3
8 g7 A8 ~. {, o4
- n7 r. `% Z6 Q( y% f5
4 C' [1 M5 d+ r- ?6
( N% {! D9 _4 T% u) D7
6 M0 Y) c0 B6 E3 L, F4 w89 B) e" H! }. h) \. ^4 E0 J- W3 o
9
- J# w3 T, m* S8 ~6 e& xmain.js使用- _( o0 j. s3 _: z1 Z2 z3 T
import CountTo from './components/count-to/index';; i- B* m0 g6 h, U' G0 G" K
app.use(CountTo)
' v/ @ G. b" G/ K1
$ m X" i0 h' h5 \, g2
. @( W) W; i+ ~1 t, X0 X" qrequestAnimationFrame.js思路
j+ C5 K L+ I; @. J' Q先判断是不是浏览器还是其他环境
, \, q/ E, K4 T+ O. E如果是浏览器判断浏览器内核类型
1 y/ L. B' o: h2 G& u) P/ r如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器; E+ G& d' V0 S1 p, o/ y
导出两个方法 requestAnimationFrame, cancelAnimationFrame6 J+ A8 U& ?2 t; j
各个浏览器前缀:let prefixes = 'webkit moz ms o';( l, f0 c/ O6 N
判断是不是浏览器:let isServe = typeof window == 'undefined';; Q* ]" u4 G: Q5 j0 {* S0 I
增加各个浏览器前缀: " p* o" p/ Z+ M
let prefix;) I G" L; X! r% z
let requestAnimationFrame;, K; z2 ]( K* g# G2 L
let cancelAnimationFrame;
8 c, k" [ f* a' T0 W2 {// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
2 O. D# I7 E' M* J+ j( k for (let i = 0; i < prefixes.length; i++) {
( R. J3 \* m) m8 c if (requestAnimationFrame && cancelAnimationFrame) { break }
* y k1 V) |! n0 c, a1 X$ n7 k prefix = prefixes
: P5 m& O9 v: v0 o) F requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
& E" v! E6 d, E( \$ d cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']# c% C7 B' i" a% f# N
}
# {1 L% e9 P6 K( f% G! u+ ~3 [) k$ N2 t! z
//不支持使用setTimeout方式替换:模拟60帧的效果7 J3 ]; j; ~2 d: `
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
* _: a4 z6 i, c! X& X" P! m if (!requestAnimationFrame || !cancelAnimationFrame) {0 k' o* R# k: D, m
requestAnimationFrame = function (callback) {1 v* v- X- t; D# t0 W! O) t3 {! H
const currTime = new Date().getTime()
4 `( a) S' [8 X! J& f0 a // 为了使setTimteout的尽可能的接近每秒60帧的效果
6 r% p) q; R6 A. U1 l) D const timeToCall = Math.max(0, 16 - (currTime - lastTime))! H- C6 `5 M8 K3 j. v& N& b
const id = window.setTimeout(() => {0 r' E; Q* g* {& E' _4 |5 P0 k- W4 s
callback(currTime + timeToCall)4 a3 i0 j: \8 O
}, timeToCall)% X! E" W. O( `/ W
lastTime = currTime + timeToCall
# X( E1 ^0 r, l- P. J; H! D3 d return id8 U0 O! } b2 O. L
}0 }$ D" i# z0 T1 H4 d# \
$ ?8 b4 r6 ^5 {* c& \ cancelAnimationFrame = function (id) {# Q4 S- e, ?4 t: n4 I
window.clearTimeout(id)
" W4 c- r9 H2 k3 ?2 Z/ [ }# L6 s3 B/ `% L
}
% @9 L) v5 j: ? J H: \
7 n8 ^( ^4 M6 g N) R3 j- C, h! _1: N+ I3 x/ A! k! _( I
2/ Q" W' k" W. L! H g0 Z8 [) K
36 {1 f& t8 Z' y
4
; G' u! N! m4 n8 `5: r+ Q3 e6 g1 k4 k- n
6
9 l3 z/ [$ Q' l4 M- b7: y! f z0 o0 h
8
+ ~. M% V; x' ] r. E* x- \9 G0 D3 _+ N& c+ Z% L, g: K
10
! x( l' m4 ]* e8 f3 U Y- T11
$ r+ i( z" E$ }. a/ x' Y/ O12
1 Y9 }! W5 b4 N# |13: t0 B# }: U8 t, q
14+ L0 H7 R5 Y0 t
151 I, X. W7 ?- h) G) L6 _
16
! a( D" y- s9 s" |% m- W17
$ l6 ]4 W+ X1 a18
6 X/ B& t$ Z; B" N2 Y, U19
; w- d0 y( r' S8 X203 e9 c" J: Q+ t* e( {6 v' P
213 I4 l C/ f# Y1 X8 N
22
2 ?/ i- R, q2 u. Q. r \234 [1 H& B7 c( t0 R* |2 e% r( X
24
5 S; j8 h/ s5 g5 g. Y257 k* v) B+ A; @ g# |
26+ R3 ~6 k5 G0 D4 D* J
27; m% Z% m1 d; B: p0 g4 |1 R
28
) I* E8 ~! m( L7 m/ R/ \- X! {299 U% G. ?* s3 A- F, a# w
30
# p1 A7 m, K, o312 O2 x h' t+ B6 n
32
" o4 e" ^4 j; c" ^$ c; Q完整代码:
! Y5 n/ p4 R: H$ S: h. ErequestAnimationFrame.js
3 A/ n) \ Q3 E: `3 K/ d
* H$ q6 b' W6 ]let lastTime = 03 T+ P1 b7 F8 N& \; \
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
$ F$ M" |- `# B9 Q% A
; u5 S! V/ a8 x+ ylet requestAnimationFrame; S- ?( L2 L( U3 e
let cancelAnimationFrame
" f- p. F3 N5 g" M- N4 W
$ v9 a: D: @3 D0 L// 判断是否是服务器环境6 F" F# x: [$ I* g
const isServer = typeof window === 'undefined'
( Q1 A4 P1 G, `if (isServer) {
3 a) S6 b% w/ D0 Q1 S requestAnimationFrame = function () {" `6 t8 Q3 l1 \, U9 b, h/ S
return2 c8 @. V/ s% O" t8 _6 E0 w# A
}8 n0 H& L2 g8 ?: W0 H2 L" `2 _
cancelAnimationFrame = function () {) S1 R( U+ L" P
return! J9 l+ p" f- {/ i C B( N
}' \9 t0 y4 B& ^. [8 |$ h; A- _( F
} else {
3 ]8 I' E( J) g1 X4 R* w requestAnimationFrame = window.requestAnimationFrame* j6 `& Z6 f& E" ?, }% ~" H( p
cancelAnimationFrame = window.cancelAnimationFrame. |" U/ X! r v g5 k
let prefix; ~/ k$ N5 j% i# h6 o( z
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式7 U. H8 N3 e. N' Z
for (let i = 0; i < prefixes.length; i++) {
& }# O4 a2 F" H" O; h! t: D c5 p; T3 U if (requestAnimationFrame && cancelAnimationFrame) { break }6 r3 G$ {' c. f% x" j+ L& o
prefix = prefixes4 l. e! B" s @) Z5 L7 L* ?2 m
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
5 I$ S$ c; v4 W cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']2 O! o, C# a% k) Q4 |
}
+ Z) e& Z% B' E$ H @
0 N) U L: E/ g" l; C: Q // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
o# L R( _; r$ I) K if (!requestAnimationFrame || !cancelAnimationFrame) {
: B8 A* E; M7 z requestAnimationFrame = function (callback) {+ u: k) \% ?/ S: g9 c9 N" _1 f
const currTime = new Date().getTime(), T5 Q) }1 X8 T6 S
// 为了使setTimteout的尽可能的接近每秒60帧的效果! w0 O6 q v7 b$ l# E2 ^
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
4 i6 n/ z3 Z8 | F& z. y* g const id = window.setTimeout(() => {
$ S, E* r$ U- q+ I0 |& z$ V! m2 V* G callback(currTime + timeToCall)1 n6 s, w* q1 l! E& Q) N, Q- i
}, timeToCall)
/ K! h1 _$ i% |- h+ ~ lastTime = currTime + timeToCall$ d/ K3 }- @1 P; ]5 E- x
return id2 b9 V6 D0 F/ L" h& \$ W: O
}
7 B; @5 P! m6 I! p5 T% H
4 `) H# e) e5 @8 _* _ cancelAnimationFrame = function (id) {* Y0 A0 a: {1 B
window.clearTimeout(id)
, p" K! t, [( L( h# F }
; Q$ y, F( S- x4 c d8 i }
# V9 G# b+ h* u0 W} F1 |: P' U- n8 t
! G% B4 x+ C$ nexport { requestAnimationFrame, cancelAnimationFrame }
% b8 J1 Y! u0 T; T- }6 {) c
6 p6 {. _& w. ?1 a# P/ E7 V* x$ S6 i" s( x9 @ F
1
% g( ~2 \" ~9 @5 U2 o, r0 |2
. N+ U4 v. z4 L a6 C3" n8 z8 l! r, @9 [$ W) |
4% N5 a) ]! o, g+ `& ?4 q
5( C# \+ P6 v/ v) |4 r# `
6/ J. D; N q! v" g: o4 E7 ^
7
* Q/ E' x" J& i& P* G' W7 R6 }8 o; F9 \, j" D6 D3 h v
9
8 L; i7 W. u: g4 \+ L10
7 \% K+ e- p9 c0 d8 f+ b% c" Q11; j* }; ~" H3 _4 l5 _3 r
12
{! x3 p, K, w9 A13& M8 ?7 ^/ u' i) z
14$ O& W9 W( l; z5 S( i9 R6 {* _
15
% [& F! s& W$ x16' ~; k: Q A3 x8 k, O
17
" ^) ?3 \/ N; x- T* X; {18& }# Q: a- R! b- G* \6 M
19
0 Z' c; B% ~7 W# X8 A4 M20$ H4 Q8 F% D: _# V' H" ^! b! p
219 U# M6 i+ v) Q; V
22' a' y: M) q; _ h Q. X
23' [ z& O2 i1 q% z
24
8 ^# ?6 {) ]$ E; X5 q; B$ R+ O' M25$ P/ v# X; `# ]( ]8 l
26
' q- L. L1 I3 z, k9 M0 R1 m27
: H5 N2 S; E" P5 {% @5 ^286 ]' h2 B; ]! ~, t' ~) R) [4 u% Y
29; j% {/ b7 Q, E
30" q c p* B8 m. p6 `7 ^
312 @/ [/ U1 l& a& q
32
c) X4 }7 n/ N( Q33) P3 @5 C2 V2 c* h3 B: A
34
; J/ l6 y! [2 M- e3 t5 t0 b% C35
8 j2 L T& D& L" m' ~( G, W( h. Q5 N36
3 k3 M$ @5 t" R3 ]! |/ X% u8 N37: o1 t/ b& v9 s( |2 O6 Z$ t
38, N0 B4 O H) y' c8 d
39
& z* {9 M0 i; [2 r( k40" _4 e$ }, k; L2 {) q/ O
41
+ {7 `3 {1 O. A' X2 s/ [42, s0 N( _7 i# Z* a R; W
43) `! y) j! n9 R$ v; ]
44
* z$ v* v7 l* i' K9 @, d* `" W45
H$ ]# t. f/ ]: ?( z46
# ]; n" c1 `! H7 ~1 @47; N) X8 A; q. D6 m
48" z8 P, Q+ T$ H+ T$ U$ \* A6 t# c8 [. w
CountTo.vue组件思路
! u! [4 F( `, X( x F首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。 m! E# j1 }8 z. P
. j6 ?. b: d, N9 v- Z引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
R, N. P) W- [# l1- E% |1 f9 s, b/ h1 I- D- Z( W! k5 t7 }7 Z
需要接受的参数:& @0 Q/ `5 Q, \" y& g1 R
* E/ b" w X- Q: v1 v) A; A8 T9 N( r9 F7 K
const props = defineProps({
b4 S2 E z- D, X start: {
) G- S4 W1 ?1 i, |# ? type: Number,& Z9 {3 q) m; M& r8 r( r7 `* M3 S5 Y
required: false,
3 B( \4 ]* A$ {0 p' C default: 0, L& m: G$ \9 F! l* y! p* o9 q
},
. W; x! p0 O! R- d$ X9 F end: {. @* G ~# ~" w' I. ?3 Z4 T0 N* e$ P+ d
type: Number,0 r% D/ m" j9 a9 S
required: false,) q+ w0 p, A+ v: ]2 U
default: 0
6 B% n/ }3 t6 u7 O& p },
% X- e, S' V# M( f' {4 X" |- r duration: {+ ?! Q7 K3 A9 U9 Z4 A
type: Number,. I5 t# i$ @% \" ~) R
required: false,' f8 E2 |8 T1 d* t
default: 5000
' F9 T V6 n4 s; A },
; l6 `5 F* B% u R# {" V! | autoPlay: {
* ?2 E( _8 o0 b* [ type: Boolean,0 p1 |4 m2 }; o0 E# M( l" f
required: false,! a* R$ c( Z8 f9 d0 S; v: l, ~
default: true/ S. v K; W9 \8 f8 n% J
},
$ a4 j2 n2 Q5 Q( M$ y. s decimals: {- P y& J* r5 O+ X6 {0 Q
type: Number,
! |$ h- L8 O% e9 O: L9 ]! Z required: false," V4 C( a* d. Z
default: 0, s4 @2 q" y; B' q
validator (value) {
1 o4 {8 Q3 M# V/ ], ~9 H1 C4 M return value >= 0
, ^: t6 m3 s% R1 G; ~: Z }/ a* z# @6 Z" f* ]: s8 x. a# S, ^, g
},' C7 ~4 P: g1 @5 m" z* d4 r
decimal: {
8 W g( K5 x. m type: String,' x( R- L* h1 W$ b) u" }, R
required: false,
0 O6 s3 Q7 F& I: }1 q default: '.'9 M6 T4 Z, \$ @, I8 p1 P
},
' E. ]: `! `/ l& c4 j separator: {: }0 d; L* b, e
type: String,, w; k: G+ H4 |* v
required: false," d: W. c. q+ {5 I1 y* s
default: ','
9 r" s C5 N- l/ J8 L. L! w2 m }, G. e1 i; x1 v$ O7 y8 Z
prefix: {' |# P1 d' w6 \7 A8 i$ P% F( C
type: String,$ [7 `+ G) j5 T: J
required: false,
& B) z' j6 X, [; m4 h- p5 s! L default: ''7 q: A' ^) e' O) E
},1 B& X+ ^6 S" A+ ~
suffix: {
. }; B) t3 P5 S4 { type: String,
$ v) T, B/ ?; V! d/ D6 X( l# O9 z required: false,
5 w3 X$ p7 e9 j% t5 K default: ''
3 l4 l3 r t l: l/ K+ z- P. \ },/ e$ M. W1 c0 h5 |8 m2 h
useEasing: {4 B2 J+ l- q9 G! X7 r3 r- |
type: Boolean,
! B# \6 @- }/ l5 D required: false,) _" ^( R# m8 v7 N6 C q1 M9 Q
default: true
/ c/ y+ Q) b0 {# w9 R },
- v6 H3 M% M) v& u easingFn: {* S* _( }! \7 y# B2 a. J4 h/ f! M
type: Function,
/ i2 z, d% m: U% k; y. A default(t, b, c, d) {- c) M+ K `( z- k0 L
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;) |# H& ^% s, x) w5 C- g3 x
}" A. Q. L0 ]8 v4 V7 l" Z
}
( L8 `; q. Z; \# v})
! W) H7 b, V* O D# Q: o1 Q& b1 |4 w% u3 \0 e2 `" m( K% b# p
2 |8 Q5 X! F5 M7 H% f. g10 F) J1 |6 m/ \1 N" `4 s
20 C2 a; }" s/ e3 z
30 p" I7 @( a3 |% d- t7 v9 k6 ~" \
4( S H8 n- }- e% h( q8 b+ ?
5! Y% {9 x0 o0 p1 P% t( ~
6
0 s6 C7 D& F& [/ y2 ]8 ^: T7
( f2 G! v0 p& o, O% ]8
9 Z7 d" L& G' s9 l+ |9
" P2 Y* Y# q \2 \. M10
( c1 c0 b1 t& B! G+ M) @11( t; L. B( R/ h
12( O& i& @, y, G% m0 N
13
; M! w! F0 y, o* V; X. v142 z9 @! s2 T7 w, b' C0 l4 C
152 c; h9 E& w, c h# p* f
16- P% B0 s- k4 Q7 x
17
# n5 B2 D4 ~) m( G: ^* h18
- ], Q/ T; E9 V6 O+ F+ ?# ]! j- D19
- b- T3 c- @- s! H1 v2 i20
1 ]: A8 d1 Q) u6 d. ]6 `21, @9 f; K' G$ c
22; u( p z) g6 O3 |
23
3 A# G7 l: a0 O5 C241 h& @6 K, I! o' m- G- w3 r
25
6 B; {9 g) V! ~3 R26- k& T+ r; q6 Z1 ?* {9 {+ `
27% G3 T6 @% y: d! Q& s
28
3 k# M) o+ }# H: w6 j29" F9 f! V/ _$ P2 Q; o
30
. l6 A0 _0 d% f) y: L! j31
7 K; u" H4 Y/ c2 x32
) W5 b. ^6 k4 D. p# g2 X33- t4 X. {, J5 ]4 k1 R
34: j$ n$ e; |8 F: w8 A; O/ }
35
+ D/ B# C. v. L! y1 ~4 y/ A366 K1 ?6 w8 ]! y& |% U" F$ Z
37
; Q, L! Q0 e: O4 Y2 T38
8 Z, X) @. R6 t0 _; m7 O1 X9 Q& L- w39
! z' y) E( ?+ ~! e0 E/ U" G40: a$ [, m, d: Q0 ]4 G1 s1 ^' Z9 ?
418 H8 p/ c. w0 H; {
420 Z3 t! Z3 n& s- J3 Z
43+ P0 E" X5 j( p+ k6 e7 ~0 U
446 z+ z% [$ g7 ?; q& y. d7 R
45+ J3 i7 S' p% j* H- p! h
46" ^* M l2 N& A! i9 ]3 N
47" f3 Z8 D: w$ h$ }* Z+ {, J7 |
48
+ Z @$ v% D4 |49
. @! k! N. B# Z50
' d# B) @! T/ o' _) ?5 _' I51
2 z3 |+ C) ]8 C* g: e; W52
( t( e& g2 ` G0 R( s53
" l. L, ^; `$ T$ U54
% `4 L9 f, W/ o. v- m" v55
2 U, h+ `& Y1 G' O! p( B* q56
1 y) O& _# g2 Y; S' p57
( t" v0 x+ ]8 _6 t0 S$ `58
2 A2 u( f3 n' G: {% [5 @59
! K4 H; S; z/ m3 l60
% s" m# O; C2 c O+ v7 @8 [6 y8 m610 N/ x' v/ }1 E
62
. U5 k* ^9 d! B( l启动数字动效
- @ n/ O5 J6 u* R) j+ Y' Y j: |+ p, E7 [
const startCount = () => {
; o! g( U- l% `3 m' L( Z2 Z state.localStart = props.start A2 z& Z" o Z% r! ~
state.startTime = null
0 z6 `" _1 y" M state.localDuration = props.duration
+ W5 E5 j; N+ b) e) f4 Q state.paused = false" {+ ]; L7 t) n3 a% A9 S1 p
state.rAF = requestAnimationFrame(count): B) Z5 O3 T8 Y, }1 D$ d
}/ m5 I6 F6 C. q) U5 E' C) A6 I
16 r: O6 Z* j- M, D. m t1 M. K
2
- q( c/ i7 Q+ J0 X1 d* r O5 ~3
8 ^. ^5 y; t& V0 Z( K* i8 U44 i7 W6 H* y% H( J. M) T* i6 M u
5
" m, `. D K. ?. y, Q& c6
7 x! o: z; `0 S71 a- z1 X0 K: E! E
核心函数,对数字进行转动
0 _ z2 p/ ^; D5 | D! h7 B& p V: _& c
if (!state.startTime) state.startTime = timestamp
, b8 Y( U8 F1 @; W! t H, u { state.timestamp = timestamp
9 A7 |1 |) ?* h0 J3 t1 {( p% i* z const progress = timestamp - state.startTime( `4 v) P5 n5 n$ ^6 `- U( ]
state.remaining = state.localDuration - progress
) s! d I3 [ J& d. X* } // 是否使用速度变化曲线5 S! q' m2 o! g; H. |2 d6 C; j
if (props.useEasing) {, F% Y6 y3 w; z/ M& T8 e
if (stopCount.value) {
6 G0 X1 H3 o1 `0 f! F state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)" c' H6 H: S0 |* ]( P
} else {
: i+ c- w. }, F7 z5 M3 t state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)7 Z# ~/ u6 H) G/ R
}. \* K7 p6 _% ~; r
} else {6 O2 V# ?6 o# G& @! F/ {1 @5 p+ `
if (stopCount.value) {
& Q& z9 v0 T9 F+ L) b8 \% R2 Z, w state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
% X- i+ x: i0 Q: r# X3 p } else {
W* v" b( }% }1 n# v. v' n7 B state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
1 n# Z$ t( s5 U8 H }
& _7 @8 X$ X { E }) ]9 O2 h6 X/ v4 i
if (stopCount.value) {
! J( Y T( M( c# C# h9 v4 b state.printVal = state.printVal < props.end ? props.end : state.printVal1 l; z4 V9 J! Z, k
} else {0 ~6 [0 o+ M+ F; ]0 v
state.printVal = state.printVal > props.end ? props.end : state.printVal4 h+ F& {+ v4 J: G E7 J) I* t4 G
}
v- p( D; A8 h0 X" @0 X2 w7 `1 X
state.displayValue = formatNumber(state.printVal)" |8 }; }. f, _" L) T( m8 [* X1 z& K
if (progress < state.localDuration) {
& t& \ \0 z/ q: Y; t0 y( i state.rAF = requestAnimationFrame(count). F( [/ y: F4 T s; i6 W+ z% O) k
} else {0 |6 v3 `( i: z: d0 M' s
emits('callback')5 r- I4 k- K7 ?
}6 L. K- E& c6 O' D# \
}' f+ ~$ f6 s/ Y& _, w! m
& T1 o2 @5 u( c }( F# z* [
0 P" _6 I+ x3 w6 H# v3 P, d) F
// 格式化数据,返回想要展示的数据格式
6 i8 T- a' b- ]* i9 Gconst formatNumber = (val) => {
# x; s9 {8 ^5 d) l& [$ p& j val = val.toFixed(props.default)3 w: O- o/ Q" V7 w- v3 _
val += ''
) P) m, G) I( |+ h: s6 ~ const x = val.split('.')
y7 v( |$ H, | let x1 = x[0]& t/ W9 g5 X( Y' f. ~ d' s
const x2 = x.length > 1 ? props.decimal + x[1] : ''
4 d+ ^6 R/ }8 U+ h' U const rgx = /(\d+)(\d{3})/
, z; t& U$ F5 i4 V- \ if (props.separator && !isNumber(props.separator)) {
* J/ F8 g! a6 c/ q" m- [6 j, F while (rgx.test(x1)) {- e/ a3 e# ?% C$ `" F
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
* n) W+ D2 G! t& m2 h }3 G! K; z8 n. A R" s1 U
}: @& W, v! r7 S: O* {) N0 q! N
return props.prefix + x1 + x2 + props.suffix, X# b( k! I& q' R6 n
}
' r" Z6 N/ w% o8 u6 G; s$ R
0 K) e. Y, l8 V: @, A1 J. N& o+ U1
6 I: ~1 [, x e6 x- Z0 B0 t6 C2
7 J3 `0 {7 }. W7 [3 @6 Y/ `3
$ i1 L1 J0 W/ P8 p" m7 k! y4
4 S# `- F% Y5 U5 I9 D5
% |0 r% q4 ~ x0 T6 m. a9 `1 Y8 G; W
71 X; s, B7 G7 m: z
8
% T0 @$ e2 i# q$ h% }* k& y. S# g9 `9
* x4 v% e! j3 o1 t9 @( h% Z- ?+ x104 v4 w3 U" S ]) S; A M
11: ~. N4 @9 r+ b1 }+ e. }
12
! ~* `6 S9 ~: z' r2 h$ }13
: N' _, ?+ T( O: g14
1 h! p& x. y4 n" q9 _# T- w15
1 ~1 D! c3 Q" v2 s& [: X4 y/ e16$ A4 d% o+ [ [3 j) B0 E. O
171 G6 m p& `7 W$ A
18
3 e$ m7 O5 \) Q& j6 U190 Q' c; O1 w9 q& ^) D# ^4 f
20
" }& d& p6 R r' t215 ^1 l9 k7 x7 x* {# p+ s
22
6 ~% u( T" c* i9 M" _; Q& `9 O23: E: O" b* E7 ~& q, K
248 O" C) R. W$ s1 c$ X! R& J' f" L
25/ K* G- T8 `# K! W( k: K) L; L
26
& n5 r/ r6 T2 `# g: m+ l4 O27
% m1 p- k3 J) p8 v) N# V28
" v3 ~( C7 E( r29( D& [, U% P5 x I
304 {% h; Y0 k0 O# J% l* b
316 e- W& o! S7 L7 ~7 P7 J5 f
32
' L: t F0 K& t% |# [8 @2 K33# Y' W; X* j! r- R( d4 C8 N- F: e
34 ^' g$ S2 w1 ^* x. m
35( N, I ]) i* N+ _9 [: I5 \
36
- T6 @5 r% n1 v- N37
% [) `! [1 V0 p4 v: w* @+ P% T38# p! D' |* [9 e# I5 R* a$ M- l
39
" w$ c! S- [! d, d40
. Q- p" H4 l9 j( r! K. J41
0 L, U+ I! ]; ~7 u7 ?; ]5 ~42
9 `$ c3 I* Y3 K5 h4 ]& w43* \2 @' B; A/ \% {. X7 |
44
, f, K/ `9 N- s6 G9 Q3 h) h( X45
l2 Z. ]* i, P4 ]3 v46' c* \1 c9 j5 \5 W8 e5 w7 h
47
6 w) N* t5 N" @% B, z48 j) j# R+ j# B& ]
取消动效
! U9 w: O9 v# j# \! b' }0 J' s/ @' {
// 组件销毁时取消动画
$ Z$ s' {5 b5 O \2 aonUnmounted(() => {6 p9 J4 u1 |8 C! a6 M
cancelAnimationFrame(state.rAF)
" k+ o/ a) ~- Q' h7 h( }, N})
6 O" C7 A# e* M: l- j1
2 K8 V! S1 r; J# I( M" o2
- P" j0 @0 M- ^; j9 f+ t6 w3
2 f$ G* m' M0 Z' t9 d- W* E) N4' q% r+ `0 g- w7 h6 j3 n
完整代码
( F E5 E" e3 s a, x1 J: }- W- c
2 [8 ]& Z* @* @8 O: y<template>) F2 P6 i0 O2 v2 G+ ~3 h+ I' k
{{ state.displayValue }}
5 Y; G+ z. o% Q N) Q+ a+ Y. u</template>1 C$ z7 E/ ?& @$ _+ |
5 F5 {* b! i& F4 ^# g% z
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
2 l' S* D" w& Cimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";$ M; Q% {: P& {2 E: \
import { watch, computed } from 'vue';
9 c. r, Y/ D2 r" b8 ~6 [import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
6 T; F! L5 z6 }7 c! K* r// 定义父组件传递的参数9 e. W. l) {( f- T* c+ u
const props = defineProps({3 ], Z5 V, A/ y: D( ^2 R
start: {7 y% x5 t2 ] T+ z. {# d# H
type: Number, G9 n5 W2 q L8 c1 }3 D+ _
required: false,
O+ g) }5 p8 `+ [ default: 0
, a& K' A% f. A) S. A$ j },
( g) D' R4 S- F% H, \$ Z end: {: n2 a* y: g3 ~- g& m
type: Number, A D% l/ d6 x% V4 ?. w
required: false,; w' h. [7 V7 S% I- F8 u
default: 0
$ h% Y& \! P* j; H, H" L2 u }," b: d7 _7 m1 ?; I1 m! l
duration: {8 R* X% \' Q8 J! T
type: Number,
4 K$ }: A5 w: L$ r% T# z& b# u required: false," e. z& T( i$ a/ q" B
default: 5000
4 n, z$ f! \1 v' O },
; K( T6 \; O- R autoPlay: {
4 |9 b" Q f# D5 C type: Boolean,1 l) q; W4 Z1 Q: y* b
required: false,* q/ O) r/ _; H) E+ h1 ~2 s
default: true2 h0 b; U7 z1 ^& ~+ }2 e( {
},
6 W U0 _: c( i& Y decimals: {! ?5 S. m; ^; \6 ~6 l
type: Number,
; c- W! T$ \% _- F7 x V% R) X required: false, H% e) m ~; ^: Z) q
default: 0,
0 f$ T$ v- Y& I" \& f8 E( Y validator (value) {
7 p- j% u9 E2 s# ]6 y. n return value >= 0 a5 z6 ]" w$ V' g9 \3 n+ Y7 c- r* ~
}
a5 y. l+ I/ E- W) R },1 W& ?2 A" _! u8 K
decimal: {7 |6 v0 K7 ]9 l7 `$ h% ^% N7 ]# K. r
type: String,: O) A) `" Y( y3 ?* J) w
required: false,
5 N9 c* H! _! U+ x default: '.'" S# X, `! ]0 I* M2 }
},7 v `& Q8 q. p5 k
separator: {1 g- M/ h: a5 V/ s* {' x4 C5 H7 s
type: String,
( {/ v% V5 c( I& T" Q# L7 q required: false,
9 w! h: A1 s" }3 G( h default: ','4 ]- [" d! k% U5 \0 S: }
},; p- V: e8 N9 N+ w) Q
prefix: {4 X( C# q( I2 R- b
type: String,/ I4 r7 U2 ~1 g3 b! ^2 H
required: false,4 s6 h$ c; N3 F/ y% k( c& y
default: ''
B$ K g* r, `* G0 x. x },% F4 R0 C3 ]# B* e. ~1 v. r4 a
suffix: {! c2 w" \! Y2 z
type: String,8 ?8 r- ?4 \7 T; ]
required: false,( |. N H+ O! n( a L
default: ''& C! }, M6 E/ X0 b9 t- G7 C
},. D3 H2 {0 [% R1 I9 Y
useEasing: {
4 c: x& |6 Z7 b P1 } type: Boolean,, F. U0 V6 E" T
required: false,5 ~8 v7 v: V) l4 r" |
default: true" b5 A* M* a. t8 w
},
) m8 T2 J: N; P& r# ~! b/ N easingFn: {
7 s m" L6 R/ D4 d% H$ P8 I3 V, @ type: Function,
! k/ }4 J2 ^* |2 }& F/ y default(t, b, c, d) {( ^! S$ q* _: |1 a
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
) j2 S. ]: U* t& Y6 ?$ ]$ R }
' q+ D/ T8 V( L$ H) N$ n7 R }
, f- Q8 T; Q8 x: F C})
5 [, [3 d4 D. f+ q
& s% q2 j5 d8 H! `6 a }: a. econst isNumber = (val) => {$ S- j: F2 y1 G0 I* @! n$ \
return !isNaN(parseFloat(val))' s4 [# x% i# @2 E
}: \6 I! Z! u& j* k$ Z* `6 S; W4 B: I/ U3 [
3 ~7 J( _$ q% o W, Z( o. J c
// 格式化数据,返回想要展示的数据格式2 X) l0 n9 J( x" c
const formatNumber = (val) => {# B4 P) T o) X% x/ @" m/ A1 V4 P
val = val.toFixed(props.default)
& `" F+ M5 M3 g$ v) V% e& H1 S val += ''1 t8 V- u, W- D# x
const x = val.split('.')$ q$ t/ v, X) _& Q
let x1 = x[0]
% p7 S1 `4 r4 q+ z/ n& O const x2 = x.length > 1 ? props.decimal + x[1] : ''
/ W0 r% K- i: W6 o7 I2 P: |# S const rgx = /(\d+)(\d{3})// _ T9 _ ]' Y! |( r, c$ Z V
if (props.separator && !isNumber(props.separator)) {
) i# i& l1 u- q% E0 B while (rgx.test(x1)) {
7 {' A) T5 U# b0 s8 K$ i x1 = x1.replace(rgx, '$1' + props.separator + '$2')* K/ A, Q1 y9 m7 O
}
4 M$ l& U9 E( f5 x! s- [" j5 Q }4 @% v7 x8 H( F! Q/ E
return props.prefix + x1 + x2 + props.suffix
. J% [& o$ K) N# O* q}
. } j3 V9 `; p, f$ `, q
& x m7 n9 L; I1 v; E2 \: T! \// 相当于vue2中的data中所定义的变量部分! h& |+ }& c, f. G
const state = reactive({/ u8 ^: l9 H2 c% T/ S
localStart: props.start,! E n8 b) J6 l
displayValue: formatNumber(props.start),$ k. E* W' \5 H. |; T
printVal: null,
- n, X# G* z; ]) o5 y! h paused: false,! [, W) K ]9 N$ C
localDuration: props.duration,
, G/ X( o* x, v$ ~' |) J0 f" O7 i4 X startTime: null,
, V: D4 m6 w' ?2 I timestamp: null,
$ W/ @# d W& U3 V$ s8 F, C7 H, r remaining: null,' }* r& o: ^1 n, [! @+ U
rAF: null
& w u) t3 J, i/ s: F})& P$ @) g( P- v; `1 H9 t: H
; }% A* a! `0 ^* D W4 I7 L( L// 定义一个计算属性,当开始数字大于结束数字时返回true
) N' l/ `* E# N! wconst stopCount = computed(() => {# g! v9 G# L$ g4 w, E- R
return props.start > props.end
6 @* |/ K1 m' C( R" `9 z})7 u" w& T! K# l+ w! Q7 f
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
% J% J$ B5 A* @) l2 a9 ~const emits = defineEmits(['onMountedcallback', 'callback'])
. c- n/ D$ F/ s$ Z6 {% S Y# I! \. i& H y8 P+ i n: B7 e
const startCount = () => {
9 t+ V6 T/ X0 o$ x5 ^ state.localStart = props.start
. N( ]. m I6 N7 T2 _ state.startTime = null- S; g. p" Q1 x. k- F
state.localDuration = props.duration
: ^+ n2 f& r8 |- |% T" z0 p1 ?# O state.paused = false7 K1 M& h/ S& A: T" M6 O+ i1 }1 t
state.rAF = requestAnimationFrame(count)
; b# B" F6 o; F}0 _( z; H i6 A9 N! X) H* e: X
+ v. f, b' j$ Q/ y2 Swatch(() => props.start, () => {
0 v2 @' H$ n' X( G; l( v5 b9 J. h+ r if (props.autoPlay) {2 h9 {+ @+ w2 C7 a. m i
startCount()) H! D3 s0 t2 C# |8 R
}6 b- A" T" q! Z& p1 v
})
9 H% r: D3 I/ k* [5 L6 R. H" }* ` W/ L E& s& B
watch(() => props.end, () => {1 d6 u# ?& y% a/ d
if (props.autoPlay) {+ S( y* v* I3 b, W
startCount()
h) I# P2 @5 ^7 C( E- L4 q }+ G1 `2 m5 D% C* A
})8 Q4 @$ S6 W* v6 z3 F/ R
// dom挂在完成后执行一些操作$ G P [3 l7 N0 f& \
onMounted(() => {" h0 j. ^$ @) u$ o7 ~# `: S
if (props.autoPlay) {5 t+ J' Q* ?% u& V% _! K8 G- R
startCount()! u1 E% Y+ F7 {7 G9 i$ o! t
}: c- L- Q; t* J% E
emits('onMountedcallback')% U: h: f J3 d4 p/ t+ a" a
})$ u+ ~: {. x) {: N
// 暂停计数
1 ?# V( X1 b9 p8 }const pause = () => {
3 K( `4 c9 W% S( S cancelAnimationFrame(state.rAF)% ^7 i: L/ Y' {* R) T# ?
}- T( d8 K5 X* R0 r
// 恢复计数
) b: J" x _1 H" e0 X0 zconst resume = () => {/ t( z# [, c8 F9 L" `" V8 u+ N
state.startTime = null0 \0 m5 ~9 t9 T$ z& \6 a" b" y1 Q$ x
state.localDuration = +state.remaining E) ? n( k) z; P
state.localStart = +state.printVal
, g3 P0 W, H+ J" ?" Y, i requestAnimationFrame(count)# r6 [" L/ f! e t4 B
}
7 u$ B( s3 ^: X, y
2 Q7 ~: D7 ]: _/ c/ Qconst pauseResume = () => {8 e Z. w2 g/ T; u- y; y* j
if (state.paused) {1 m, O* n. } g l" T
resume()7 u+ `. |; `7 b( X2 N2 d
state.paused = false
~- }7 B p- X3 m& E" } } else {
( Y, F7 K- }! @# Y N pause()
2 B( T% |3 Z6 K- C( D state.paused = true+ t. e1 B8 B- |# _4 q- ^
}, D. f' N4 v1 x4 {0 K
}$ o, t& x; @0 w0 A& l/ Q7 L
+ J" V! t& {8 _; E8 [const reset = () => {* M' A9 |& E2 }1 S0 q; M4 a4 t' t4 `
state.startTime = null9 w4 Z; X3 s7 T {) l3 J* Q
cancelAnimationFrame(state.rAF)
! G) ^& U4 h/ y state.displayValue = formatNumber(props.start)7 C% l5 @$ G+ o& V
}: C |: H2 T+ U" t0 q
8 i% ?" _2 g) q! c6 kconst count = (timestamp) => {+ }& |* | i( U9 N b& M3 b
if (!state.startTime) state.startTime = timestamp
O+ }. k" G# n7 W6 E* N. o# z state.timestamp = timestamp( {/ m9 ^6 E) L9 D$ M5 }
const progress = timestamp - state.startTime
% G1 y+ N: m# r( K5 Y! G state.remaining = state.localDuration - progress! I8 \/ H ^3 ]9 d' r. N9 J
// 是否使用速度变化曲线) ~4 l. |1 @3 Q" z7 B" e
if (props.useEasing) {4 J, {: L) U9 U+ @' T( x
if (stopCount.value) {' P0 [2 J% v* Y5 ~! y
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
' E+ z, g3 E+ h* V5 D8 Q' H } else {
, x; |8 ]0 G( ]) f- f( L state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
2 [( b+ A9 ?# M. t" J: ` }
$ n- u+ S2 f- K2 m6 @' z& x } else {
0 B8 K( N! [9 g# [ if (stopCount.value) {
. s: W2 H# n# b# g, p( M state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
8 w9 @' Y, g( L: C6 b1 W } else {7 m( D" T, a4 a$ s6 o: L
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration) N1 P( B# T$ w* ^" D
}( [; [6 {9 J; A/ S
}
) e$ Z6 ~' K4 P1 X( C/ [. b) ] if (stopCount.value) {
! U: ]& z: V& V0 |7 h) f state.printVal = state.printVal < props.end ? props.end : state.printVal
/ N* s; x; V* \& O4 H8 o. r } else { d" W, z6 t4 T; \- T2 x4 v- P
state.printVal = state.printVal > props.end ? props.end : state.printVal
5 _' [; Q* W2 R. V* g8 t. L }9 M3 d; c4 w9 [0 K4 g0 L0 |. y
) B5 n$ s% K& j/ u0 d
state.displayValue = formatNumber(state.printVal)2 ^! r# R/ K" l8 ~+ i1 V
if (progress < state.localDuration) {
9 ^' u& [7 L9 i, E, q+ @) G state.rAF = requestAnimationFrame(count)
& O9 _1 Y8 J2 |6 i7 } } else {
9 G* t9 m! j6 V) [ emits('callback')
" ?* G) o5 h) f; |0 B }
# C: o9 S m( P7 Y! f- j( R) }! Z}8 X" X- x+ I O! c* R
// 组件销毁时取消动画% @* v7 b8 V$ h& u/ e
onUnmounted(() => {( X+ x+ m' D- S, K7 v! ?. Q
cancelAnimationFrame(state.rAF)3 A" |. a. j. S4 a5 b) T
})4 h/ O+ y& h' y/ f7 s
</script>
6 I$ y. w v/ l* m! A' i. Q" u
. M. {+ R1 X% f* z1
+ P( J- {. A/ |# W1 {: R# _21 a! S% \8 k; j" Z T) t& J3 V
3
6 s2 m3 Y4 Z: r H* I4/ f0 s: e" n# s4 ]
5
* q. H7 h! ^. L# e6
( R- R& f- p8 w5 B) c8 O4 ?7
y$ [3 [' o8 R8 r+ l3 ]4 b" j" A8% |+ U8 C) B8 m) H$ x2 c! q H
9
}; H, _2 A1 r9 K" p105 D. i$ q/ Z! c) I9 A: }
11
/ @5 W7 f& z3 m; P `12# i9 @# y& ^# b; P* k$ T
13% _# C( [. _% i7 ?
14, d2 z, D T% }
158 o8 q) k7 d4 r% i8 I
16" i) J$ M6 H+ a. \8 b
17+ |7 \* n; `7 }" S8 S1 i
186 c: H9 s) } h& F$ S# `9 ]8 E9 _
19
% K2 u6 m' o, i/ N20' E* ^8 |, _. _# @1 M: S( p
21
% P2 J2 b6 N M- q F2 q% r22
; |; ~1 T. U5 f238 |" }+ ]" C- r4 T
24
7 J+ [/ K; f$ C% L. N+ ~25- b/ ?4 y6 k" y7 h1 O) `; J
264 g& J p6 S" T$ a, V
279 x" E/ @ U9 V
28( W+ D' s2 O& Y9 q2 n
296 W: X1 b# A) M: P
30
/ u9 M1 Q! k1 g. h& i$ u310 B6 N6 T" R' _% Y, z: z6 J* Q
32
7 i+ A; O8 f& M2 {33
8 Z! B$ Q& W8 j; [( L3 V34
* T+ }% I: R9 }( @35
8 s/ S5 J" \& }( J$ s36; v/ Q% @8 b; t/ C/ R ~6 A) v
37
% P) f/ }+ D) E* d38
) s; x1 B0 m& N. J. d390 F' M3 O: }5 b/ _" V6 i
40* x; X( J6 a6 h# M7 E
418 H7 l5 h' N* o, B+ b% g
42* j1 e8 K) e- F
43
l3 k t) p+ L6 c; o44
; k" a' t5 R0 q! f451 R% G, L# e" `8 {9 M E$ r
46# h& T" |$ T7 @% b8 b3 P
47, X+ ^- v3 z; z6 S! ]
48: M' k( Y" q! U! O! `1 @
49
. P' N2 y! K( p3 N50+ N# @4 z, Q4 ?$ p8 r' H8 T
51$ k2 ]: @! N& a9 v% a7 D$ @
529 ]) `- N; J9 ]* ?) B% [9 `1 C
53
9 p6 S% Y' O; d$ t8 ~# l0 S% q54
$ Q6 Z6 v& D/ t" B4 g9 B* {55
* J9 G# S8 n$ m6 h56, V0 Z* G! [! I8 K! R8 y
57- _2 G0 I1 G5 `- ]$ H4 Z
58
! T% t* f: ?/ r( i+ p0 P59
+ M6 a. a% v6 w/ T60
) K" c( s q5 `8 ^" O* M. P61
4 M( N3 ^3 R! R0 c1 X8 y62; X; ^1 ~, [+ l
630 D# @: }0 P6 \2 ~* M$ q
64
v) Y, ?) l3 `+ k+ O+ F65
% {8 A$ |. |8 l& p( p) R66
& D" G" m) o7 t$ f67
" q/ n" W6 ^% m5 i68
' M) F& m) G, W1 _4 }69" ]8 ]4 l# `6 q$ B* w5 W) A
70: T: l8 U, l; E& s$ m
719 \- ]3 I, S7 u7 S9 F
72 R7 D v Z" A$ ?4 g( E5 v- V( l
73# u/ U$ W% d" C* w
74: R+ |/ P) e$ j, R
75! U( E# l. A0 L
76% Z: R/ Z6 A G% p# \
77
+ {3 H& B& o8 ?( g5 v" m- {78
& |8 X8 _/ A4 v; {0 E3 l795 z7 w2 \. _8 g; ~* k" R7 F
803 v/ p$ ^ ]7 k# f/ R
81' Q9 z" y8 q" }6 @( S+ b
82& W. P1 n; {. ? b5 ~
835 \& f# {* g+ k8 {1 K3 o
84
0 i7 W) R' u- @3 c85
+ g4 z: V% G+ f8 C& W. s7 p86
4 h% p* L& S+ L: F# }87
. [3 g! A, a2 a2 e0 ]3 L5 l! m0 T88
* M" n0 s' m% n! u' J2 h89
$ |( G5 [, Z; b' L, L$ p90/ p! g( h) n( n v
91
& f9 B# Z! u3 i3 [3 g8 u3 o92) K0 f. R" x( ?: G$ c+ o4 q) Q
93
$ ^# s4 c3 N7 q4 V6 v" f7 t- j94 T1 }. g$ c7 _- R
956 J% ^; L% I1 x* Z, S' z. r
96# {6 ^, H4 l0 R1 v. r6 u A
971 ~( F3 I1 e1 d$ D+ W
98
9 R5 ^$ ~! c1 u9 t991 K+ @) y4 ?$ ~. Q+ ~( c" l5 Y
100! p4 n* i* \! j' w$ b
1012 A. Y: }# c0 X2 \, a
1024 e5 u' i, B( x, I" a: G
1037 a- ~( _) K: w- K% H) K7 ]# ^+ D
104# h& y, x+ R: u4 i0 F5 t9 P- N+ f
1056 X# N3 n0 Y( f) ]5 c+ t
106
2 Q, m5 [% N! x3 ]107# K2 a- Z, Y! q2 l
1086 r" ~% E( V A5 w
109
6 N5 q. i" {9 w1109 @9 `' H7 b9 g: _+ f! _ K
111$ o6 l/ {2 [1 X* c. x. D7 X
112
S, X! w; \8 ~1133 n9 F( t' U) _ V
114
+ |6 g6 T2 s' o% ]# ~* v115
& p7 _4 n3 {) l. n* p _7 U116
& u* }# ~) I2 d. e, q; i5 s9 d117. y$ Z* e, O) ^6 T1 Y# y* ]% Y, P
118
" g9 g* d; P& J" G) O, s, i119
/ D4 f Z( p$ P# ?' A% u120* e& s( g: i6 m: h" @" C
121- p" C( H& P8 g% V/ ]2 [
122- v7 O: C8 U N5 N2 q3 g" N5 t
123
! h ^" R3 s/ J124 i8 @. q+ S, Y) ~! H
1252 O7 Y4 R9 o6 o9 ~( M
126. p: U1 i1 c( |; r2 Z/ j
1273 C/ H- D! ^1 J( q, k! W
128
2 t. V8 O. R1 G' O6 i+ _4 ]) X. M129: o9 z( j0 r; D# j* {" L* ~
130# M. _% z4 }7 O0 Y8 k
131+ |; d2 ]. @7 H: i! o, `$ D
132
+ |9 k9 o9 q- C7 I2 b% \$ p6 T1332 O- s) f7 w/ p" F8 Z" b# [
134
9 g% K( i$ G4 O }135' |# G& t6 O4 z: c o
136
3 K. u2 b4 b! n; l- V2 z1 H1379 j+ v3 ]/ }6 x+ x3 e* X' ]- N3 C
138
5 f2 v M" g3 I3 o# H139' K( a [ L8 I" i: s! s5 [9 p% d
140
5 ?( n" F d- R }- \5 m! Z. V141
1 f5 q9 T4 C* C142
, Y5 k$ T0 ^ _4 B; }; ~143
2 o' Z! C5 b8 b% F) V9 Q144
2 c- q/ c/ b6 Y# _145
8 S& s6 w/ h4 S4 v" @+ Y146) U- B/ m0 @, v+ ^9 D
147' `( o2 u4 y9 X. o' Y1 D
148, T( `3 ~6 }# M) ^" ]! V a; _
149
3 j% u7 B& u& _$ P5 l( |150
6 l5 ?! `# K, h2 m151% r+ f, u% [) ?+ d/ Z
152
$ q- t- y3 M" X$ c# t153
7 r) @/ t% O% s$ X' r5 w1541 s$ P8 L" V1 f6 o7 g# R) E1 O0 I
155
" m, e0 q7 S1 v6 p/ d" L! z- A156( }/ g( S/ ~1 t( y$ o3 y
157
: B0 O, n9 p9 F3 }/ S$ }158
/ Y( i! f' V) s) l7 }* { y1593 v$ c" Q6 {! B1 R4 u7 `8 B
160" n% F9 V: H$ m$ [% [
161
# P# R* j% d7 ?0 P1 k162
: z$ W1 P, a) w# c2 U; T& p163
1 _& V3 t4 l5 Z% e$ X4 A3 t7 I2 B164
! t' H4 O2 `& q5 Z. D+ H165
) L* C1 |$ v5 c: F1664 K2 o0 |; D& b X: k% `
167
2 p7 C4 w5 f( D5 X& R+ b168
3 q1 s: ?6 v: ?8 w1698 H, a% Y2 B; R" {$ i
170. \# ^" s+ }7 X4 z
171
- s/ R, S2 `) _, ]+ o. Z8 b' A6 j172$ k6 p% O8 Q! F
173
. E$ P O. ]; e' z* V h {- _174: b3 |5 ~3 E, E3 a. D+ H' ~( `& }
175
2 X$ { S! @6 k, S, U( V7 A176
+ i/ i4 R% d1 `( F) d m( y# W1770 l0 D( i% G+ `" V2 P( [! w, F
178
" K% E& W: c$ x; m2 w" o179$ c; q% R3 p8 x. A5 V* _
180+ j, x. m$ S# U, e3 `, O' `
181
6 S6 [% w: x& |& m. G' m' v182% z; E0 {9 s& b; Z; q/ [
183, T7 _" P& h: W
184
1 u4 |7 G; _4 f9 v; y% D6 j6 @185
3 G# R0 P+ x1 g/ y' q4 ]186
9 N5 I* ?* \7 E( I" E( l; B187; N1 A8 T# O& S9 s+ @
188$ N+ w- x) ]# c- R) H5 k1 U3 T
189: }$ R; _: C/ ~0 y
190
8 ^/ }( T( ], W2 V: V191
# T. V* M$ T# Y, X# J, y# b192
3 y; W4 i" S6 o0 J2 i193
/ {% G% v- e3 a, `0 L4 h194
% Y( I, G# l5 z: [' l. i0 w195
! [! C) _- i% i$ R+ u1969 n0 Z, ~3 P- Q: [
197& r1 m2 T1 w4 D
198
6 Z$ y9 t3 ` z- ^8 O199
. I; A% k' r3 ?2 e8 a' t200
3 Z0 i. S& }4 O& _2011 P; F. e, }' {6 z
2028 p7 e0 ?, f3 W/ O- u4 Y# Q5 I4 p
总结
8 m/ t4 Q. p$ F8 r7 P. _自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️6 k4 g: u0 {: q) _/ t* h, H9 r
. O3 t1 P8 U" m6 m/ \' @% v5 Xdemo演示
; N) M; T/ ~7 P0 y后续的线上demo演示会放在* I, P: ` w7 w0 p# |0 L% z7 R s6 x
demo演示7 X) q/ [3 D/ J7 V5 s& a# D
完整代码会放在
/ T# }, J* [7 u( @9 I- w9 t个人主页
0 T+ J1 q5 E" b9 L X* N/ C" Q1 c( T/ E0 R0 `1 X0 X8 |2 ?# O5 V, F
希望对vue开发者有所帮助~) Y# ?& Y7 i+ c3 ]: q9 p s
; ]2 B; p; [# d5 A个人简介:承吾
: E1 e; b3 N& k工作年限:5年前端3 Y6 S/ d8 B) I( q; J y) r" q: G
地区:上海
8 Q' P' }+ @3 c, ]) s' a" ^个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!5 C4 `7 U" O9 Q) e3 v
! ?& ~( e. a. y+ |2 P! u7 \1 I) Q
5 R0 V! p6 `+ ]! c8 m* s, R. v# F! n1 h7 p/ I5 l
5 |! k a& C7 r2 H* }. Y% ?" T————————————————2 z. Y6 S4 `" X4 e
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, a3 U6 z- h' @! o
原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
6 f- Z5 @7 c* m* b
7 [- k; q9 K' x: n4 D5 Z
& F! s0 g2 C: s: q% J |
zan
|