- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563425 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174250
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效' p9 E& [( m. a9 y* g& L* U0 I
( ^! f& z2 s, Q) w s4 s* e3 I
前言; ?% A) m$ ?7 ^9 `
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:8 N7 H) _0 g7 q8 {8 P, S7 A
TypeError: Cannot read properties of undefined (reading '_c')
1 r& O2 Q F% _的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
V* k1 E' P. [3 ?* ]6 j2 p! U4 K' i& Q) y. q% H
& n' f7 R' f4 _思路$ F% Z/ N: f$ o; q' l- y
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
( O8 ]! H( ]$ m" s1 f. r3 [/ \! P* A- ?! i& d
文件目录
4 ?9 F9 R- ]7 p) e
$ p' h" L: X2 P4 b) V
9 z) N( k; V0 f" N使用示例
, B, e! O3 B5 {* T<CountTo
4 x9 \# @) n8 {* H* u :start="0" // 从数字多少开始" L! z' |! y. j; L6 k2 t# Q
:end="endCount" // 到数字多少结束% W6 ?5 C) j8 t9 C" I) K. `1 o
:autoPlay="true" // 自动播放
5 v' ~, w6 ]+ I& F# {* X :duration="3000" // 过渡时间- j' `8 e$ z. p2 Z: L6 y
prefix="¥" // 前缀符号, i1 m' `3 C. u6 ?7 ^* Z7 Q
suffix="rmb" // 后缀符号
- g. W- }* t* w3 W [ />
6 _0 V2 a* t. E+ I0 _! B4 C16 q" _2 R; A$ V) ^: s/ O% R) ]
25 I* G3 J, }9 z$ h
35 {# Z% i4 J% n1 i+ w0 o. M
43 S: L* x8 }! G* Q
5
- U. v" H9 {# U* s4 K2 ^. P6
1 N8 M/ V7 }! Z* t0 ?4 `7: _ q& g/ ~0 ^: w; v* ^
8
6 c1 X+ p# x' K: K# q入口文件index.js$ o) {- ~* n/ e8 i; V
; W; j. @6 |5 @2 Gconst UILib = {+ r8 c! G4 E$ q
install(Vue) {# C- R4 `2 j) R+ h% v
Vue.component('CountTo', CountTo)
' p/ k! \; x" I# N Y5 L }
* S5 ~3 M, e, {( Z3 w}
# T# i; _$ F5 J7 d( x6 X+ Q6 H( C: y: V: c
export default UILib
6 u9 P) v- Y( B2 S5 y1 ?% B1 |4 S' g+ r
11 v0 N3 ?+ A o+ j
2
7 u0 E* K5 p! x# T+ L' Q3; q& W$ y3 \4 r; o, ^, f, W, c, J, F
44 W7 y9 M: i5 p# e! X
5+ j0 a8 W8 T+ |$ Q. s
6# Q0 i9 f/ V8 w7 ?, `# t
7
7 H8 o! ]- X' \' o1 p; k9 |, w8
% G, G% A4 S }* O; D90 o" Y: d4 j3 e) s
main.js使用& u5 y( D' S) @' \
import CountTo from './components/count-to/index';
; _8 }0 e j+ Mapp.use(CountTo)
M- a* @9 @9 {6 f8 Z1
* e1 f# |! `) s4 B- f$ e- R23 J' \) l' p# L
requestAnimationFrame.js思路1 Y& A+ f4 ]7 o. q/ B: T% ]5 D
先判断是不是浏览器还是其他环境
6 ?( B! w6 r7 d$ H! t如果是浏览器判断浏览器内核类型; @: {8 d, l% A. V7 Z* C
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器7 h' g' F. `- s! h4 K6 A: t7 A/ M
导出两个方法 requestAnimationFrame, cancelAnimationFrame
! L, x1 O/ ^3 ^8 i各个浏览器前缀:let prefixes = 'webkit moz ms o';- M; Q/ H4 S% m# A; o0 i
判断是不是浏览器:let isServe = typeof window == 'undefined';
: a% O4 c7 w+ ?9 t& \' {4 h. e增加各个浏览器前缀: % d: n M6 C: z2 {5 f
let prefix;- C: K {' E2 J2 A5 K
let requestAnimationFrame;
: ]+ r) D- c0 O2 z) z2 nlet cancelAnimationFrame;% S% _: H; g7 W
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式) A& ]) ^+ g) u
for (let i = 0; i < prefixes.length; i++) {
6 A# O; ], @) E% M J if (requestAnimationFrame && cancelAnimationFrame) { break }2 N* {( D$ r. d! d) q
prefix = prefixes) X+ R# i" d6 `- I
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']; a; X9 P# J* [
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
6 m) i: `4 C$ a- t( G" b }
1 y: @# ^" Z2 n; l1 _7 u9 |' F0 ^& e$ @3 ^" I: l3 Q9 I1 t
//不支持使用setTimeout方式替换:模拟60帧的效果* X0 O0 Y. ]* K. A! }5 [
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
; p* ?1 n$ n9 x. W& a if (!requestAnimationFrame || !cancelAnimationFrame) {
4 ]( }4 Q( }$ r requestAnimationFrame = function (callback) {: R$ ? h Y2 W( ^; P
const currTime = new Date().getTime()5 n4 Y" S8 \4 x% S
// 为了使setTimteout的尽可能的接近每秒60帧的效果2 d4 K" J H9 f$ A
const timeToCall = Math.max(0, 16 - (currTime - lastTime))9 n) L, u1 B2 I! o! U
const id = window.setTimeout(() => {: ~$ w: b' D$ ~
callback(currTime + timeToCall)
3 |( k% B' u) z% ^9 W- f' H" W }, timeToCall)5 F7 [2 P( s# ~
lastTime = currTime + timeToCall
$ ]8 q% o/ [3 m3 X return id
( h" R, T' J, y' V }
& i; M* B6 J9 ~( l6 w: |$ B
) O1 k8 W& E% Q" o c g% n: ? cancelAnimationFrame = function (id) {
+ S- w) q! E. P9 s- \, f window.clearTimeout(id)
1 c8 q' C! Q3 _$ F s' @ }
5 _, I7 J$ D6 X6 E1 k) ` }
# b' ^) _1 v, _
* m. q. h$ v* E2 G, a$ A) n$ f( {( t1
0 S, W+ r. k1 E3 P2
0 G" S! x4 N! C( G7 v: X4 h% Y* Z, m( H6 W3+ U( V8 P% X2 ` p8 B! z, B' B
45 C; ?2 k5 `7 z
5
5 }2 O( ~! [, X0 [: Y y2 f1 J4 B6
. y1 m7 }# [2 b: B# V70 W: K/ G1 C8 j; e2 g3 M
8
7 W: f1 Y+ _; ?% k91 @, v, U8 O) k$ V0 s. y4 ~- W
103 {5 d* L* Z$ \& P+ a. o
11& ~3 R! H3 l0 Z. l& k1 j# a0 L
12
% r0 z; S1 A# X* J133 m. ]/ S, U3 L$ p+ Z; |( ^9 j, ]
14
) W+ X; f) z, b" Q' o155 {" Q) E; Y5 e
164 U1 i2 g5 t6 i0 h5 h6 _% n! ^
17
) Y, o2 j) D6 W* S3 q7 W0 i$ j18
; `/ W/ R7 B$ w4 ^, w. [19
2 m! p8 k$ a( f203 L, S* L4 d6 d; T0 a3 \
21
7 R8 \' G1 t& p9 W# u( i22
& T# |0 L7 k" o9 h/ Q23
- {$ a) ^9 z! c/ J8 d, J242 y F0 |2 j5 s# y* ^( }
25
' T; n l# ], K0 e4 C" E26' W' q+ R* h( s% f
27
/ O$ ^. |& o, j2 ]- x* N28& n6 L+ B& k: E# {8 }
29
' l- Q1 ]9 c4 E M6 W* {30
! C6 L& I/ _2 _. P/ b31
' `2 m; C! \* f' |. z1 ~32* [0 u6 @% n' u: l2 {+ a
完整代码:
. q# f$ x+ X" @+ _& {; L* xrequestAnimationFrame.js
: \* L Z# i$ X4 e r6 T7 G8 X+ e; h6 p; }
let lastTime = 00 M9 H0 \' c! Y1 l' H: g
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀- h K* U6 g" P, `! w6 L v# I
# n+ a- U. k, H( O! D
let requestAnimationFrame
/ M1 _) U' j( U1 F6 j7 zlet cancelAnimationFrame
0 `# q9 K1 b9 l2 z/ G3 q2 ^! m/ A5 k# U" o
// 判断是否是服务器环境
4 e' C+ Z8 ^0 ~. T. ?0 D% o3 o* kconst isServer = typeof window === 'undefined'7 [" Y" I* ~# j- O+ U# ` r, A
if (isServer) {- Q. _( R7 O* b" ^
requestAnimationFrame = function () {0 ?* x' r8 d$ j1 [
return
: O$ ?* z5 J; N: C- D }
% B3 f- i. m- M* w* v7 L8 @; s+ i" H cancelAnimationFrame = function () {
4 P: ~+ x e' J% y6 |! _9 Y return( h) F& j$ f$ C
}
( i+ [. @1 |, u# G7 Q- T} else {! Z; j2 ], v+ s# i+ S/ O& g
requestAnimationFrame = window.requestAnimationFrame9 V$ O+ {2 |, v7 U( s
cancelAnimationFrame = window.cancelAnimationFrame
; A0 t+ p) M2 b0 b( Q let prefix
/ [* \9 I" W; d& j- _$ p7 I( i* _ // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式1 T! \) J5 k J
for (let i = 0; i < prefixes.length; i++) {
6 S! A) \7 C& F9 p if (requestAnimationFrame && cancelAnimationFrame) { break }
1 N4 B% [' t- d prefix = prefixes
) j5 W, H6 F: H% l7 Z1 e requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
; k0 A9 ~. ~, G! t; t/ V- p5 z# t cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']( B/ e* E4 A# e/ Z. r5 w) `9 o
}7 ~ |) m7 H" D
+ Z% S6 W! _6 q% s( q
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
7 _# F8 p5 d: U. @* _2 u if (!requestAnimationFrame || !cancelAnimationFrame) {
" @0 x. o) q; Z- i( Z. r4 u: M requestAnimationFrame = function (callback) {/ Z% C- E. h: k$ p/ `+ _
const currTime = new Date().getTime()
3 |: k' y! j. Z // 为了使setTimteout的尽可能的接近每秒60帧的效果" ]9 c0 K/ Y, m6 M
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
- B3 Z1 Q n" T: ` const id = window.setTimeout(() => {; i: E7 B0 q" u2 ~; I7 K- r a" V
callback(currTime + timeToCall)
& F8 S, m) I1 S% `& m }, timeToCall)5 l' u9 {( U o" W2 \. d
lastTime = currTime + timeToCall
" V4 @3 V3 a2 Y3 l return id
8 V* F+ l0 B# G' r1 O# z0 ` }
% w" I8 u. P4 K9 \6 O) f& {
4 M$ B% H7 e& Z/ r9 r cancelAnimationFrame = function (id) {$ l+ g+ m, {* F
window.clearTimeout(id)' N' [: Q# W4 g: Q; _
}3 s- [: \1 U, k) T
}( L V1 W" [: c6 d$ k6 e2 R
}
. a0 V o1 c9 G5 l; V; C' t+ L& O; F( w9 R: h; r2 y
export { requestAnimationFrame, cancelAnimationFrame }
' W' E" V/ _% q6 Y3 h+ |3 L4 s9 U) {
3 f. o) S Q8 O& B1
# q& T) m4 U8 I* H/ t9 S" ]2
+ U/ U7 F# d7 @" D0 r3
8 C# r$ m2 Z" W4
$ @) v: Y: z; I: u8 T, K5
2 q" a# t2 h9 _& @5 Q/ b1 S6
* {$ s3 v4 B8 r( z5 }7$ u% k0 A" H" U" m
8
8 D/ q/ X0 C4 r' L& Q2 T, U9
$ C0 q5 V! N2 x10; ^0 ?0 K% B& [- b; z
11* \/ `4 V* C9 I4 U1 C" D
12) {3 X5 k4 [1 K9 O0 o: }; {0 B0 N6 H$ M
132 e& X. F" @- t' `% [8 [8 P
14' m+ j( @. E) s
15. _* W7 O4 q a4 Q
166 z$ z+ z5 Q' Y5 |
17
' O# B m" V0 d" v+ l; J% g: G: h! p18% Y0 e) u' S% O+ J [# {' i
197 c9 ?& o& B$ L: v2 G
20 Y; d* n2 ~2 A9 p
21& @+ J1 r3 I4 x! j
22
# u: U8 ], Z6 `4 Z232 O" E: C- `4 q/ E- U8 ~8 x4 g: i, D
24) F/ K$ q4 _" Z1 A; |9 j/ B% v
25
. K# M6 ]9 O6 n26 T0 [$ a) H- l: L# e) X2 C, _
27
8 j" [1 |# }' d" {% @28# F5 W2 [9 ` ]; q
292 G% [# `4 g$ G; f: @
30" D0 l& ?0 X! C$ }* \
31
% ~ U( o1 ^4 K% c327 w4 G% h1 l5 D1 X
33
0 c# Q: N' G$ n% z" z34
+ w3 _: L4 T( X" ?0 S0 v% g35, e# B- p2 R& S7 c3 _/ g- }
36" ]# i& e- F! Z" O3 b
37; x" O7 _6 p# ^
38
) h% t, N; s7 Q! Y39' v0 U x& S7 \' K" @0 S+ O
40
% Y4 N9 P5 F9 O41( _' d8 T3 L6 R5 c& x+ s
42
1 _1 l6 |) J8 S9 Y43
& h2 n$ R' t* a* O. C2 L44) c+ Q0 v0 F* x5 b( I
453 M' E: A# L; {* W. Y* [7 k
46( s4 V( f9 i E- V) A) K
47
. G3 B/ v* U6 q6 I8 r% u% V7 @48: u- Y( m; l! k. C
CountTo.vue组件思路: A$ s$ s' F8 a8 _7 g3 i8 Y* I& Q+ O
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
' W7 m$ X3 t+ A& w- t# _. b
+ n, Y6 I- M V2 t0 D3 T引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'6 l7 K; N' S1 C' p9 k; I
1' W% X1 d+ R& g5 H5 _% v
需要接受的参数:
+ |' U7 E* q+ o& j; U. e) I- l7 D3 k8 U& h' H) w8 Z! B5 A4 q
const props = defineProps({6 f4 }9 i1 V$ x# y- K
start: {% a" h( }* U$ v5 G9 m
type: Number, q1 }3 N0 P, c
required: false,4 J' Q# b8 e- C5 c' y, M
default: 03 i3 a% e# t8 _2 C2 p7 r5 D
},
- m* K: o* B5 j: V% p o3 w \ end: {
9 w% d, F5 T- V type: Number,
0 ~0 B* @' }3 G K% r required: false,
* x4 S5 B; ~( o, k) o9 ^" P default: 0
3 C1 u: ?1 z& q+ E- y& ]9 }$ [ },
+ R4 Z$ f" ]& }+ M duration: {
4 \& d# b" ]3 [) [ type: Number,
8 q) M: G( X1 X# j2 c3 l0 | required: false,
) B! @' d' _5 k7 M7 e% P default: 5000
9 t! v& R6 y# H4 x5 a) u },
* d1 K# _9 O8 _3 @7 e( ]& k9 e autoPlay: {' z- ]8 _) |( X8 a9 `9 c9 N1 X
type: Boolean,
9 O2 k. F8 J3 ]% `$ L required: false,
0 Q# @0 |! n0 q$ v9 B" Q8 [ default: true
. Z+ x8 q O. W+ f* b9 C2 S) K },
7 Z+ ]' S p- | decimals: {4 h2 S! Z g- Q0 V% `1 ]! d
type: Number,
% Q8 P' |, R3 E$ i! ]/ T* q3 f required: false,, T3 Q$ @ D! ^. t
default: 0,% i# z7 k$ Q. Q1 e2 m1 V
validator (value) {
, C: ]# E0 c4 `# p( z return value >= 0
, K) k! V" [3 W: R }
5 Z9 Z: q9 h& i, F {5 B1 k },
# i' h- U* q' T decimal: {
6 B! Y! F5 l! j type: String,
: K+ C' Z& I0 O- R7 K required: false,8 l I2 E2 M7 J' Z
default: '.'
6 b* E: H, f6 L" `0 r$ k: x },9 m& v5 Z0 b; A8 O% O3 e
separator: {! d/ X4 V7 y) S8 S$ [0 v0 n
type: String,7 c' l: }$ g) B4 c& B" H
required: false,4 Z! Q7 W- ?. o2 L/ d6 r3 N
default: ','
& |$ d6 w1 t U },
* y2 U2 j: u: k6 b4 B3 b7 @+ e7 p prefix: {
& K6 B4 c; x" L! _$ | type: String,. M" @6 t) r/ ? J& j
required: false,
, e H2 ^" z2 I/ m5 q default: ''
# p( ]! b7 a! T$ U) @ },3 t( |6 N2 F. \- g6 [8 C$ j$ S
suffix: {
5 g; p0 F; W( ^+ y* f7 d) O& h7 B type: String,
. X, G6 ^1 g0 b required: false,
' B0 F6 i* a' I" b default: ''! i' p: Q- k) x, H
},4 |+ F9 G& E5 w! d- ^- n
useEasing: {
# o1 I8 W, x; ]8 S' x type: Boolean,& D: V% P7 f3 l2 o
required: false,% B/ |4 B7 T3 k8 X
default: true. w0 }: ~! o; ?3 e' A
}," q: D) _3 f4 s# l
easingFn: {
7 a' g) N/ b K% v ^. u# j type: Function,# _( S$ [ L* }8 V6 _. {
default(t, b, c, d) {
, N- C$ C/ u6 ?: Y: l return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
7 a3 o( V I f- g/ r' W }- ^8 d$ k" e' j. x
}7 a! E. V- Q9 P/ E
})* ~, B8 f8 n! E3 m. R4 I/ m) X
$ i7 m2 I, ~# N) c
- e- h; f& T8 I/ G# k$ [1
, Y# S) w6 n9 ^7 W m3 ^% }. a; s2: A6 C4 W4 m2 V) O6 p
3' b9 [% v! X: S# A
4$ G% d; O) J4 j2 x1 o! O* }1 \
5( H. N9 b% [3 X7 d+ y
6% m) _( v' |9 E. P$ z& v& T- K
79 u, d, A5 C. C( v$ p9 W
81 |; G0 d, f4 v" e
9
& X4 ` m! O8 K# O; L10/ Q r, \% g) _( ^! {
11
L! x5 h u) H) n12
* Q7 ^+ a& _5 b13
8 ~4 a8 q! ^* a( {7 q# D# d144 k8 n0 m: P7 ?0 X" L9 K
15
' I( }; W% [9 z5 X$ S7 K2 r160 ?* v. n: u, D) g( D$ E+ n
17
' p: a" G, N; W5 h18
9 M# j/ z5 J' E! F5 i19
% W& \- M+ p- g/ @. N( H. w9 T# M20
+ C. w& r5 z9 H21
( b1 G9 z* @' Q. L226 d% m9 p0 W/ G4 E; G( u) f. S
239 [7 v8 O+ c* N6 D2 Q$ ?
243 q: k1 [/ i& Y3 h
252 h0 ~5 R' y1 o( ~$ F
266 L1 P; S9 J$ O. g8 k" o( ?
27, n/ X. R& T, Z. Z+ C# u
28. d: f) P$ X5 F7 u* J
29) L! v- }& W) D' k
30( [0 q2 {- {% Y4 b( x1 R
31
M) ^7 P& k" W6 _3 R' N32
* \1 Z$ ], S Q. w2 a33
' E2 K9 a5 ]4 x6 F/ m34: }5 X6 o. N [& @3 v
35$ ]# T- ?- E. L' X5 q1 b, |2 X
364 ]* u: Q" t+ N' r( w- X1 w* g
37
# m# e, Q. {; b n9 p5 [+ M @38
+ W. q0 F @8 |2 R& ~5 ]39
' u+ u0 X: U. L3 M2 }40
" }( s- O3 Z ?* z( {- K& _) T$ c41
$ w7 \+ h: ]8 \2 ^: b4 L9 }5 D426 O9 b" o6 h/ Z- e2 s
436 d! [; V3 O! k$ E
44$ Q* w7 z% s2 ^) r
45+ i8 N7 @4 _/ |' W9 Q8 o3 \* b$ h
46
# B: P+ ]6 y$ X0 j" {. f47
0 U/ T- U: r9 N& X48
' D1 Z' p5 M$ x: W" K. N, h$ g4 h/ T0 A49% q- ?) E2 L7 P* M0 i% Q
50
9 Y8 E7 p( \; C$ F: d4 n51" f$ N2 K$ N0 _ Z; S; t/ h, \9 _
52
: Z1 Q3 A6 T3 r0 h4 R7 B$ m% V% t53
* ?# f9 ]/ Q; _+ b. W! F8 u54
- y. W0 {! M s+ V55) d5 j5 a$ |' Q' Z. ^, k4 e6 V
56
2 G- ~; i0 Z7 ?& T2 @# u57+ t* _/ s" j, R5 T
585 u8 B* x3 g. G+ w
59' L+ Z9 R9 i5 ]$ ]7 m. W
60
) m& a; [/ Q4 `- |# A) |( t61* }* ]5 A- l5 ?" F* _! o) N. h
62 @/ e% E+ @9 ^: B
启动数字动效% [' B, `( b5 t1 {( q
9 h2 `0 z/ D- B) U! u3 k
const startCount = () => {
( O! O- z# `7 _ r state.localStart = props.start
8 c; F/ c: }7 x2 W5 _$ r5 V state.startTime = null
# b y7 u" c8 d: i: i4 O( l- m9 m state.localDuration = props.duration) S# q3 W8 Z. u
state.paused = false0 j! Y* I( D( Q" a8 x% q
state.rAF = requestAnimationFrame(count)
* n' T& X1 u8 M1 h" a}
* U9 p" @; [: _2 ?2 K1
% o, _5 |9 G$ d. T8 t2
" _% V& G3 K$ _' W: B* X1 B3
7 O) F, o1 J0 s/ d4
1 O6 y& P8 o: H5 p4 }5
' ]7 t& o) e( X5 f2 K- M61 u& ]# I7 d; M( h
7
% {9 w" t X" f& E核心函数,对数字进行转动/ f1 }# `# O8 L3 t
3 a% M3 E2 @. I4 F% p2 w5 z
if (!state.startTime) state.startTime = timestamp! A* N6 U7 f9 Q3 ^
state.timestamp = timestamp4 X1 m% ], W. }! O3 d$ m
const progress = timestamp - state.startTime
9 J! |4 ^$ m& C/ H- M6 W5 ]+ ^ state.remaining = state.localDuration - progress: W5 ?" P% v- e; p
// 是否使用速度变化曲线$ L) Y* p9 k( I6 C4 M" {& F
if (props.useEasing) {2 U; s: G; T+ Z) Y5 m0 B
if (stopCount.value) {
& u0 P$ v; C, }% n1 ^ state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
! U) _7 y: ~% T' N2 r } else {$ l7 }* u; e5 ] x% M( b) Q% T
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
# F- z [- N" x( I7 } }
& B% v6 P1 V7 e6 i: U. G } else {' K: G$ f6 a5 w% l0 U! j
if (stopCount.value) {
& z: V/ J$ q4 T4 L! N state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))6 z _1 j! v+ x8 n
} else {
( d& b9 M. ]# G" @ ^5 k8 r state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
! e5 p1 N5 t; e5 e }( m* H. s( a% \ |
}8 j T; B, X/ y, l+ a
if (stopCount.value) {- f& u& c4 ?0 q( ]% _
state.printVal = state.printVal < props.end ? props.end : state.printVal* X5 i1 ?& z2 l
} else {
4 a# x1 [# ~: F( U state.printVal = state.printVal > props.end ? props.end : state.printVal i2 C* V# T- {, x- r% m) p# X
}
# E2 H8 Z& t1 u, s9 o- F
! H4 t( I* O( l3 l state.displayValue = formatNumber(state.printVal)
* M( w9 ?8 ?. b9 W2 | if (progress < state.localDuration) {
9 r2 O% n# y$ O state.rAF = requestAnimationFrame(count)4 L# i2 p# v2 a: \) U3 W Y
} else {
! F) I( P4 w) u& i emits('callback')
# @9 X4 t' t: \/ o+ K4 v, p4 ~ }' f& H8 G R8 E3 h6 @4 W
}
* \: O- q% m8 X% e; R/ A# M8 N& U. G7 e# M
0 J0 c' y) O/ k9 r) N+ p// 格式化数据,返回想要展示的数据格式
G6 j8 s8 z) Jconst formatNumber = (val) => {
# H# |: w {. ^ ?6 t0 U val = val.toFixed(props.default)
9 d. q3 n) s0 H$ _, l8 o val += ''
$ u2 k. X& d/ c3 r& Y const x = val.split('.')
& O* q* Z) M: v, Z" i" E; k9 A let x1 = x[0]$ X0 B2 w6 D* s9 ^: y, Q/ Q
const x2 = x.length > 1 ? props.decimal + x[1] : ''
- \7 K7 d s k, T const rgx = /(\d+)(\d{3})/
; Q5 y O6 Y$ r: h2 S2 Z if (props.separator && !isNumber(props.separator)) {
9 L& i& {5 d& |$ X- _( s; C while (rgx.test(x1)) {" t- l1 ^2 q; U) c
x1 = x1.replace(rgx, '$1' + props.separator + '$2')' _+ x; Y7 L: o1 Z& E
}
! A/ |/ C8 I. K" b3 S }: q$ k/ n- x4 p- P! W" O
return props.prefix + x1 + x2 + props.suffix
( f7 a& g4 S3 I/ E# W6 K# F! T}0 H2 L8 \. c# K$ M( G
9 v4 I/ L6 ]' d+ @. f5 |( \
12 \. ]1 I) t( s0 {, T. n& T
2
3 J; V( z; A- }7 X2 K( @+ F! J* k30 ~& N8 ~6 [2 j4 V; g7 \! M
4) p: V% s5 K" X; s
5
8 a/ D' @9 D; C" n( g8 `6/ T6 K/ s& s3 ~9 y( p: w
77 V3 J+ r0 n4 s' F# |6 d
8
+ S+ ]9 u( [" p) o S3 D/ f+ k( d5 J. h4 L9
7 n% k: M2 S$ ~- W10
3 h( f( V$ T4 q4 ]11. ]* n/ Q, n& F" A. A4 a
12
3 T: h7 S) x5 q+ }' b% ^9 d }! ?8 v. [13
" Q w1 o' y3 Z/ f5 y/ Z147 W8 c- _. a+ k/ f. f
15' d( H+ ~9 O9 d# O7 m# m
16$ X" J, G' z' [& O( M
17% D$ T5 Q2 }3 }6 P% X' q
182 \; i1 f5 O. x$ A% [- U; d& U- n. q# Q
19
7 e6 Y+ B) M9 q$ W4 Z C* E4 L! B20' O& [2 x! e) q! |! J
21
* ^* q* N) h; @: Y# t$ M22
7 K, R+ S# }. f5 n8 ^4 m23
+ H9 j- ~0 k7 w9 N: d246 [9 K/ v6 ?; s- M: ~6 |
25
4 A+ f# n4 F/ _; M5 `26
b6 s" u' h1 a4 R- ?) i27) G, [: x( h6 k2 s( Y$ k# ~
28' l6 e, Q: `* q
29
: m6 s$ ?. R2 Y; t+ U6 X" M: Q# F30
4 O# ~4 {3 i' A31
/ o4 r# E: O" w; s) ~6 ?9 s& T0 T32
! c1 j- z3 q7 e/ n$ t, E1 j8 @33
( v, V' H6 u' q9 ?34, [. Z% W" h) E |
35
0 B0 o3 F8 {+ K/ @8 r36
6 r, z. D$ f% X# c" ^8 T37
; S, A2 L! a+ ~' L' ^38
& U5 E/ |$ v" h, h1 w0 ]399 |: n# v4 g$ M5 v" N1 B# @
40: Q$ r* h0 A, H! W P5 F
41 l4 [: M- X: o+ L+ F: z
42
/ h( x2 t+ ]. T9 r1 K7 j2 Q- q43' W i: ^2 T$ u( `% z4 u: j
44* C6 \# _' N5 b) Q2 p* u( K7 ]
459 Y! N; s. S" L: D* I
46
* q, E) N# f+ ?$ ~472 @. P; N4 a) V+ ^ ?
48
8 Y; Y: _* b, C# N1 i5 a, x2 v; N取消动效
, q9 B; x: K- z1 x: t6 p3 \7 o8 m4 J( k
// 组件销毁时取消动画
% I: X3 _7 n0 u: \) u; |onUnmounted(() => {
* C. u0 Q0 }# K8 k$ p7 } cancelAnimationFrame(state.rAF)
9 _$ ?8 X5 L6 u) p% L$ Q})* Z9 _& s/ q/ }1 {" ^! K) f
1+ F1 }% E' P( m# P: ~$ K
2
3 `" x* b1 H- J5 r; j {4 U3
: H- ]8 l' L6 U0 g1 t4
: f8 A% K% s6 k @完整代码
4 R3 |8 k0 Y9 ?. X7 r K2 b
/ W1 _5 s @$ m$ ?5 V, d; Y<template>8 n; [8 O& ~9 v% Z3 x( O* X# e: \
{{ state.displayValue }}% ~9 @ p5 Z! `
</template>% a) d$ V7 T l# A4 H) ]! N9 |/ w: F
- F1 O6 k- U, t9 L% [* r
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效) d$ K* e" a' G8 Q8 @' i
import { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
7 I ~) @4 H! q$ I$ t: J! Dimport { watch, computed } from 'vue'; m0 ~! T6 j8 X( b
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
/ o. i# N/ X- I2 \( ?// 定义父组件传递的参数( w) q( r) E# K u8 U. T
const props = defineProps({7 u% l! i# u3 O" [, e- N8 H& c3 E
start: {
8 p' v1 q3 p6 L% ^* t6 F type: Number,1 h P) g6 C7 G0 R2 X
required: false,
+ A0 E- f8 o/ g- _0 ] default: 0/ T" q% D; d9 g
},
, ?+ v/ t7 X2 W9 {' E1 T3 Q8 G) Y end: {
$ G7 `$ d7 N0 \7 u type: Number,, U' o6 @. ~/ Z ~
required: false,5 L( b7 d$ w& Y+ m. X# k! g
default: 0
1 i J1 F( L* J: d/ { },& k. a9 @& a5 U
duration: {* l [$ q& C& `) a; G' @5 b( n. o
type: Number,
, }) m3 }4 f. r9 ? required: false,
! N( K' J0 `! e default: 50002 Z9 @) k5 D8 @3 W2 x: j+ H
},) J+ B0 C; z2 \0 P: o& _3 k. H
autoPlay: {
" v8 y' c: {5 \! d, |+ { type: Boolean,. p3 j" N$ C1 O! E7 a: O( O( e/ H
required: false,- f' Z. T5 {8 m% j0 L8 H
default: true
# M3 {, d/ f* A( F },
3 ]2 m; U. z8 m- j4 g1 d: Y" Z decimals: { y0 m" u* F$ a4 i
type: Number,
! p7 t/ a. H9 _5 o/ v4 s required: false,
4 i- }# E5 a: N2 @. | default: 0,
. b, Z& k) }, j/ Q& M validator (value) {
$ Z% A" _! ?2 ^- D return value >= 02 }& m0 j, }' K% ^
}
6 U: a8 H/ p' w; W4 |, J1 ] },* P0 V4 w; f/ x% t" [ N! N( K
decimal: {
0 ?8 E0 u: \5 b0 A5 R type: String,4 L# r2 \) {/ b
required: false,' I- t8 H/ s! S3 _- g( n
default: '.'! V' H# v) q. ?$ U" ~" ~
},( i2 m9 w$ r2 i4 t, \6 c- l q
separator: {/ m1 P& R6 E; G1 F9 v
type: String,+ A# E( ?& S1 e3 K
required: false,
, M& S4 N9 u. X default: ','
/ `7 X) H( D8 G- P6 H: A },
5 `3 u% Y, j* I1 \ prefix: {1 h! D& ^0 w6 ~
type: String,
5 t3 k1 z2 B9 d( ~; L2 m required: false,( J& ]$ G+ m8 y: ]2 d4 a0 {$ M
default: ''! z3 X: n* Z0 X: O. H4 x3 e
},. j" h2 }) b1 X. Z
suffix: {
- Q3 Q' |: U: Q7 X) B; U" ~" u6 a type: String,- c7 k4 }7 ]3 n& C
required: false,
" x1 S, G. f4 v default: ''
8 ?0 G6 t1 i# }% S q/ t5 ?& v& o },) U$ m4 O' V \3 o9 E5 P# M
useEasing: {
8 p4 \% [% l) l' A2 S type: Boolean,
: Q, G2 c# M$ f+ ~/ D9 o9 b, R required: false,& P9 o% {5 \, y' _
default: true
6 u0 L9 ~( i9 @' a. O },$ `7 m7 N! m; P* |/ R
easingFn: {
# a! y' p# |, z6 u, N! |; y( o type: Function,
8 }7 y/ F! P4 K+ V default(t, b, c, d) {
& R4 f E7 }7 R return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
7 p) s5 o; }: F3 |- X1 h8 Q) x9 s }
" v2 f! A" ]& s, i! j }
; ~- J9 U5 L8 a! W* P/ [})' a& n5 O; P2 V9 E4 P' {6 T
5 |* G, P# J. H; D- ~" s8 Z, f/ mconst isNumber = (val) => {: w; q1 s5 M3 R" G6 f9 ^; F/ Z- E
return !isNaN(parseFloat(val))$ S& W! r Y# m2 y7 e" V% o+ Y3 D
}
" _8 l9 {! Q' r) m
! S" V# s2 u7 ~ ?( f, a// 格式化数据,返回想要展示的数据格式
; n1 q, i) y$ S9 y" P7 B' Yconst formatNumber = (val) => {
4 P, q9 R" |0 W* G2 J. l val = val.toFixed(props.default)
' t; E* S. m! C6 v' O( `6 J val += ''
& Z$ h0 \3 o) _! |, v const x = val.split('.')
1 y: l" X8 y" M2 i; A let x1 = x[0]
3 S2 C% L7 j# V; r' ~, M1 Q/ T/ x const x2 = x.length > 1 ? props.decimal + x[1] : ''
, J9 y$ U! ^+ {, ]7 W const rgx = /(\d+)(\d{3})/+ Q; D- e+ S9 ~* x) d/ P. D
if (props.separator && !isNumber(props.separator)) {
- `! n w- ]! t5 {$ h3 P& I while (rgx.test(x1)) {
; c% T* H1 T$ @ x1 = x1.replace(rgx, '$1' + props.separator + '$2'), E6 q$ W& H2 x* f, U* y
}
. X" s8 L/ X; r) {$ d7 S }
" ? x" J8 X, ]% l1 m" w7 [ return props.prefix + x1 + x2 + props.suffix
4 [% z- l4 m4 e( o- j2 _}
. n1 Y/ \! B- [+ u" K5 h* F: c1 P: l; n0 O9 ^6 o! b {
// 相当于vue2中的data中所定义的变量部分/ ]. O0 B$ F# h8 W0 Z) R% n' j
const state = reactive({# g$ q0 T7 A2 i+ w
localStart: props.start," w" `% @) V9 X9 t4 I
displayValue: formatNumber(props.start),; k( E c5 m- V+ e0 `# i; p* k" r
printVal: null,7 B* H5 P& o6 P9 o5 u
paused: false,
6 V8 i" I$ w1 B4 w9 a" X8 Q% V localDuration: props.duration,4 U$ G% v# {0 A' o1 W! Z$ b9 g
startTime: null,
6 w) }8 Z+ b& b timestamp: null,
- E* T* |, H9 K remaining: null,
# B2 e! u9 ]2 {5 [ rAF: null
+ X; F/ M0 y" E! S3 j})
0 S% V& ~6 k. Y7 m4 y( T% X t% ~% d+ A9 S, {6 e* ?' I* z
// 定义一个计算属性,当开始数字大于结束数字时返回true9 z3 V& n O+ P) m3 @
const stopCount = computed(() => {8 c! J; h8 t3 Z1 l7 f
return props.start > props.end+ b1 z" S. U1 D
})1 g: K0 O `0 |1 |. r# f
// 定义父组件的自定义事件,子组件以触发父组件的自定义事件3 G* d6 {' \& ]3 m! v
const emits = defineEmits(['onMountedcallback', 'callback'])# M3 t' r9 ^" V5 @9 c
% |# B' P( n: i9 a; {) I/ O# G3 N
const startCount = () => {
5 C. P+ t4 D v: N. s state.localStart = props.start
3 d i5 ^1 i6 z% ?$ e+ o8 q state.startTime = null
1 P6 X* [" _# y% _* x state.localDuration = props.duration. ~" |0 S/ q$ j _3 S5 s
state.paused = false% a- Z# b) k1 }1 ]
state.rAF = requestAnimationFrame(count)
2 a m- t* I' R8 i}) ]/ J9 O" R& G6 o: w
0 O* L, `0 b. P9 C' _" a4 Uwatch(() => props.start, () => {
3 e1 a4 B; B! K0 C. x* p if (props.autoPlay) {; ~' }1 x# w7 i9 r- I+ V6 H8 C& C7 @" U A
startCount()) I2 o4 Y1 ?7 Q( v) W' Y
}
2 u% S8 u1 E M" @- Z6 s})6 ~% g! y8 M# E6 i
5 g+ w$ c" e6 `3 j. k9 _! `; Wwatch(() => props.end, () => {
2 Y4 I) R( }; | if (props.autoPlay) {
% ]8 V) i6 Y# W2 U startCount()
; K, o- G6 v# J( K* c5 i }
`; _) F: ^: p% G( [ n})
$ I! S+ s/ l0 }4 O// dom挂在完成后执行一些操作! L; M8 ]- C6 p J+ \8 y' W
onMounted(() => {
6 E& i1 k, [5 R7 a; v if (props.autoPlay) {* j+ I5 |! j* O4 A8 i7 t
startCount()
; N0 }9 n3 k+ k7 [5 G }* b3 O; \' k% A8 @/ |: o$ ]" o7 E) o
emits('onMountedcallback')
, {- B% v8 h# r9 n) L1 C}). h, m4 b Q2 B+ X. q9 Y
// 暂停计数4 O7 {; k2 l1 \ `, {& j; `5 G" e
const pause = () => {5 p, C& R* g6 u- ^
cancelAnimationFrame(state.rAF)3 E) b' E3 e; Y z; r
}
# L/ t0 v/ m- {# d8 a0 k// 恢复计数
1 F' ~9 x' P% x( `; z: U) vconst resume = () => {4 L$ _( l. x% @+ I3 r
state.startTime = null
+ ], d$ w2 G( f2 ^! H6 [) O9 s state.localDuration = +state.remaining
- |" Y/ I3 ?* j$ D5 s2 x state.localStart = +state.printVal
& l5 {) v1 j6 ~' s9 j requestAnimationFrame(count). {/ I8 f1 ?' ~ Q, j( L
}
5 y+ ~4 _( S6 p# V9 j; L4 }0 G6 A/ g& N/ L7 V
const pauseResume = () => {9 j9 r- R# Z3 a4 E
if (state.paused) { u% V: j5 @# v8 l$ a
resume()
9 ?1 M6 ? {7 s" i, ~ state.paused = false/ k; q) X0 b' t: \9 ?6 @
} else {
) Z4 u! r( a; h- G3 e pause()7 F; d) r! [ p; F& a) ^
state.paused = true
& Z s) l* Y: K$ ~. R& I N }, c! Y5 _! `/ ~ X; R, S4 a# c0 B
}
. o- ]) i, n4 I" ^/ D" l, U) g% g
F& u) |' z9 E+ }0 D+ gconst reset = () => {9 a' T9 R! S% w9 y8 c
state.startTime = null
9 e( x6 N" O% t6 u, C cancelAnimationFrame(state.rAF)& {0 Z% l" j9 s# \4 X, o. ?4 l
state.displayValue = formatNumber(props.start)& _3 m; ~3 K1 L6 t1 F
}
# k, c+ u9 z! d a* g
) M+ \9 F* r: G/ a9 V9 ~+ E1 r! lconst count = (timestamp) => {
" N# o7 y3 {, v if (!state.startTime) state.startTime = timestamp
2 u+ i" d+ w7 ^2 _) w2 ~$ m t state.timestamp = timestamp
1 K1 d( r+ o6 ~7 u1 {( d8 V const progress = timestamp - state.startTime
4 x- }4 c* O& s5 V1 B state.remaining = state.localDuration - progress
* g z2 B* ?- k( a% d- i3 a // 是否使用速度变化曲线' K0 q# Z5 j) l/ d# ?
if (props.useEasing) {# z) m: _/ P# S! H% y
if (stopCount.value) {
( o' ~8 K8 w3 d! P% f( h7 O$ R* G state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
* [/ E) l' ~2 S* \; N; i. x2 z } else {
3 J: w# l9 J# v state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
; w. ~- I$ i! Z }
: u* |' W' i* m } else {
0 f3 E! V/ Y3 ^; {0 c. u if (stopCount.value) {3 W9 ]* ~) {7 o! k, E1 G
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))* N$ J3 ?3 T; K
} else { ?6 W* K1 N7 W+ ~; M+ W+ i
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)$ j* r* e5 d3 H; u
}
" }) F) [0 \# \; q5 J }$ h# k1 Q* V3 o
if (stopCount.value) {
- t* T0 Y) b U4 C5 o% z/ C0 v state.printVal = state.printVal < props.end ? props.end : state.printVal. Q! L2 T/ X# w# Z) g
} else {
" F4 F, e6 u$ z7 a state.printVal = state.printVal > props.end ? props.end : state.printVal
3 D7 b; Z+ u, }+ x, g }7 l5 F5 L7 j- e! C7 f- s0 G$ X
2 @6 K/ x5 Y' r1 o3 l- y8 `; D state.displayValue = formatNumber(state.printVal)( r7 z) U- P) g2 f* J+ M
if (progress < state.localDuration) {
# r! r! ]; n/ [8 f( B state.rAF = requestAnimationFrame(count)
" }) X c5 p" w$ k } else {* f1 `9 p, X, p" L* G0 U8 Z5 |( G
emits('callback')5 a% s6 Q2 j0 y7 y
}
( p, f% G) s9 t- T; R. G}
6 ~8 q" n" T" s( K: b// 组件销毁时取消动画( F, p q. ?7 ^7 j3 L$ X
onUnmounted(() => {
1 t2 w0 B% B' Y: S$ [# }! |9 I4 Q. M cancelAnimationFrame(state.rAF)
- O0 E7 O# ^+ M) V) y}), C: h2 f# r6 ^
</script>4 z- r2 ]# O/ H1 l
! V0 {) w$ [/ {( r
18 E2 q7 w5 ^, D" e( o
26 ]) M/ p4 f9 f$ b4 Q* l
3. I! s- Y# I6 h2 B3 O
4# L# a! E* ^0 b$ j
5
2 X, j; S# g; f4 \' R% k6$ R v2 p& }) F0 {- F
74 i9 u- x, T9 e4 }
80 i) ?/ S2 h0 ^. V
9% x2 r" G7 w* u) r$ F8 q! f# G8 @
10
* T; |. b1 G) d8 F: s" A$ c& [& f119 @) F* ]* ~4 ~, I6 G ]) J0 }
12
/ q' |7 `9 I. ]3 q+ p. g( O13
- F0 ~! G, b* L$ l7 m- v14- T% e& M6 R8 f7 m- I3 R- o
15
* ?' p& t) J# Z) V5 T" k16
2 p! M. P4 L7 P2 F/ N9 O6 m17; ~& w4 }3 ^# S4 @1 K' \* ?
18$ q. F5 p) W2 [
19- _ C' V* n4 P/ S3 L2 F, w, I+ f
20
" R3 g& X: C5 X$ v0 n2 j- L% n4 Z211 J8 V3 a. Q6 G5 ~4 u% L1 y+ U1 C! `
223 l8 O ?/ }# P- ~1 O
23
: x5 Y5 I' D% E+ A& Y24. \" [' U; |! t1 ? @& ]( }8 d
255 D2 U6 p0 J- y0 H+ P& @
26/ G- H' I+ x1 a* H
27) h- _ a% d0 `; t/ Y
285 ^, \* m6 b" V8 M3 D
29
8 ]9 `; Y" t0 F30
, J- ]7 a, J: o/ i2 r31+ b; d h& a4 }6 {' L3 [ _
32
+ d1 E# B |+ s, V33
/ Q' R1 K' b8 Q" t T34
- O1 i# U& S s8 Y) D352 P! O7 D! j6 k8 A
36
: q4 t" S, b; x. s8 u: G37* h4 c7 g, L1 u" o2 m
380 Y. X& {+ g* j
39
0 V! o6 _( o* V3 f5 u( F401 a. K, a. j2 r
41
e3 v0 X! M) l- F42
3 ?& f v D. ?+ z43! e# O- M5 T# G
44
O, p- U8 p. Y4 M/ p5 [5 {& X457 `& }1 b+ w4 z' Q" K' _* o
460 _7 U8 V( }% E1 T) }8 _) n
472 T% i- G! i" V2 p2 f# m
48. }. D0 [1 M, I8 x, Z8 R
497 e' Z$ M( e) `( m( I3 a
50
3 i Q0 r* d0 q f5 F* n+ k51) `" f I( K7 r7 \. K' V3 v
52* _0 l, i }: V$ T' ?' o
534 U8 H3 K. N2 F! h9 p
54/ j# n2 Q) a+ k" A, h
55
" m) r0 k" F+ Z5 U. h56
* ?- i4 [% N8 t: K57$ h: Z X5 b# @# _
58# F. j: X+ X& A5 P! I' {" l: P
59
) v4 Z7 Z! P$ W& z# D8 g, M60
7 `6 U: C( s1 J) q61
; ^1 J, r ~: w: w7 S620 w! r, |& Z* T3 I9 V8 x9 r
63
9 N- Y/ T( a6 k. K64
0 D7 I6 M/ q9 w* u+ f" j65
" o/ I z1 B; y) q# z66
! C' `0 E0 `5 q* G! u0 ?# ]67
5 D v; v8 W3 k# [4 b- q# L; @+ E% p68& `. m+ d! _; X0 j* H$ y* g0 x6 b+ C
690 e6 K2 r5 y9 p* z! B
70# c7 P4 x/ m$ J
71. ^. J3 b- B; q7 y7 U
72
* s: D% T& }' x3 i73- n6 {6 l( h, v3 M
74
. M7 o( l, w. A8 u; j753 n4 R- x% f2 P1 ~$ e+ {
767 z' S3 f* `7 G; n8 [1 Y
77
) r( [' C6 m0 Z$ g! Q8 f78
8 x5 Q" z! _$ V. z3 J79' E8 D, J5 ?: }& q
80' H( A8 u: a, x5 \1 }2 |
81' Y. n/ {; k2 ~5 c% B6 `1 L' ]0 j
829 z) o+ Y0 C: N# b- M
83
( Q- g( q# B5 \# `844 f7 T4 L4 x, U3 ^" v
85
/ T/ b; n- Y4 T! q# d86
9 v8 P! s( ^2 d0 |0 ]8 T$ B87
/ {; y; y5 `1 j+ B; W* V; o88
$ m1 N+ u' @! D) K! J89; I# @7 f# v/ [
90
) r/ s3 |# |" ^9 p/ `" l91
5 S" h+ {3 ~" g92' O, g$ s7 i7 V( z2 [/ i
93
: e2 o( y) @3 J: k" L- z94
7 y7 r5 ^2 |& m" H95
/ e; W5 S- t7 F- j& j968 V W( w' G# `4 q1 y2 y6 X/ z% _
97. Q8 u. [6 ^' A+ b
98
a1 v$ c! ?6 ~; ~2 i99
1 N& d) d) I& Q% i `100/ v7 O0 K4 ^# U& c% `, f
101
( e( E$ B! `* @( O( {+ `4 ] `$ y102
! A0 |: I0 c+ r, [1034 |2 a P7 N6 E& F+ w
1040 Y3 }# T% H# C) y9 j/ s/ m
105; P/ s+ @# B( f4 r* H' |
106
* s* e, l% k2 h1 Z0 L107
6 P; K" {* D8 \; P8 J108
' H8 c* l; }- V9 s1098 ?$ d ], }# E9 ^% }
110
4 P* p% g, Z! I% d: I3 A111
7 a; K; N* H7 e X' A112
8 _+ R. |; y4 F8 K3 H* x113
, j' d% ?$ a8 |114
3 {/ |$ P' \: ^115
5 ~6 M$ v. b1 u& I N* G1 [116) I1 ^. w0 y4 A' P( B; o
117/ f$ Q. @5 V/ ?# v
118$ f8 ^3 W7 A0 L) }8 e
119; l8 s% x5 ?; y+ \4 x) |* c
120
0 Z6 g+ l% g- I: ~121! X5 ~) l2 \+ G+ ^5 `7 Q
122+ D4 S- E9 C% g7 M, F: X8 M
123
) V! S0 @, a4 B, {$ h" L6 E" H/ G6 Y124
0 q% M% P( S( ^9 G2 j* d125/ e9 r f8 @) g, i$ P: [1 F, d9 n
126
* V4 m7 u! H4 O2 j- \2 N127
. W; C" o, i# m' r! e1287 W& Z; O* C9 y% i3 ]+ n
129+ a* V( I# b8 [% n% S
130
5 {" t# w" J! U* d0 B R& ?1311 c4 {- v6 E% \; Q) r
1327 u2 D* g$ r! u7 b7 j" Z/ s# ~( T( }
133# o' s* B2 @: ]6 J; Y% z A* p( Q0 Z
134
, q) w" b. M2 R- |0 }135; i$ I0 p& H/ ?) K' h
136
/ w3 r1 F+ L5 d# z; o- @! {7 u7 @ T1373 m* |! r5 N& k' a0 L' m
138
+ w. U r' _; M' N1 E# x139
3 ?) k6 N- w8 @! F8 A8 {% u140
% n. E$ v7 X! R/ h. u: d6 _141) T2 E& f% w! X" G1 O
142
' A- j9 |: S9 {3 o( G' ^9 f; S1439 v& }6 B4 v% g" b: a2 x
144: w3 y! K2 W0 M) G; L- K1 q
145
8 o: t) g8 i( g. Q4 p0 W& p% t4 K146" w; c$ W3 @9 h D" b0 b
1476 V7 ]# X6 {: U) B& z
148% G" P) J3 e* h# I7 F9 V; ~# u2 s) b. I
149( p8 G- e" V/ E& d" @# k& E
150
. P7 {2 H9 N! H* ?3 e" d151
$ c a& b' _, X7 R/ ]' ?1 e' f- J1 A152
" H" l N( \5 S3 y+ x* r* N5 y153
% u/ G- Y: A- |154' d9 C& u3 r/ P! F, }
155
- ]: Q% i. K0 q2 ^: X6 @7 z$ O" r+ |156
6 M! e7 G5 Y' Q4 L7 b157
! ? |, w7 K7 `$ X" b7 ~: B; V: e1589 v- ~: U. l/ n4 L& v. r
1596 i1 o5 @, v) T/ L. E
160
# @# ?' E+ e, U' B. J+ H' n. m161
$ y: z; F u3 n& o9 k162
" ^' I1 M1 r* H ]6 x/ F163; j( P1 Y ^+ D. i8 q+ [
1649 \. h8 q% \3 b; W. `/ u j/ \
165( W& n9 ]. w" |) @8 y/ [3 E
1668 o1 z, J9 ]/ s; `; u/ N
1679 O. U" @2 ], {9 A3 g3 N
1682 m3 @3 G. t& k
169
* n" w8 R3 _ S. N8 j, n170: ^% B# R; W2 ^
171' D9 _4 D y: G
1723 c/ k; j& }* U- W! H
173
' [1 H; I) h( B9 u; K/ Z1 N174. e2 I* I" p' O7 c5 {) R
175( x4 z1 p4 ^. [( t
176. d2 x2 }9 q; [1 M v
177
; `! f8 l, k2 q; W) t1782 T' N4 E& f( c$ y7 K
1790 t4 z. @3 H5 q5 k
180# I3 m3 p, b$ I+ v, W
1819 ]8 E$ {' R' k! n
182
* n4 c3 K4 Q# Y1 F5 d. W* h8 ?183
8 X; G# e6 k/ v1 T1845 Z& P q9 y2 ^* R* J2 I% \& c
185) K. T S6 N% R
186
* v# j% _) g8 l# g187; E' s8 [9 d4 {- R* ?. a$ B
1883 |6 Y5 k( A- I. n9 p, x
189
2 R/ E) }$ E4 n: _! E% b190; t$ y, X$ h5 ]( y8 I
1918 M7 }5 s8 B# g9 {6 x p3 X* K' ]
192
5 v5 [4 K2 p# n: \% p. r193
9 @# y9 q. c8 R1 s9 f194
' I+ A5 s. A: v8 _( W195
0 b3 l# w) z# g; H6 x5 q* E1961 [( T" Y( {) b8 o7 Y
197
1 r) t9 ~+ G( e4 ~9 s1 V% \198+ H( J3 c: a5 q
199, e- Q/ H U6 ~" O" W" n2 a% |, Z' q
200% e5 n0 q7 ^! k% M) t% {/ V
201
b9 V3 f$ J3 K3 L B# ~3 Y202
0 |& W6 w$ {0 S2 t& @/ h总结
8 z! X, m& p- ?# Y3 ` A- \自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
( z& a: }+ x( j( q, U ~# w# ]8 U) M2 p% L/ ^5 V- J# H- z
demo演示 u% r8 U$ `# V1 O% h% w B
后续的线上demo演示会放在- {5 I' F/ J: ^
demo演示0 x0 G7 J" R9 g( M
完整代码会放在3 H: h9 \' l: n- ]& w4 I( K
个人主页 h# I8 B" o2 t% y3 f) o
7 {9 v7 R' v& \, \希望对vue开发者有所帮助~
" k% a4 N, |0 l/ B# z1 t6 D
# K) D+ [8 [+ b个人简介:承吾
+ F/ i% |$ K7 V' s W工作年限:5年前端
: o% _( M, R; P- `地区:上海9 S c( G5 t2 p) j' v
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
2 z; z ?$ Y$ O* u/ ~3 S. A9 D
; B1 j: T9 W9 Z6 b1 ?& }$ T) z3 `4 p0 L
( {* ?2 R3 A2 f$ b$ K+ B
( {. P* x2 E* n& N( P. X6 D
————————————————
" |& E i6 s% n7 C版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
$ d( K7 e q& s6 D6 S2 t) b i原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847( T$ M8 W' U6 r
- a( m+ R& M3 @3 X
9 k& Q. l3 U$ K. v# W# [4 K
|
zan
|