- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563241 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174195
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
4 V/ d! }* e7 Q- b0 F0 W
8 ^% ]' t& l9 G/ t7 O前言% P7 g; {5 a: @* T3 P5 {
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:7 E! H5 ^1 y. q
TypeError: Cannot read properties of undefined (reading '_c')& o% [, e; E3 k
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:) d; u# H6 [0 h4 n5 @
' K3 D m5 u; {/ X
& j( i+ b1 p0 d3 l8 Y( ?思路4 X( G( B) c+ p- }
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
1 ]) S* h, s4 A0 t# v( o, v( V% `+ w" m9 t0 c) N, H; y7 h1 }
文件目录
' X3 I- n# D5 v$ p+ R+ b5 `/ R% g0 f: e3 F
+ Q# {- Q, o" _5 B
使用示例8 x; C$ h. q1 w7 _9 ^
<CountTo8 I& {# L) B) i
:start="0" // 从数字多少开始1 i0 o2 i" s$ b9 ~
:end="endCount" // 到数字多少结束. i8 @! }. C1 D) \4 y7 j3 y' r
:autoPlay="true" // 自动播放9 h+ ^' f$ r) J* h6 F1 b
:duration="3000" // 过渡时间0 M9 c* ^7 C9 \, c; j
prefix="¥" // 前缀符号0 l/ F+ Y; V: z3 k6 Z8 Y
suffix="rmb" // 后缀符号
, W4 e `8 C, Q4 v; w m4 W+ Q />
( n( o. C7 o8 n1 K7 u1) @6 O6 y. j' _+ [, ^
2# b: O$ {+ q( u! _/ P6 l2 q
3% E" C7 P6 ^' a6 O& K5 Q+ z
4" M1 i5 Q* Z1 \: {9 q+ G
5+ U. n+ v) T- n# [0 c( D
6
+ a% F2 C4 F: H, ?$ P8 p. P7
+ _$ F$ r% _; U+ N8
& s* G$ @, X1 t: o入口文件index.js$ H" T/ L* _4 V1 X$ h
5 ^2 Q2 d! ]: ?, e
const UILib = {5 w- `2 h; _) A
install(Vue) {
! N/ ?9 S+ J$ q2 l2 i' t- V7 t Vue.component('CountTo', CountTo)& F) T/ q7 G z
}
5 `: h: B! A5 @; D}
9 s9 D8 o3 V: g4 l9 t$ v! x
; B8 A; v$ x5 w# c# n' Eexport default UILib
) m: z; h- u3 ], X z/ F+ n, I! G m! b( I" ]! G
1/ e$ u; s- n3 I% q+ p- m+ `; ], H
2
0 N7 J }, c+ O& A8 e. f% r$ U7 [3
! P- W$ j, [) S, j* i4
- ?& [) T3 z! Q& u9 z% r5# w' e4 `/ Z: S; h0 C' p6 C
6# a# b: d$ o6 z, O* E; |: J0 f
7
) g$ n! A3 D h3 N) P7 o x* |0 [8
* q3 D3 h" i: ~) J" `$ ~9
6 ]9 d$ T" g" E; S9 Nmain.js使用
/ ^3 O& H) l. i# s6 Aimport CountTo from './components/count-to/index';
+ i. Z" b1 _2 b) e/ ~app.use(CountTo)$ `- Y' u( I! I' Z
1
! l2 P: r* A0 g0 N2 p) m9 x- L& F4 b2: b! W* ?- s& F: Y o1 X
requestAnimationFrame.js思路
# Q. ?# T3 f& I先判断是不是浏览器还是其他环境; X M1 J7 G2 ?, t4 ]& s
如果是浏览器判断浏览器内核类型7 _& {, A! T7 r" }( A
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器
' m/ C1 N9 d4 U4 ?& S k% D导出两个方法 requestAnimationFrame, cancelAnimationFrame
/ F" d( M( E; w+ J0 x0 R1 i各个浏览器前缀:let prefixes = 'webkit moz ms o';% {) U! h; `% N$ b# ~
判断是不是浏览器:let isServe = typeof window == 'undefined';4 p s( p/ w g! B
增加各个浏览器前缀:
. L6 ]# e6 e' n# u) O nlet prefix;0 A3 p+ E) l0 U) _- B
let requestAnimationFrame;
7 Y6 p3 C# T. N+ f+ y. s+ dlet cancelAnimationFrame;
, w/ m7 U c. y1 H& b" C7 N// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式3 d+ K' ]- Z d0 Q3 v2 w* b0 ~
for (let i = 0; i < prefixes.length; i++) {9 q0 j- Z& A" J5 X9 l
if (requestAnimationFrame && cancelAnimationFrame) { break }; h1 ~+ k6 @9 A' F- U
prefix = prefixes* d( Q! W' F2 C* _' u/ _
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
; G6 [2 k, x0 _) d" |' s cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
: g& P; G, V' L }
* S! {8 o, M' `4 M4 ~. ~* ]
/ e5 s& P4 ~& x8 s //不支持使用setTimeout方式替换:模拟60帧的效果
- K- | U! H% D8 N! b- O! D! A* d // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout: W! s4 G- K& n" S: _' h h4 f
if (!requestAnimationFrame || !cancelAnimationFrame) {
" f: b0 n3 ?% K) O* B requestAnimationFrame = function (callback) {* W9 W- _# R, @4 p' |2 L
const currTime = new Date().getTime()
* j/ J- i5 r. x) c7 ? // 为了使setTimteout的尽可能的接近每秒60帧的效果; y$ }! i4 t. C& M; B0 ~
const timeToCall = Math.max(0, 16 - (currTime - lastTime))( J& x) N2 i4 N$ r. M
const id = window.setTimeout(() => {
8 c: {/ c' I, e8 O2 @& ~* c callback(currTime + timeToCall)
1 U) j6 ?+ q2 t7 c8 ? }, timeToCall)1 q) r. K2 \. A
lastTime = currTime + timeToCall
- N( ?% m: P+ z) s% F+ x! Y return id: m- g; y" F) ^" z
}/ [+ l. L6 [# X# L3 f) N: B
% T2 C+ f/ k/ ]2 `, ]. G cancelAnimationFrame = function (id) {2 T5 v) j- ^+ u2 ?
window.clearTimeout(id)( B& Y0 ?+ S @
}
6 j8 Y, |* a5 k* m: B6 E# }: i }, O; q) N" X% d+ V; W
: }/ i |) i* ^3 o* C7 X9 i5 @! \1
2 y- `! V& L/ v& c2 Y1 n2
( f/ e p, g) G7 R/ T8 `" F3' z& m1 X+ D5 Z9 V
4
" a! b/ c/ v6 e( Z5. l1 P+ Z$ E- p6 f1 U2 ^. r2 N
6' M( z/ P: n' M! k
7
2 ^0 q6 K* x" o4 \81 k% f# m5 x# S( ?' T1 _* {
9
_; {- n# |% T% \2 p7 j7 m10
" F/ g7 F) h1 {8 @9 a+ ~; J N11
: M6 k, Y! ]) l128 `' I# ?. |$ I6 v# ~
139 Z% y( y1 o' o/ |
14) F: l& z) c" y7 _" R6 o2 X3 b$ h
15
) x( P C' u. H7 f# I# v3 c168 _) T- ~9 S* L8 P. b
175 [6 R4 \# P. c5 v; _; c
18
: r" M9 f0 H" a. E19. _- F0 Q/ |+ j. P* f3 F, [
20
* `+ o) W; T) @215 ]& F. `* I2 r9 J# m; S
22+ q/ Q4 [- S/ P9 a2 I
23
! E$ V0 b# Q. f& ?& g24
6 K2 R" a! x$ B' g0 }3 x9 J259 p3 C9 M0 L3 V$ |
26
9 O K6 X0 W+ Y; Q! K0 A278 X; G7 `; M" D
28
* V9 d3 ~; Y; C/ F7 d5 b8 B5 {8 G29( G9 J q. D) D+ B
303 f, K9 F# t4 e
31
" W6 e9 b' A! l' T. L2 Q4 q& J( b32) r4 J( z$ \2 m# y4 F( W. Q0 h9 y
完整代码:+ n" e B: A5 q8 v
requestAnimationFrame.js- G8 ?4 I/ w4 }2 [+ ?
/ p/ M. O4 N( `5 D% olet lastTime = 0
$ r g& [3 Z7 s9 ~const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
( `. ^' i( P9 f/ g Q; e1 c6 e
" N1 f( n8 O, h. M/ }let requestAnimationFrame
, p9 ]% X; w3 \, m+ \4 \# q$ llet cancelAnimationFrame
3 G6 R# M# ?6 p3 ~% e! V" }7 k+ s" Y2 B" X; [8 ^
// 判断是否是服务器环境
0 q6 d# h7 C" L0 V4 x" a0 kconst isServer = typeof window === 'undefined'
0 @) B& E' m: ?$ m4 X9 K! |if (isServer) {7 Y4 ~4 d+ x: T7 }
requestAnimationFrame = function () {: f1 `5 ?5 P, g& l6 C9 ]3 @' b2 z
return7 J( N$ R/ E& k# T7 q2 R( A4 V0 @
}6 a/ I+ n+ C+ d8 C' b+ N9 g
cancelAnimationFrame = function () { X6 D4 R9 @0 U5 G* r7 b
return
, l7 h8 d$ A' g$ n! K }( \" b& ?7 n( d' N( }9 |- d
} else {
, `; i$ c4 y. t/ n requestAnimationFrame = window.requestAnimationFrame* u: J/ ]- S+ q
cancelAnimationFrame = window.cancelAnimationFrame
1 ~5 X, A( L$ q) T; s( U z/ M let prefix
5 z8 }* \" |/ |7 H5 n F% m // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式7 o. ~2 t: ?9 l+ F# @
for (let i = 0; i < prefixes.length; i++) {% q( @/ H8 ?5 t' C2 k9 N+ ^
if (requestAnimationFrame && cancelAnimationFrame) { break }" y# w" P, h* R" i5 D
prefix = prefixes* ` B0 z* S1 D3 v
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']/ P4 `2 x' C9 c, q+ H) T
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
) V' H& v; j" Z; S( E, q1 [7 j }
5 N l8 ~( Z: F- A( s9 b6 ~/ q3 Y) |3 q2 I+ \( f( a! [
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout: o' J2 @3 _2 _) G8 c. g
if (!requestAnimationFrame || !cancelAnimationFrame) {
, w( w% h7 N# ?( X requestAnimationFrame = function (callback) {( q7 A9 O" v0 e+ D! ^
const currTime = new Date().getTime()
- J0 b0 j R7 @1 i. @9 _. x // 为了使setTimteout的尽可能的接近每秒60帧的效果
2 P0 s4 o4 K( [3 o5 E' T const timeToCall = Math.max(0, 16 - (currTime - lastTime))3 e; B: |5 j: c$ M
const id = window.setTimeout(() => {; b4 r3 h- Y2 Y
callback(currTime + timeToCall)
& j: M$ w/ [3 r6 P1 I) B. O a }, timeToCall). i r8 I4 O# a0 t, r
lastTime = currTime + timeToCall3 \! u y0 T, S% @2 o( L
return id0 ~$ K! p5 t& ?
}1 [8 q; z+ X+ ?- n- l! ]) [" d; h: M
/ q* o d+ I5 O cancelAnimationFrame = function (id) {
" d3 g6 s* b5 v. U0 H window.clearTimeout(id)
# n1 u3 G9 m6 \/ k }
: X5 F* r# r$ n3 S }4 r, G& v, N5 t) c# J
}
U# s3 A8 x( m( Z! m& x" ?- f) b, ?% T& {4 D/ d4 R* Q4 y
export { requestAnimationFrame, cancelAnimationFrame }; y2 c3 ^ }) d# B: v- B& g3 h
7 p4 n1 o* a S* }+ t0 b: n4 r4 Z
9 U; B* W2 w |: _1+ }+ B5 [ ?8 s8 t5 d. X8 q
2
2 K" G9 i! M& W' r6 x6 [* f3( b0 w4 r% u! Q6 f
4
6 _ P% T0 B+ l, n& t( A5
1 b* u" V* Y& Y L9 B$ n( d6
1 [$ Z+ Z( I% r; q- _7
, D: p% H" y" k/ P; I% T8
1 w7 \1 x" ]8 [$ Y9$ O0 W0 _( a6 g$ [ b3 }
10# q2 `% c0 n3 P8 w6 Z
111 ~1 `' z1 U0 S" o+ [ r
127 T+ y! `$ G7 F3 K3 D
13% N' `& M7 R) v0 N5 B3 l
146 @4 p! f3 u% \. @& X+ Q) n
15 t, p! C$ f. B6 @/ e
160 s8 ~: `/ w. v- b5 Y1 `
17& x8 G9 _3 [& l; @ ~" p' x7 u
181 O7 J) S+ H1 Y
19
" a$ f* e& y# M9 w20
( y& m3 \1 r7 x+ [21
- {. Q* K# o& W' c# [" m22
2 R/ r& v8 X, ~) R23
1 J$ W9 M f- F24# x4 I) E! @/ \3 W# p" J9 g ~
25
+ @# \; b4 z& I& b7 l7 g4 [26
3 v+ L& d7 k, @( T+ m1 D27
2 m2 S6 X# ]% }4 p: [28
: L* X( z( @- m- r6 c! }29
+ T- e2 Y' T5 C/ s' J) X7 B30! F* |4 ~. P1 X% U/ V, c
31
; L) w' k# }' M7 S: W32' s- v& f ]* r! l/ p
33$ p2 \4 ?$ w* ^3 Z0 M
34
2 T+ H+ J" q8 G) P( g35
& a) j* G' [9 \3 W( x36
: G8 X% i9 X, u% z! }372 o0 S4 d5 O% W6 v/ ]2 x0 y
38
; o4 T, U9 p: M/ h39
3 u% {. Y3 |$ ]3 h! c40
@1 {2 R u' f2 {% {415 m& }) L0 {3 F5 Z; ?: o3 x; y8 d
42
9 [4 ]7 z) h% h43
& h9 ?* g* Q1 p- W( o6 j4 g44$ C @' \: M7 f/ w8 K5 `3 I5 x6 p
45
- X2 \8 r% ~" d" u; ?7 K! x# W46* r0 @, X* G5 C) X
476 E- e& Q5 R' U, ~7 m) C1 |
48
, y# D( T3 d& ~# X! OCountTo.vue组件思路
5 }' ?! c( d3 s首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
, K/ k/ s B; O8 R. }; d! P1 y2 y( q& I
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'1 K* [5 X/ W9 C8 D
1
$ C! n0 U1 K, b& L S# c& | s需要接受的参数:
; O& D9 u; M& e9 N: k6 c" J# F5 V1 m
const props = defineProps({: \+ @0 j" b4 q. P, G3 @
start: {1 [( X s8 y: m$ Q5 Z4 o
type: Number,
6 A2 e, Q7 L' S* w+ z3 J required: false,- M# L) g- p) S: f! @+ F0 W
default: 0# j. [! l# h& i9 S0 l: a [1 j
},
9 M4 i7 y- Q( |7 C |5 n end: {
. }2 i, Z# ^8 ]: H6 D type: Number,- A8 K4 X D! r5 x/ f
required: false,
) }) t' U0 t" i/ A0 E# [ default: 09 v, H" a6 ]# g1 y: w1 U
},
1 a) H3 J$ j) L4 J+ V4 q duration: {
" K' B$ ]. f b6 y! \& W! A type: Number,
' J! e( O2 m- B! ^9 T( t, L required: false,
9 y: B/ A; s9 P- w' ?, M default: 50005 V- E6 I+ ]* o) V' B3 {
},
# |3 m; a& V( ?) `( Z autoPlay: {. S& ?2 o( O7 `4 q( f: e0 p
type: Boolean,
9 G5 y, T+ A+ S e3 @5 _$ A# U required: false,
! M2 _, |. S+ o, E& B2 ^ default: true
, [% }: ^' M) a0 W' ?7 Y6 U },* f' U* l* M/ [/ q L( C R
decimals: {
1 T5 P, \, C' m D0 }- k+ | type: Number,- G% r- J ?( e. B7 p7 [& z
required: false,! j/ Q2 O& \/ [, b0 c
default: 0,
7 G: Y# E0 h) d7 v# S% _/ g& l9 { validator (value) {! K. K4 O' H- V
return value >= 0* f6 x4 s/ ?1 a9 B7 d; \
}0 c$ A& W/ d3 c1 W. h' a
},* G h- w4 j8 D( {% y j# _& |8 y
decimal: {2 t, L& a$ @ T: V& d- }
type: String,
% k1 Z% p/ S9 N6 O9 I" F2 y required: false,* e4 m2 z8 P/ S
default: '.'
6 W% s6 B& i. Y2 E( E H5 D },. t1 o: Q* i+ \* e8 g0 d
separator: {
" ]' _/ k# o$ D D" L1 y9 c; v type: String,& e: i& w5 F* b5 v
required: false,
& Z% b. u- `, ~, d! N2 b7 e' T default: ','
3 Z( o/ r& G( y: V( d }, z& ~- C+ E: P2 r
prefix: {; t; t2 P* t- Q
type: String,' ~8 P1 q2 b9 K4 z% w4 w7 ?, ]# R
required: false,. I! y- g2 o9 o; N; h G E2 d* [
default: ''" B. o. \1 o* Y& k2 w* c
},
+ i+ N; h W8 [) y* {( K suffix: {
$ \; {$ X, m6 ~/ h type: String," T0 D( c- e+ y, |
required: false,1 k j9 V+ {6 Y
default: ''
9 n; Z# z, c$ w: Q' y- ?+ w( R },& S8 Y2 y5 B5 b @
useEasing: {4 n1 v1 ~. _4 d1 b: d: m
type: Boolean,
, \) R ~0 g$ n3 k required: false,
" z5 U# `$ x! Q d, A default: true$ o$ M) h$ ^' K2 p7 L1 e$ L5 l
},1 l, d L% f+ W' f% S% q
easingFn: {
/ d% v) l! f/ F8 i3 ?4 _. s# P5 K type: Function,
; p5 C2 g. d! J# Z' s5 @& e2 E% [ t default(t, b, c, d) {# g& o8 A6 o6 U) b
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
3 c* P: M: q& r) `5 i* j }8 k0 _- K$ s. T, f/ N# ~
}
9 s0 \/ k: M- F})/ N5 s4 A2 P' X0 b# K
. m ]: a4 p# b& i+ {
0 n1 r; K' E* N$ `0 t# g7 h! X1
. S; E2 u* a! L/ L! q* h% ~2' A$ U% m9 H9 Q9 ~
3: r. q2 d' H L2 S" i
4+ r& M( A9 I9 F5 _5 i
5
* e+ u" L1 ]- L$ l+ D" n. p4 V* R64 x t4 C& j+ Z: B. S( G
7 p1 `+ y3 N( s% L
8
* I( M1 c( R/ h4 {1 o94 |+ X: c3 L9 }& y
103 n4 r, m: K3 w
11; H& n8 }. U# L6 t5 y) M& W
12* F6 ^- k. L+ h4 Y. M4 v2 r3 _
13% D3 R# M* j0 o, |/ r) q, S. r
14
, |7 L& Y4 @* ~' o4 U4 Y/ r+ [$ \15
- a4 {7 y# b) F3 A16* d5 o* o. P" {' ]/ ^* Q/ N7 g4 i! d
17, [& F) S1 H% @, f/ U! Q& q2 s
18
: ~ I5 D, F- O7 D6 g19
3 }0 o. r1 i6 o% c% Z# }20
' ?" \/ _# P8 a; }21
( A: Q" V& i/ o; F! A$ B' m' }22# R& b# c2 W5 r O
23
( p7 I$ R1 }+ @6 G% {( i24
; T) V) ]: K; R' B25
7 d2 \- T3 Q! D$ s26
: Y2 U; H1 x X3 s+ j/ o27& o+ X6 h$ s; [* ^
288 a! c9 P9 h& z. D# v
29
7 Q# ~% Z4 g* B0 L30: U* \, ^0 w; ]7 Y% a5 e3 H
319 O' F4 d4 m0 K6 t+ o. `
32 S5 u. t) g3 y1 P4 |) ?4 y5 L
336 e7 y* ]& g+ A: t+ K1 Z6 c
34. C! u' _0 X: X1 O
35
: c' v* j$ S R/ |4 m' \367 Q( a0 `5 x7 P$ V# X- D
37! q3 q$ j# P) Y0 o5 Q
38
& Z) i1 `9 ?* ^' J& g39) E7 d: \: P! x3 f
40
) M" ?8 i8 q. l6 Q- u& U! a41
: N9 [( N8 P# E/ m. r# R! |42
6 D% @. [9 q3 @; {( m, h1 ~435 y/ x; |2 n5 X8 a
44
; ~' H0 k5 Z0 o45
/ z2 y0 M1 N! t9 s" o4 I2 v% @# @46
' _+ ~( U) E5 f& K47, `. d1 \! k7 F' O
48# I q' v! ~2 O r$ W2 M/ v9 s
49, e. s/ t. a; L: b1 [
50
2 z4 ?! ~5 J7 A4 R51! J! ^5 X, V2 x
52
% ?6 K/ r: ~' v! R) W2 \( N* r. A53
& e* y" j p! |6 p4 n7 C54' C r" o* Z; i' @+ c
559 J F- u9 x+ X( `
56- l# O1 @) M8 l4 n1 }5 H$ M
57! A) j; C, g9 z' m( a
58
+ r ^" z: _2 W9 y! L, g) O1 m- H598 j5 W( ?7 v! G9 i: s% o. \
60
7 ?! C4 f) P! Z& S! v61% Y' _* j2 Q7 L( n/ X
62
! T% h5 P% Q5 j启动数字动效' @8 ]* }' o7 C6 `3 K
2 L- B t5 z4 i- [! K% H; e2 Wconst startCount = () => {$ C! u1 J* C: s3 H5 f6 { x: F2 `
state.localStart = props.start
; F2 i2 h- I, c5 @1 U state.startTime = null
5 N% R! E' W1 [. T state.localDuration = props.duration6 C6 K3 d3 N2 I3 h
state.paused = false) l& T" ` k' L, z
state.rAF = requestAnimationFrame(count)
& N8 f6 z, ~ ]: J. K: U) Y2 g8 o}; z* O# A4 C9 F9 W5 X+ K
1
% c" J, d, \5 b4 L5 R) |- a* |/ p2: d1 ? w8 g0 E1 w% ^3 G
3- b3 d7 \+ h4 j- ~
4
* U) L6 y+ n$ w$ X: {/ t# F5) E6 Z) B$ X; w Z
6
( n- C- u" A( K7 Q7/ N K' {! R2 Z, y3 q
核心函数,对数字进行转动
3 x7 J, d+ S& ]% w7 X5 I) _( y: I
. \) o! T. q* H" |/ l9 Q1 B; X2 T if (!state.startTime) state.startTime = timestamp
+ v- O% E, X7 Z1 F: @) Q state.timestamp = timestamp! p* Y1 L$ t0 U
const progress = timestamp - state.startTime# N6 _2 C4 j2 W3 T! L2 _$ m8 J7 Z. F: C2 g
state.remaining = state.localDuration - progress
w! j7 m+ J1 l: ~, J // 是否使用速度变化曲线
' M" Q6 V5 S2 @4 J7 C if (props.useEasing) {& g+ ?1 t% N% B' R9 O' E
if (stopCount.value) {4 [' E$ g+ r) q' v, s5 h2 z9 I
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
2 ?' E- e5 E0 g+ P2 S* F& B } else {
! F! I8 F) p- |- N) K. p6 S& o state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
) o" c1 H1 o! E" I1 y' l5 w2 s }9 k4 {' u1 H) v* _! U% k' s
} else {
R. d5 ^2 m" ~8 P- f if (stopCount.value) {0 J7 d! }+ k$ ^# g, Y' V# p# Y4 B
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))* U/ g" T: ~% S: Z; o3 o1 |
} else {
3 B/ s8 G, H' ~- w state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
8 S) l; N! k0 B }8 K! g5 N0 t4 a% E- A7 U8 b$ o" H
}
9 {! ]$ J |% d# n+ d if (stopCount.value) {
% g2 Y& p' r4 Z3 E3 o state.printVal = state.printVal < props.end ? props.end : state.printVal- _& P5 t, [6 H% v
} else {
4 q l" Y* r8 M9 B$ Y+ z state.printVal = state.printVal > props.end ? props.end : state.printVal: x, K$ f. ^+ L/ |3 T0 o4 G$ I
}
& _! t" C2 ?3 A! X$ h; i0 q# Q- ?' v- a- M, b
state.displayValue = formatNumber(state.printVal)
5 r" l7 B% c, L U% a7 _; e if (progress < state.localDuration) {) v' U5 q; ?" j- O/ E
state.rAF = requestAnimationFrame(count)0 n6 U( J" z( Q* ^4 K
} else {4 x; f, O1 }4 z8 e8 c
emits('callback')1 ]" W9 X; s9 f- ~
}
4 S7 L# R2 G5 b. n/ d3 k" P9 C}
" ]/ C$ x$ u* w$ D+ r% [* C8 b
) V' t6 b8 R, b3 D9 |/ @, q" I+ [3 A6 x6 S O- q4 S' j7 t
// 格式化数据,返回想要展示的数据格式
' T6 `' K6 H& _const formatNumber = (val) => {3 L7 }+ M" v* N: e1 g
val = val.toFixed(props.default)
( j1 Z& J; y+ x val += ''
$ i: \2 V8 I1 O const x = val.split('.')7 M( B, B2 I+ D6 }3 X- n
let x1 = x[0]4 x: ^5 }( O3 V: y. o* C( H
const x2 = x.length > 1 ? props.decimal + x[1] : '': V2 d/ b# l: X
const rgx = /(\d+)(\d{3})/
8 ^; {4 i) Q& p1 ]2 i& } if (props.separator && !isNumber(props.separator)) {% I' y+ T# k0 j; C
while (rgx.test(x1)) {7 y2 W. C g: m5 ^" ?( i7 D$ \
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
+ P4 e; ^0 |& E& K } n- m6 k9 z& p6 D2 V1 R
}& d8 z( T( S o/ E! V$ o* T) P
return props.prefix + x1 + x2 + props.suffix& Y0 F) O' u) @2 |$ Y# C
}
! ?5 [) E" D) s }# K% e4 F9 Q
# V0 {6 d3 o( d o1. _6 d* |- A5 e
2
9 _" \, n7 J3 \$ V. Z9 r4 n38 P$ A1 c+ U k1 x) q$ L4 T. X
46 a; _% o8 e9 ]0 K# b
5' x$ k6 c m$ [+ F2 e8 k
60 N' |* A$ w4 O7 K5 y6 B
7. I) D8 V6 i" u
8/ w$ @0 E! u3 d9 d+ N2 z
9
, Y, J ~. I! F2 r$ h6 x& ?# P10
1 c* b5 `, J9 w$ ~2 u4 b/ G* n11
. H* s7 P M3 {0 ~' i7 ]- T12
0 p* T4 O8 @0 G: F$ ~, L/ x13' b( P$ C' W6 ?# p5 N2 `
14
+ s7 @) N/ [/ W( W15
+ r, Q6 X. y5 W167 ^. F9 H7 z* S6 I: {) I0 F+ a
17+ Y$ M: S2 c' a/ p3 w) d
18$ \0 o% C d1 t* G8 b* Z, s! T6 ?9 a
195 f0 _3 }6 ^; c
20. ? d' _2 j* E- u0 C
214 e; _1 B* T& _- F4 b' b
22
& a/ d2 Y6 [+ ^* ~- u23+ Q, x# E' Y. d! z
24
1 z5 K8 R o2 _2 z! {- Y25
3 `0 w6 r8 U% ^% B' G$ R* t26
! y, r o `' }5 }273 F, h! y# N1 |- y* Q0 P' @
28
6 \2 ^; c7 o! ]. a/ O# s' C29% h4 u2 \& H A5 d4 U) a
30
; ?7 Q: B6 e" K7 z. ^7 E6 [9 X316 |7 k5 L4 {( Q9 J1 `
32' M+ ]- e- { L; H) ~
33# L. {' p, m* N3 y( V' m: e
34( t3 M" ^( ^9 ^9 o( C
35
d, Y8 ]* ], c& H36
1 V% a- s- r w3 ^; s7 U372 U G F' M' ^0 m" @! X: M* j6 t( _: P
38+ `, e. f6 ^' S3 ~) l& D
390 {6 ^( y$ a* ]! C
40
+ s! F- b4 Q; j8 ]5 N41$ |9 \, Z3 y6 N$ x4 T: C! i0 Z6 r
42
2 q! r$ m& s# [' v ~6 T2 Q43
) I5 u6 n6 G0 x- X0 Q* K% q44
3 ]8 B' f8 V6 O454 D& y$ g2 K) ^ a
46' w% T& w8 }4 X
47
: T( X( z1 W" [0 r9 k4 a: \- Q48 \3 Y |9 @0 s( n V2 O" W
取消动效* h) @% w& k- E+ v
2 r. K t0 m7 U6 ~$ a: h: ?3 G// 组件销毁时取消动画
; i; C o" H O6 v4 |5 z+ o V; MonUnmounted(() => {
6 c( h4 s6 y5 J- K- M! v9 Z9 V4 Q, p cancelAnimationFrame(state.rAF)
' j6 Q( L; {+ y# t}). T/ k5 B: e2 i% X& B
1
) r' V/ ]( l! c& W' }8 U- C2& O L# C$ u; a* H/ ]) f( d% [- u
3: @+ i3 G' b; T# @9 W- q9 W
4
0 {0 I( b+ [3 w* I; C; o完整代码) V" \4 b% I) B' F; j) b
# T% x, X9 k- M0 [' `$ ~# h. G<template>
2 J7 Z( v1 H" o |) X* U' X {{ state.displayValue }} E- x0 N7 h7 s* o9 ?4 F: y E
</template>+ g2 K" E/ c; ^9 v) p
. r; @& `; N+ E
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
9 z& ]' V! S% R9 F9 Iimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
( d5 X9 j% U( _2 z0 kimport { watch, computed } from 'vue';: h* M. y! g9 K) b" H+ \
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
! S$ U( H( \! }; b4 }6 X// 定义父组件传递的参数, P/ s# V, ^/ D3 D4 r+ }
const props = defineProps({
( |2 ?# ^. K- z: _- I3 ~. { P3 e0 P start: {
- G F( f8 i/ i- s7 s4 b; t type: Number,
( o0 j" r$ C: C3 L3 i& u required: false,
! k+ x* T" l7 g default: 0. Y+ ]8 ]1 w8 P% K! S2 c7 t
},) ^( w/ Z2 o; q( |
end: {
" S, F$ t) B* p! Q type: Number,
4 n( k# Y+ ~6 |# F3 A required: false,
$ R5 ^, A1 @' ^& M- t default: 0
6 f5 `3 Y4 ]6 D! C },
( f/ I; `7 M% u' t duration: {
) v7 X$ p% L1 S$ b. e' o& E type: Number,
- n- C% v' q4 s3 x" T( W required: false,
8 L. l. V: O( w/ c- s default: 5000. j# n v7 @# ~ v1 }, ]; \
},
, {8 j' w" R. j autoPlay: {
4 |! u# Q# V' n8 Q | type: Boolean,( d" m% C5 l6 }0 o) p# H
required: false,
! P! z( [1 @# K4 G4 p3 M default: true6 s* \# N3 v- `) U7 a2 H; A
},
2 u$ o& c9 S! \; C- y7 | decimals: {
9 Z: ~3 G0 `- ?7 Z. P0 f type: Number,
; Y# v. m* ` c* A { required: false,3 C8 |5 ^" o+ h
default: 0,% z" p7 f" ^9 h& K8 N) y
validator (value) {" ^2 u' a) \5 C! [. v+ C% o
return value >= 0% ^" Y" ~' P7 i1 A2 @$ w( J
}% R/ O3 F% I/ {3 Q2 Y: q0 G' P
},4 V: c7 S1 G. j% i8 c$ y
decimal: {. c: u7 z3 `5 X& R1 I# |) G( G
type: String,- \5 E6 d0 M2 Z- ~7 \4 B e
required: false," d) q/ ^- w; U* k+ k
default: '.'
' E) }+ Q& }# u },. S9 b& M6 K$ _; v: t* x f, O
separator: {: }! s! \! s3 a" c7 T8 B1 [' ]
type: String,
/ W! M( K; T# ?7 y3 `- q required: false,% u! x% g" @% k) x
default: ','
: ~0 I7 ?3 c. o3 c. W# h, Y },
0 b5 N3 D9 E6 P; E- D prefix: {
( Y6 s+ ^) \, N" u0 ` type: String,
( i; _! k) _1 t- J/ e1 b6 Y+ G required: false,
/ Q0 B. @! n1 h, @) X( p) q default: ''! N3 M3 x1 Z! p" W, O/ y
},8 @7 G, @( G0 @: w( n5 O; P1 {
suffix: {
( n6 A4 ~; H% T7 ^ type: String,- }6 g$ W1 ~- M( t; [
required: false, ~4 E( F" G' Z) d
default: ''
8 R4 v- v, Z# d },
7 K+ u" {! y T$ ] useEasing: {, g, H7 D1 @* ? @+ X, C2 r" r
type: Boolean,
3 m2 s' B" t& j required: false," N" }- f9 f" W
default: true, u1 w) V0 W; E8 H- X( p
},
8 f. e0 r7 L& @3 Y; [ g) z } easingFn: {' F* L. q- a+ o) g) u/ V4 l; {
type: Function,& K; a' b; J1 }: J
default(t, b, c, d) {& r( q- ?) K" q
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
' {/ M0 @$ J2 L8 I3 \! w }
' }# l, `# s4 q* I7 y }
# Q/ S( H* w5 Q7 }1 S9 w})
% K+ Q) j% \7 z7 p( d
/ u+ z% U0 P. rconst isNumber = (val) => {5 J2 Z3 Q/ B. v9 V! m% j
return !isNaN(parseFloat(val))
1 D; X. z1 P& y4 @}
, V! j9 n0 Q3 p: w) r, ~4 z: F
3 Z" n* z0 H" ]" c// 格式化数据,返回想要展示的数据格式
. a# |) h: `% mconst formatNumber = (val) => {$ ~( e* D0 n7 r2 h) @
val = val.toFixed(props.default)
# U* l6 ?% ~0 \6 e' l! P8 ^ val += ''8 T. ^+ j$ `, H$ d$ O
const x = val.split('.')* c; w* Y& t$ k) U6 L* }3 N& U
let x1 = x[0]
1 S+ D9 E" T+ q0 R% K' Z/ P- t const x2 = x.length > 1 ? props.decimal + x[1] : ''7 i/ t& R$ ^, r8 X3 C
const rgx = /(\d+)(\d{3})/0 H+ O M3 \. W* [
if (props.separator && !isNumber(props.separator)) {
! C# ?1 l7 l+ T3 |* j. t5 b while (rgx.test(x1)) {! f3 A' }5 q* d6 X J1 P2 F4 Y4 z* N
x1 = x1.replace(rgx, '$1' + props.separator + '$2')# h1 Q; ~+ W7 Y
}
# w. o6 ~" D) M" d/ [1 L4 @* R* B }9 N* \" j, e3 B# ?
return props.prefix + x1 + x2 + props.suffix
5 R2 b! q6 J) B8 i2 ?( X) G}
& D" E4 B, f1 i7 D& u- H$ ~+ |, K* l! ]& m( c5 g
// 相当于vue2中的data中所定义的变量部分$ I+ I1 W$ R. f# P, U
const state = reactive({5 ^5 k* K- x7 s% i/ r2 l0 p
localStart: props.start,( D' r" d$ N9 D% x, m! z! D
displayValue: formatNumber(props.start),3 j+ Y3 v* _- N3 r
printVal: null,( s! S& |( P* z! E" I
paused: false,+ ^+ Y% l: M/ j, V0 h
localDuration: props.duration,0 r9 l i( Y0 S
startTime: null,
# b, _. D- p3 m. V" }3 q timestamp: null,
7 K7 T$ k& v; E0 t/ P. h& M remaining: null,5 R4 M" v; \; Z7 `" G, f
rAF: null' N. P8 I, e2 I' T& L. k
})
1 p& t) j; W' Q; h2 F" v& L+ Z9 G; O9 N. Q8 }
// 定义一个计算属性,当开始数字大于结束数字时返回true4 x* e2 i9 ?0 l3 J+ P
const stopCount = computed(() => {
) M+ h6 N( [" S, W2 b return props.start > props.end5 r4 u- V4 ~ x {( M! s
})
. Q3 `/ [. V: @/ `// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
8 G# n7 Y1 C! O: Z: Oconst emits = defineEmits(['onMountedcallback', 'callback'])
" A# i2 X& V8 S, n. G* l, B: G" ~8 E. I4 H1 {3 }. N; c. b( k
const startCount = () => {" l! H& i! z7 z1 ~ H' }+ ]
state.localStart = props.start
w0 `/ }6 D7 x7 m% P* i0 X1 a state.startTime = null6 z0 S3 x$ _$ i, ~' x
state.localDuration = props.duration
3 @& [! F K e& q C state.paused = false; c* x2 w4 D |8 A: p
state.rAF = requestAnimationFrame(count)
0 |: I2 D: S: l# }& @}: A# c0 ? _+ f6 d
5 p5 M# U7 I/ d' o$ T
watch(() => props.start, () => {
/ J6 d8 j/ [. l% {: G( J/ v if (props.autoPlay) { D+ P5 V. w2 Y: c5 u9 ]/ E
startCount()4 k4 [3 T, Y7 h" i( W
}7 p2 c G- \& ]. u1 K
})
$ Y7 c. {# C) I+ Y( g9 ?2 g5 Y$ P
# A5 l4 H- I$ Z5 X: m0 Iwatch(() => props.end, () => {* H. J8 T6 ` s) `
if (props.autoPlay) {
! d4 C+ \8 Z' |+ L5 Q* a% f startCount()6 I7 C. q4 |5 A
}
6 `! p1 Q0 W. h. O9 b+ m, W})
. w& E) g) Z3 ?1 ^0 G4 R- h9 x// dom挂在完成后执行一些操作: ^" M- V: k8 X- x# K
onMounted(() => {& v3 r1 q! w/ y& {! }) j( B
if (props.autoPlay) {
) o7 @7 |4 q( l; P6 i! `5 N startCount()
& E& W1 E- T# C( m5 h' S4 G }) O4 G5 @- U, Q: F# H% F
emits('onMountedcallback')
7 t: r9 c/ G \5 w})
8 g" S9 p r6 i$ D// 暂停计数
6 t, C/ ^/ M4 A kconst pause = () => {2 T" l8 M( r" O9 }& Y
cancelAnimationFrame(state.rAF)
0 @7 e5 k/ \. e* D" S}8 k2 h* `. U9 v F; S) |7 `
// 恢复计数: D t, [+ ]/ W+ d8 k6 G) Y" x3 C
const resume = () => {
& S. I* X5 w% P" b. X# ] state.startTime = null" G% w5 j$ q' s) |1 Y# u
state.localDuration = +state.remaining
4 Y5 f7 f+ r; ], T% C' u+ A state.localStart = +state.printVal
6 I; M: O" @7 h# m7 M requestAnimationFrame(count)
# }5 u- Y- R5 l& V, ~4 M/ U}
9 n+ J5 Y- {1 m w
; E% w }2 v& U. ^- m2 b% rconst pauseResume = () => {. Q$ ^9 P5 H& [1 m7 m2 V9 C) X2 h
if (state.paused) {( {) a* T4 I" `5 g* Z
resume()
5 C/ {; L. D$ L state.paused = false
# U6 a0 u" F5 I! b2 D) T7 b6 @ } else {
* e1 \5 W; G* r5 n+ e( ` pause()5 a( m/ R4 t+ B# e4 c) a
state.paused = true* ~( T) _( Z5 G6 Z
}. G9 x& f6 g) C4 L! C
}4 l% Y: R9 o, W; H
7 H0 M5 M: E0 C0 k) K. D3 J8 J. q4 |const reset = () => {. t& G. O: \7 o3 Y
state.startTime = null9 L* \# Q6 q% c. m% ]6 k
cancelAnimationFrame(state.rAF): V& k/ T4 ^( n3 g% f& ^
state.displayValue = formatNumber(props.start)
; H& {% o8 M" z$ ^( k7 f( X}
$ V: W# h2 E6 c+ Q9 O1 |- r/ C0 L0 h" @. a+ c$ r) h+ \
const count = (timestamp) => {
$ q0 `# K) G+ ~- t# m5 A/ \& y if (!state.startTime) state.startTime = timestamp
# l5 J- ]' U4 J x3 C state.timestamp = timestamp
" r( g! X1 x6 ~ d3 t* B const progress = timestamp - state.startTime) A2 i! z2 S9 v
state.remaining = state.localDuration - progress: g0 Q4 k4 _/ s- B- M3 h" z- h
// 是否使用速度变化曲线- B5 }5 X) K4 u' k9 n1 z0 Z$ |" s
if (props.useEasing) {. R- l6 r4 p9 \. E4 p" K# A) @
if (stopCount.value) { P- [7 m9 f, m2 s. h0 C
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
1 D5 q' Q% d% Z } else {
% u4 ~$ A% r' `, L' r1 X6 f/ |4 ] state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)# w/ }1 P0 t$ H' x( |! l! b7 Z" i
}
f4 c' _7 U! n) [: l6 a+ A9 s- { } else {2 U) {- ^3 m% r* t$ S5 C5 X9 ^
if (stopCount.value) {
], s' ~/ [) y+ l4 g state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
+ D g7 s0 i) k } else {% a) l: ^7 D# u3 A1 w
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
) z! T: _% }+ I }! T) a# G) [/ S* C8 h6 w
}( ^; J; f7 Z8 p) i* ~* x; h8 b; n
if (stopCount.value) {+ i0 Y8 ~$ D y9 I8 m& w6 P0 c
state.printVal = state.printVal < props.end ? props.end : state.printVal; Y6 C+ f$ b4 Y# u
} else {
6 u/ t" r! h8 n' }8 q |) O" @/ y" ? state.printVal = state.printVal > props.end ? props.end : state.printVal0 Y& [% I5 X/ ?! E) \5 i) \
}
; {4 g5 d; A; T) l7 f6 ~6 R" V5 K! h$ m( Y% W- b" b& k5 n
state.displayValue = formatNumber(state.printVal)
) z0 X$ G' H$ W6 o& \" ] if (progress < state.localDuration) {
4 V0 M6 D! V/ b6 Y' M state.rAF = requestAnimationFrame(count) m7 x2 u5 c( A" Z7 h7 `, s" \8 m2 \
} else {3 l2 J* ~& W& i
emits('callback')
" Y0 `" K9 K9 d4 e4 n( b6 a7 X% i }% W9 w# Z; j s- w
}) h' F6 D8 p* h/ W# H0 a
// 组件销毁时取消动画* B$ z M' R5 s
onUnmounted(() => {
' H% Q" |5 Y7 @8 j' w cancelAnimationFrame(state.rAF)7 a: g- ]" {/ r- v/ z
})8 h% K' D; a. B4 Q* S z
</script>% ^5 A& W- Q* }
3 `$ D/ K+ T4 s$ P4 X( G
1
$ s( Y9 f' `; x' q% K; U" i21 v# T2 K; Z% `" s4 C6 ~! z( `
3, i$ s( \6 @( o* h( @
4+ [% @2 N0 \* k" U$ x* Q
5
Y$ T# N: q9 t* V6 f0 L9 G6
1 Y6 \. Q/ m7 y# ?* o0 z6 L; V& o7
" h) ^" j9 p/ ]& K8) ?/ q/ L' k' o) Q( b! f, ^
9- }6 O1 S4 g8 u1 s- E
10" ~2 l: k) i5 ^' t2 `* s5 E) u% Q
11
$ V+ z# G$ o7 u+ B. l8 e7 Q: a: c, h$ K123 j3 C% N4 H( X t4 N0 v
13
0 { d0 @- L# P2 }/ A: M6 v14
) [! e$ P" D; ]- r) O15" p/ E7 D, T+ m+ F3 G3 G3 H4 U
16
7 Y: j- N( ^' M, t17
D3 t/ N& J) g7 W, @2 x18( m) @1 q' ~/ @) `2 w9 V
19
1 h2 Q3 x# B" Y206 S5 ?* @* W7 n m' c" ]
21) _8 [: H( g$ X5 A8 Z
22
9 ^* M ]0 P, S) m; N5 u$ ^7 a1 T- p23& @9 O- G( R6 M- d+ C
24/ q% R4 D# p0 E) S
25
' B& m& \( P2 H+ g8 f26: ~4 ]6 |$ {. s$ o
27- W8 I4 K0 N. }6 l
28
7 L0 i; s6 r. s, k29/ ~' }! f/ x7 ^
30+ |; C$ T% Q# S) Q- S4 q# M2 J
31+ y& D, N5 @! ~0 z1 L, Y) P
324 O" H% ^- ^9 O2 _
33
# s- G+ b1 G7 q) f! E+ i5 [! K34
* W5 t$ s* w+ C, r9 }# M% o6 b, |35; I! j( s9 r, o; w% q3 c/ G
36
6 P7 w! D; b8 @37: D( A9 b1 }% X7 u* X
38& B; @: |- g. J" a
39
9 e9 M& P6 g7 f A+ G7 n5 i/ @409 B1 q! R& C* b' b# ~' m+ H( N
41& b1 E. l) X7 |- l+ l! z
42% Z F0 ~3 c( G, P8 w
43
8 [& u& |3 q2 X: u9 C7 }; i8 A$ w44 B$ {# A, D6 j/ Y# L7 q. I
45
# h' S0 w( i0 ^ X* l- X3 l46
2 [: C2 q( ^( P476 m) X! ^3 y3 V* F
48( _" O7 F8 ^. i7 F" w7 ^. K9 `
49$ G7 B( X a2 b& |
504 X5 t: I4 O& R% r
51' h2 p! u1 P$ Y
52
! z& y; k- X& p9 r. \; d53% x0 R1 \. }7 A$ r. S
54
# P" i- y1 ^3 Z; H55$ O" ^9 D2 q, U
56
; B/ x3 \# {+ h' a, N57, y/ M$ V6 f9 ?" t0 W3 P
589 T2 w2 ~; J1 U* u+ u5 d! E2 }0 {( J
59) ?/ \+ c" M; V% U" ^2 x
60' F! L9 L' W. k, C: j+ I6 v
614 p1 p) e. @! p! T: M7 Q1 j+ {4 o% t
62! s8 W* a: n+ F0 ?( o1 e
63
. c8 `; G$ k2 y* e( k8 U& J! K t64
w3 f& i% t- x" F/ T, ~65
8 y, {$ g' t# b$ i1 u* H9 e66
( V) v( A9 z/ T H676 k$ |: F" \/ `7 s2 M# o
68
7 X* @; }0 w X# a* M2 Q69
. h+ D# r t8 z/ T& F; \- @709 |& T0 ? R R! l8 @! J
71; s% w+ I* h6 U) {: c' z
72
# }6 t& A1 G6 p8 E9 k6 x9 r7 T* S* y0 x73
8 j0 q J. v. u0 j+ B( ^( E74" \6 G r3 X. q+ w: o/ J
75$ f7 Y2 y- T) k" L) c6 e
764 b0 x' p9 c! ]% i7 l/ |: \) d
77
G* @0 X1 S. }4 s% I( X- n78+ R7 p9 F" u9 B( Y: r3 _
796 p1 T; G% B& X3 ~
80
9 }. L- J$ S* M, [2 J3 F3 }1 H813 ?+ W- l/ D. M. c! B
82, K' j) @- X* E/ ~, y& ?) {" R
834 r( }0 Z6 v; R) A4 Z
84
( f* u' o0 L3 T9 U. s& z851 }' N5 l# O: F' [" r4 A8 b# ^
86
" x& _% ^( i$ Z1 [9 O0 ~877 J2 x+ ?$ K$ S: W
88
+ c4 z& u7 H; \892 `0 a' F0 V# w2 T- k4 C- ^& j
90
) w6 a* S' N- g) ?91
3 H: _) |% L; b) r; v* A92
* j# D# A7 L; k: J& I93
7 i8 A3 b3 L, B94
. A1 H" A0 D! A$ F! ?95( a* f8 Y9 y5 F$ G5 C
96
0 R' S6 ~( ]) `$ l% r& j/ {, v- O97
6 d% ? S2 _3 h0 P98
( f# \- d! I( p1 ~6 K& x990 \* |/ @7 ~1 Q( Q, r8 B
1000 m7 P( x: H( l
101 o! g y$ Y5 W4 Q3 I- ~* z) y
102. @+ j9 y, `% K( V4 [1 M; o1 E
103( T4 T. _, j7 I! x, C0 O
1046 W# C8 i' x$ A$ w {
105) ^- a8 D6 {( x* m
106) s [& d2 L0 W& ^
107
6 n( P, p* w3 ?$ A7 X( i1080 r5 T1 L2 x' B% N) t* h; c
1096 P. j( u6 z3 d3 P& [) g
110# ~/ `& Y* {% q2 U' s# k
1115 H4 @7 g4 W# k- I3 O% w
112; n" x, e: f- A8 E9 {- h4 w
113
, r" S0 ?3 y ^/ }4 D114
$ s9 j+ n- o# J8 L( R1159 v) Y, Y& a8 h
116
3 b' C/ \# Y* U" M. v1 t: Z! v117
" |; i) P# }, O8 e+ K) K118
7 n1 I; n1 s8 P" t v119
, n) k( P( K6 K) }: k# w6 ^- ]- ~( n3 u120+ O- C0 M6 q" a' B
121- u* i* J4 a& v3 X
122/ J1 V: x3 t( S' }) ?1 o# S
1233 R/ P+ _6 P8 n1 P2 j7 p* W
124
' @0 A, ^' K' Z- X- d1253 w b$ @; }! d2 k4 p5 \% ?- [- s! e
126
3 L M! K; C$ K8 ]2 W/ L1279 W& }+ g8 {( q6 v. L
128- v9 x9 J/ x* y9 Q: w: o, `0 s
129
. j: c: z5 ?# h% w! G6 a130 ]$ Q$ Y# P5 k
131
E( B2 B* B, ?$ |3 N132) a) U( G6 R- j% X3 U
133
3 h+ V5 Y1 q9 C) R4 \8 c+ p$ a134
5 H5 s1 R# ~1 I0 N' a: d1358 Q9 l, {7 l$ r( h2 D: l2 X+ p
136
6 K5 \% E" ], O3 C# V1375 o* Z* m+ r. p r
138$ b" ~3 r7 S- E2 ^; C0 S" W
1397 j; q& K9 c- F1 v
140
! K3 N7 O8 J% a. @; N141
& L3 F4 y: }, |5 x. g. s$ n142
0 E/ R Q; B% L+ m/ i2 A* K6 D1439 g( a- ]* w( @- X9 o* a
1447 T% [; a. m* K" K
145
/ t9 y7 P# {! g# L146
8 R; b1 B& v: g; y5 J7 K147 X) O, M! g9 g+ K; i
148
2 d, w: R/ O0 o6 P149
6 _; @2 E, X% ?8 G6 I: n150
+ w1 K4 ^/ ~) Y1 a9 D1 ]151
3 p" P- |6 C3 W8 W+ e& D: X5 p4 N152
/ a' L# V& t' U( t153
8 L# e2 u5 S- \& i7 m6 G3 G; w1540 T' M( h6 Z7 C! r$ F
155
; D# y9 S( [7 E& H7 u( ]156
0 y# |' {. {# F: k1571 W/ I1 h& f: I# \2 w
158 B2 M. @7 r/ [6 l- i( k6 H
159+ }2 L1 a) J* W1 {
160
7 N4 ^( v9 d9 h$ s# C K1616 R- [6 l2 i# D
1626 P* L. A$ N1 g, v/ e! h
1630 X- r. u0 g$ \: Y
164
8 U/ y0 ]8 R" i; m& y) Y, E165
( Q- C6 A! A8 ^: Y$ L166( \1 Y0 G: B7 y* L3 T
167! |8 L2 G! `2 k& y! q" i( P
168
1 e: k1 Y8 B, B: S169* ?# |4 }9 m/ p$ B* Y: d
170, s, j, K4 I! Z* ~( u
171
4 o$ _( J7 J3 b) S- O9 C, { O. X* p" X" ~1729 \. T# t% S8 }2 B: p
173" ^: E2 t* q# @# |, k: x
1749 A' E: G! d5 }( l& o1 z2 ]+ D
175; O# y" W4 s% p
1762 z) p+ }2 g, y9 p: ?2 ~7 _) ^) d
1774 H# c& v9 N* J6 g
178
. E- c- n0 O8 _. D179) K9 U$ h U' a( A0 h2 ^
180
8 I* T/ e$ j' ~181
% o) s" G$ q, m& A7 }! f3 |8 V182, |$ a& p/ T( g, C: G
183
6 t: f% D. a2 w+ M: S# P3 ]- X184
+ e, ~# Z1 U% K' W* V! O185
/ A- L( l7 U/ G5 r; z$ `186
4 I7 A3 h/ g* J187
) d# s+ f* m- T/ ^/ i188
; S& C1 F7 m, R3 t3 [189
3 b$ y- z- h+ G1908 c' q2 J: \% E( s
191: J; e& G$ ~4 }8 k
192
; ~5 @+ z$ ^: b3 X5 G6 A4 u! T4 a193
* e" x5 c4 d8 G$ |" e1945 O7 ^) L! t2 X) Q9 S
195
, _: r+ I9 ?+ x+ C- n" A196
4 l& D; ~6 Y$ y. A197
7 ^$ P% ~9 A. R+ @198; J6 ^/ [8 F2 M2 ?/ t7 G! O
199
- j" ]; u5 X# c" F6 y200
3 d! h) k* b6 M5 ?8 w, t# D* P3 T! w. v' a201
6 X8 h& @3 o/ ~- H0 c/ X& G. n. A202
1 V9 [- z0 ~* b总结
1 ~2 j6 d; A0 q: G- M自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
8 V, I( X8 n; ~( ^9 u! t
. V: K( {0 m* p; S' Z* [* ldemo演示
( P0 O4 A" M1 F2 _) p! D' E后续的线上demo演示会放在
: ~* B3 Y+ V$ {9 b9 v; _demo演示
8 g* G* @5 c9 s4 Z3 s; s完整代码会放在' c' [9 {! [" C: L
个人主页
5 q5 n. F% ]) f1 k! I# @1 ~
) A' H( z5 f( ]. F* D希望对vue开发者有所帮助~
3 ?. I0 D) R1 b5 [! L8 F1 T2 N2 ^' f/ d% d( @# A6 j1 J
个人简介:承吾! I! c- L% F$ N' u
工作年限:5年前端! t% n* ]0 j$ P* J3 w* G+ h
地区:上海
! V* u6 G" H8 A$ L个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
$ z+ }2 O7 g" `/ z
0 `, s& B- }1 o! |$ I
% l/ E# K* c' K7 J
* t5 u' ~. N4 Z6 Z0 Z+ w% j* D0 p7 B Z
————————————————
' Z1 H8 R6 }; t: |+ F ^! L) p' C) T; J版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
6 M+ ~, `7 W6 G3 f8 ]8 P原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
! e0 p2 n/ v: {# Q
& g2 a2 U+ ^4 Z; K, I% y- ~5 @ |' a: v
|
zan
|