- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565164 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174772
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效
0 }- Z6 @' K, M ]: h5 [; J( ~3 }1 v) t! M" A( C9 e" g
前言7 d; G8 B. W; b
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:
T% i( D5 f' y# |, s* [TypeError: Cannot read properties of undefined (reading '_c')" o# v4 X1 r9 N5 X/ P
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
( @! m8 L# ^ F" ~& @7 i1 J7 i. g$ S% d5 D; A9 Q5 D/ h. S' M0 H5 D1 i# x
1 u" @: G' J& {* u9 r2 r思路
/ Z, z2 H8 l* M. T) p使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
! c$ R p7 {3 N: y* C4 |( Z) m/ M8 d/ Q1 ]% C5 M5 g) S# t2 r, }% T1 s
文件目录
- k$ h" ~3 {/ [0 K7 X% u/ f1 {
9 O+ [+ l4 ]& P- X
# g1 ]* V% q* Z使用示例- G3 y# G2 ~& B- R: j
<CountTo
2 T) R: Q/ v s: _3 I* X+ J; [% Q$ I :start="0" // 从数字多少开始8 Q: x$ w" A8 t' R
:end="endCount" // 到数字多少结束1 K1 v6 m$ [7 I! t
:autoPlay="true" // 自动播放
' l! [( h5 R" Q* y# S :duration="3000" // 过渡时间: h; p9 }' N8 V" y. T% C
prefix="¥" // 前缀符号, R. `( e, Y! I: L0 j7 X! e0 L
suffix="rmb" // 后缀符号
1 i7 ]' n, \, ^4 ~+ C />0 D8 y! m9 x, B7 K# v
1
3 W; H! T4 `5 o; }" t) H2
% M' q6 [& C) {5 n' ` N( g3' U% G& t ]9 T" E D V* t" `8 F
4
8 t; w3 z8 P( l! Z1 k9 g' p' v! C+ p5/ \7 ^3 M- }3 z, M4 c1 \
6( Y7 U# ]4 m) `4 q. _7 U# _, E
74 S% ]0 f1 C+ l& h
8
# v" p8 }9 {9 S2 H5 F, |入口文件index.js
" u w0 a3 z1 R, S4 B, q( l6 b2 D& r* V, h% ~! \* o
const UILib = {' V! i' J( A/ I( v4 C) Z. j2 a
install(Vue) {
5 u6 q5 E- U7 w0 u+ r2 k- r Vue.component('CountTo', CountTo)$ p( O) b8 O+ j4 F- I5 S; Z
}1 m; Z$ ]) k- y. _" U
}
8 |9 v- m% m8 }5 w( I! `& N* p0 o' P1 H: Q4 L1 a
export default UILib
3 V( U g" E; ]# s8 }
/ c* J* F; H& Z1
8 i) l" c L) H2
4 q1 g; ^! n. u3 B5 O) A" D' e3
3 L( a& P1 a2 L% m6 Z4% H# {0 S( O+ A8 Y }
5
. Y2 W: E2 Z d! l60 {7 L2 J" ^& U! D% N
76 \" \! `: I4 B
88 D4 g X* e5 T
9# w/ p- T$ `/ ~9 i% i# ?9 e# Q
main.js使用# p. u5 J: _! \8 K: o/ C
import CountTo from './components/count-to/index';. y& w( f) W6 h7 X) o
app.use(CountTo)( K9 i7 M' `- |0 L
1
; o' d5 k0 e: w; a n2
* d. X, k1 } Y! mrequestAnimationFrame.js思路6 u* n2 Z% `# O$ L" B% I Q
先判断是不是浏览器还是其他环境
: E( Z$ O/ n+ a如果是浏览器判断浏览器内核类型
" m6 V4 C$ [, x2 n; k如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器0 F5 F6 e8 U# \9 u7 \
导出两个方法 requestAnimationFrame, cancelAnimationFrame
1 ]9 _9 `' ]/ A7 C各个浏览器前缀:let prefixes = 'webkit moz ms o';" i7 B. H' R6 y, _/ X* F0 [$ M5 e( i
判断是不是浏览器:let isServe = typeof window == 'undefined';
3 a0 [7 d1 K7 {1 P- M增加各个浏览器前缀:
$ W( c) q0 @8 e4 Slet prefix;
2 Y2 ~6 M6 ^2 vlet requestAnimationFrame;
1 ]% H9 `: J# `5 g* I; |6 [. }let cancelAnimationFrame;
`/ ^% E8 A B2 n// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式3 s' ^ t" G" W& }3 V; j( a
for (let i = 0; i < prefixes.length; i++) {: e+ u, p- z9 K$ J5 [* M
if (requestAnimationFrame && cancelAnimationFrame) { break }
6 S0 ^ `; @, N2 f6 | \ prefix = prefixes
* e' x2 m6 ^+ P4 X) D/ L) W requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']9 t4 h* {% y$ @7 U
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']" Y- l5 t* D6 P) H
}* K* b' K; T' D, \) ?
) E% ~# E4 n9 ~" V9 Y //不支持使用setTimeout方式替换:模拟60帧的效果9 C Q1 L7 y) Q$ Q
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
+ {3 v2 S4 A0 f, @* R if (!requestAnimationFrame || !cancelAnimationFrame) {, }$ d2 `# Q, R, [% C6 t
requestAnimationFrame = function (callback) {; E" z4 b5 M- G' M! o$ t4 m
const currTime = new Date().getTime(). C' T) j: o( ]: m- k! z: p; t
// 为了使setTimteout的尽可能的接近每秒60帧的效果
2 |, a" C$ N' ? const timeToCall = Math.max(0, 16 - (currTime - lastTime))* y: k( Z. g8 E' w
const id = window.setTimeout(() => {, J* i# @# ^3 g- o7 A- l( o
callback(currTime + timeToCall), `3 K) u- L3 e' E% n2 n' J+ i
}, timeToCall)
; u) C* j9 A2 E" ]+ j( ^: E1 m lastTime = currTime + timeToCall
+ |7 i- j$ | h. | return id
) C7 x6 ^$ z! S% x" `+ ? }
3 z. p% \8 J( V. |& ^+ t. N/ C+ j+ N; O, ^
cancelAnimationFrame = function (id) {% ?& Y: P* f+ G! B" H9 R
window.clearTimeout(id)
- N4 n |, t9 v* f }1 \# L$ Z2 L4 S( Q) T' P3 J- ?
}% c, d( {( t: `: ?% X( D8 H
2 ~2 v% b& `# U" d# W1
4 {5 O. h6 P4 m' d7 A6 F28 B5 M# A! A0 {) o0 d' e# N0 @
38 d! w- M3 Q4 ?4 C) V$ ?; r+ E
4: W! P* ?) p6 w3 y! `8 J0 N! o
5$ U) E ~5 ?) K# A- L
6
# I) F1 y+ Z% _% s# C; D- Z' k, V7
6 u: Z6 I( x) e, e1 A' \( ?8
' C/ M1 e5 p; p U5 s V O8 j9
7 c0 u5 R) Q% _- f2 {) W10
2 o2 w) A3 b! Z o( Y2 t+ z4 q11
, n5 Q9 X6 C- V2 w( x0 h124 j. ], X* q6 ~! q( [+ O
131 }' l$ r4 h' _( z/ O: _, {) { c
14 q/ F. J$ k, p: A3 F* u/ ?3 i& I
158 D: g, S* N/ z. c& I- ]
16
( _- ~9 Q" @& E e$ j, \17
, L* K, C M5 C0 i* `4 P18, d1 ?5 w. U6 n2 Y% L- ]
198 b' d& s' `* W& [7 G
20
3 Q \1 c! j" a6 b/ N% U7 X5 @% S21
8 b: C5 l2 {; W/ |: y; V& A6 B22
% i2 R1 W0 Y2 e: D6 \: ~23# }- {+ y o! O [; `
24
* a% ?, D. r) S, l6 R250 \0 z( j" U3 w& w, J
26
) _4 Z% J' U- Q! `# I2 P3 c27" L) w$ u& M' r! P2 E& i1 Y
28$ ?! f. b% W+ X7 J
299 L9 u8 l- v$ J' l! c# V6 c0 \
30
B7 B o2 J/ r" z6 K& g* n315 [8 \& _7 }3 k# z, q
326 [7 a& ~8 t5 \, T
完整代码:
O5 v. b/ z erequestAnimationFrame.js
7 g; f6 Q7 Q! `
2 S: j( ~) }; C7 _; K, I& V2 ulet lastTime = 09 B# y8 X2 i; p( d
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
. H8 U7 d. K- y: X: y- D, n+ r0 g% R. [* z# {
let requestAnimationFrame
, c8 r' V1 S2 M/ v( l; L4 olet cancelAnimationFrame* y( w0 _ |8 t% |+ ~/ ]( D
& N9 `% @+ q4 Y) z2 L// 判断是否是服务器环境* E' H7 ]; V) ^. j3 F3 p8 r; W
const isServer = typeof window === 'undefined'& d/ s. k9 M. ~% c. _! G$ Z/ L& w
if (isServer) {# Y8 M, ?& t' F8 F5 u. B; J
requestAnimationFrame = function () {
; }0 X% |. y/ e1 U; Y* S. V6 { return
# S+ z; {# a* C9 a J- c! H: r$ P }5 J3 K- M5 h4 } q! _, ]
cancelAnimationFrame = function () {2 E- `; B+ \3 w7 ^- N9 x; J
return. P) J: [2 M: I. o. @6 o
}
( q3 @2 r+ T; d} else {
1 Z& _" b5 Q! H requestAnimationFrame = window.requestAnimationFrame- X( n- i. g% I0 x" V% V, f
cancelAnimationFrame = window.cancelAnimationFrame
7 [* }! ]+ _, b9 b6 `7 J9 t let prefix
9 }+ |6 Q R: d. C // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式/ K, X& v! h6 ~( z( |* p
for (let i = 0; i < prefixes.length; i++) {
/ o+ G' z' i" ?* U if (requestAnimationFrame && cancelAnimationFrame) { break }+ I0 t |/ r2 W/ W' ]. c
prefix = prefixes
# G3 d+ g( E+ D5 W/ B+ C8 i |9 o1 M requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']* F2 \- E5 u+ t1 _; b
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']3 V2 H0 t% t( c, H( N$ N+ Y
}
" g q7 S4 t6 R4 o# f4 l# j
1 s5 T- M( p- F) C // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout/ s: \4 o; ^& a$ S8 o# G6 C" L
if (!requestAnimationFrame || !cancelAnimationFrame) {
- Y0 O4 U @0 H2 Z4 L0 B requestAnimationFrame = function (callback) {
: Y9 q! E* Z$ Y9 e8 P4 U# z const currTime = new Date().getTime()
+ h- S+ B, o- \* t* w& G6 f4 X // 为了使setTimteout的尽可能的接近每秒60帧的效果
7 d/ }; O" {. ^, L% N const timeToCall = Math.max(0, 16 - (currTime - lastTime)), h8 T# w% {0 s7 G$ ]* w5 k! `
const id = window.setTimeout(() => {
5 d/ E9 E) Z, f, ` callback(currTime + timeToCall)0 A2 ?3 d+ B6 N0 u2 l- y! f, d' f
}, timeToCall)
3 W9 b3 G# e. A* ~# V lastTime = currTime + timeToCall
& `; h. f6 R5 Y6 m return id
( z+ y4 m. }) p }
6 P3 B9 r9 h) n7 F" g3 H& y4 k; I2 b) ^0 R
cancelAnimationFrame = function (id) {; T5 o: @/ [& L3 F
window.clearTimeout(id)! d g# |+ |7 {
}
) M$ p4 ^( l% `5 O$ [8 y% Y. } }
# E3 g, Y. L' N, \8 V; L% o# X}
8 A9 S% P- K/ u2 I5 r3 X. F% x& v- C- e( s5 S; Y. W3 J" r( ~; g
export { requestAnimationFrame, cancelAnimationFrame }- c [' ~2 a; k0 O0 C
; Z: ^) ^( F j
" Q4 d# H( R+ B) o/ s& Y1
$ p% j- Q2 n5 }2+ y& f2 [" i |5 S$ }* a8 J
3% T3 V3 S7 m4 T6 d
4+ F0 f2 [$ Z; k& @% E v1 T% Y! L
5# N6 Y1 l# u9 Y4 j5 s2 ~5 E
65 ~3 l u) {7 C9 ? P; E
77 H* n; f1 q+ N" a$ N
8
! N5 i2 H/ Q9 Z0 {90 R; G3 ^2 l8 C! x/ [
10
8 [6 i2 y$ f B# y7 j0 V: w# ^; t11- B4 s! {1 p, [4 V* N
12
7 ^ Q; y+ P- e, }- m8 @! Z3 E6 w- l13! e: Z4 ?+ q* {- [# Y4 }5 m7 n& t _
14& z1 d# F* n: l
15' n/ V- c$ m% f
168 u4 @8 r! M v
173 ~; N. p$ ]9 N) A
18
5 I }& { N3 x* T9 Q/ k% P6 V19" V( o5 m; W- G" Q" \
20% N/ p: @6 Y- F4 {: G8 K
21" c( F& R5 C: ^+ B
22; R8 ]# ?+ o+ W
23
2 n) @! a* g+ T+ J0 v2 X( y244 q% n( r, j1 d" u8 b
25
- o( }/ L) O4 H3 y! {+ w26
+ Q* `4 h }4 U; }* K i) h) \27
, |6 m2 Z" K) t, |28- |* w/ i; l2 k
29
5 \0 @5 |. Z. h4 x/ {30' c: K0 M: G% c7 n0 ^8 x+ U" y
31
% X/ J* l1 h0 V0 O' V3 q+ E32
0 F! u" I. {9 S6 d- ^33
3 b( K' A, N% n3 f34
1 N+ @0 z9 B$ t& A; k. _$ o! p35
2 N' K n+ p; x9 A36
8 p# A+ _- d1 c# h4 A6 y374 u/ Q1 I" t, X- [5 X- f. X
38# P) T8 H7 S6 X- T' O4 C
39
6 j4 l$ D4 b; r0 C6 \3 w! _407 n6 \8 G3 P; N1 N
41
- s, V% o- U8 J4 R- b42
2 C. h- }- Y, B7 T9 b4 v) s+ |4 A43
# K$ Q/ V8 u1 B: l6 ?44
( @/ |1 Y$ {+ {453 r% R! G9 i$ k& F4 j, h: F/ `4 O
46. _* z m: p/ S f4 T& M3 G
47, v" T" K7 i$ I' B0 J6 v( p
48' `8 G' s8 c! e/ F
CountTo.vue组件思路; N; V5 k' b3 h" l' r1 ^; I4 B
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。
; Y7 Y$ A( f1 r& I9 \9 ]- M' `0 _& b2 l6 r3 g D8 u3 u; Z, V' d' n
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'& F! z; E0 Y7 E, B$ N
1
. y, j3 j9 Y$ J) H6 w需要接受的参数:, S- J2 w# w. r2 T8 r& g
. r) G( T3 X9 K* a' v" _. ]; Gconst props = defineProps({9 w6 T% K6 M2 @5 X2 n2 r
start: {
% f3 V" m0 T1 s* n0 q6 q m type: Number,
$ j" ]( i" s! K/ G6 u# B required: false,
# k% @+ l# F$ a+ \; {4 q default: 0( J1 z. V: `, Z3 Q& u
},
1 b- w" b3 S7 R$ k) [ end: {
( ~& r$ J, A8 X+ C! G; g% v type: Number,, t2 Y9 o, t5 g. R. [/ L
required: false,
2 @ e' ~$ r: ~- N/ _/ T. _ default: 0% @9 e! k) L7 b2 D8 P- ]
},
; p4 ?- X# P: \' V duration: {4 T( g* Z+ [1 C( u
type: Number,) w6 m4 A9 _3 D
required: false,
7 C( G7 F4 l0 Q; ]: {( Z& E default: 5000
0 t, R, E* l6 h5 m4 | },; q2 J( f* y+ Y
autoPlay: {" U6 L; P0 {& K1 T! s6 T
type: Boolean,( `' `) O/ ] g7 ?- O1 O
required: false,' A7 }% b; F. ? I+ \ m
default: true
- \' B7 j9 e2 O },
& w6 P% M9 r* w( Y; J* k. P decimals: {
% n A4 g6 T# ]0 f type: Number,
9 Z. c$ n0 u8 A) d required: false,
. H8 D% N m" g default: 0,
7 p! W) L3 B9 X$ p9 S* I! k validator (value) {% y& A" x( G" w; ~
return value >= 0- g5 `6 S; H! E/ q
}
' }7 s8 a2 {( s e+ H. R3 L6 D },
) s- F/ C2 u8 _1 c7 k. K2 w decimal: {. V6 Z/ P3 f, O {5 s/ C: k, s
type: String,. a3 r; t( @+ z$ [$ x+ i. U/ }
required: false,$ ~# I& I. M. T& F7 m4 i/ Y: w
default: '.'6 ]+ A, V0 K) p% `
},# a7 ]5 p3 q6 L; M
separator: {- c. W1 u9 h& k4 E: R3 Q% B
type: String,+ }" R& {( X! J4 z/ N& B9 m% g
required: false,
% r; e8 ~5 f2 z9 z9 Z1 v5 Z default: ','
' s5 ?3 A8 |. I* k4 y: {+ D },/ L1 Y4 _- v" J
prefix: {) h P a" |7 D1 ?( \# M# x- \: P* o
type: String,6 Z. H9 I0 @ |. z3 d9 T
required: false,& w5 u# z7 |7 Z/ G& b+ C# c% S- V
default: ''
' }0 h2 m8 x6 Z },
6 d. S2 K$ `* D: z9 n* o2 D6 u suffix: {
% U* }+ ]4 I/ a0 z7 I5 f type: String,
Z% S% l* T- ^' E! q required: false,
4 o" B' @" l* ^$ J4 l* Q% k# ?* ~ default: ''; v0 B5 D; j8 n/ I; A4 F
},
- f+ g6 |- U: Z1 A5 L# P/ d% {9 S useEasing: {
% c' M8 i& _9 u: u. h type: Boolean,
3 D2 W, j8 Z! ]( v2 K required: false,3 c8 I5 H3 u- R/ C. H5 y2 F
default: true
. R w. @9 J6 r6 x9 m% F( A8 r! L6 p },
( Y+ Z3 f i5 ~ easingFn: {
) M) y4 q# H7 B8 J% x type: Function,
) I1 ^5 u% `& j2 Y( U default(t, b, c, d) {, ?& \8 r% Z( l5 ?
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;0 y& V* w6 A, d7 \: k* i3 c
}; m& P S% e: Z
}+ n' w ]+ d" V# @' m$ L
})
% U6 t( P7 H1 c6 i& N. t8 G+ l4 N+ J( X' f8 @( |$ X* P
/ g7 {1 A9 Y; {
1
6 z' H# D/ y- B, a1 T2; H4 ~3 h2 r( X- W% k r
3
' g2 u) `! t% S# t* h3 H( i48 _( @8 @. _& [3 S: Q7 U8 A
5/ ]8 q7 z7 V2 p. C, R
6
}" t) g' [- x7) m& ]( ]& ^$ C1 [4 m8 J6 J1 P' v
86 v/ {+ [' ]4 P9 e( B& |) ^
9
7 W% [" x T- n% j, ` p- O3 Q10/ P/ t0 h/ ^ j7 K+ X7 f4 k
11" Q1 {% ^5 k) \0 b0 N
12
$ }2 }! _* v0 P- J136 y( h9 A0 }" X5 A5 P6 V6 c
14
# F+ ?" J' ]) V# t- @6 D& r. _( u15
, q" _" J8 O8 e/ b. l16( C. Z. |- T. s: `8 k
17$ {* ~. ?+ ~: v' |( s
18+ R6 |4 d/ z; ^4 C$ N4 W) Z, J
19
7 J, u. b3 b E3 F% d20
+ u! ]2 W0 Q7 q2 g$ c% t0 T2 G217 C/ t' h @7 ~7 P- U# {/ \' @
22/ b7 e+ V5 U4 i2 J! N9 B& ^
23
5 C! d F5 b; J. t6 f4 l24
- P/ \9 ~0 L/ H' y4 E8 } p25
; J0 ~. U7 x2 F/ A& @2 H4 E4 m; H26! |4 d+ ^* j% v
27. M$ [! ]* u2 n1 q
28( K, K. A1 I/ L8 S: W3 n1 w8 d
29
- }% d5 [& N$ H6 d. h8 W30
4 z# }; U6 h1 b" ?) t( z" K* X31* L) M; I+ [$ U$ @) I
32
6 D. H2 }$ H1 X2 Q9 Y. \6 M( f' x33, K$ r4 n4 k* x% g6 d) t; a7 `
34
0 m/ f; m3 d* c9 D5 u! l# L9 I35
# r5 H' h9 f2 c36# a& j# K2 s+ D* [" Y5 t$ F* J
37: d4 s" K; y- b
38
: [! O9 X! t5 s: N% ]39
7 ]& o) e2 |+ K2 B' M6 J1 `1 j40
# M: i; D8 n3 F2 C41
% I( a n5 S& D* w8 d H/ q8 f- H42& R6 i% W2 @% r
43
) R, P& }7 Q% e$ a) Q! Z8 `+ [44
1 r( Y5 K1 W/ u# t# Y451 q$ ~1 @% v' [5 J
46+ ], L5 @/ n9 n6 i: z8 s; ?
47& o5 N# @; S) r5 z- l
484 J( O1 a" Y* e+ E3 M ~
493 [& Q7 O4 c# i: Q
50
, l5 [5 T5 E" \3 c) `51
q' a9 ?' p3 V( l5 e1 [52
a+ A" R& Q3 C9 H# } c3 f8 R53( U' u, T. Z% [8 ] r
54' w3 f- p0 H# ?
55
3 y) r; y) {: w! F a8 ^2 L56
& r, ?* L8 I3 `57
4 U5 z3 u) w1 ?# D& P2 v0 p58
1 h7 t6 ~' A* ]7 p8 T: {59# }8 q. x( k, L7 N2 t
60
- ^; ]- p7 O9 |' B61& E( X3 h" o5 v: w( e
62$ @1 F( \& ]$ N7 j6 p
启动数字动效/ b4 l8 t8 y, W& e! d
$ \" ~5 E2 ]5 B& O
const startCount = () => {
1 v2 p! H( m/ M, Q, B0 E state.localStart = props.start+ s d5 }+ B$ C$ R Z' \
state.startTime = null
' j0 J8 }/ `. X8 y" S# ~) e' v5 q state.localDuration = props.duration; p3 V5 _* s2 h8 n8 w
state.paused = false" p6 B! K/ M% _9 h7 o
state.rAF = requestAnimationFrame(count)
N( T( J$ r$ n8 m2 F, ]}
0 X5 B' U) J3 N B. h( O+ s( Q1. L, G- J% D8 v3 x/ h+ }
2; ^0 V- o% l9 k
3& ^% c! G1 O* F- T
4
5 L% D1 x$ r; _2 R/ U7 h. M5 k! B+ l& z; ], F7 T2 {
68 N+ E( B& R9 A" l# W% @
7
& F7 u8 y% W, q8 r6 s核心函数,对数字进行转动
! S* R' a8 G8 I [( E r* J' j7 L2 H) a k
if (!state.startTime) state.startTime = timestamp
8 c, c. C! c! q P9 I1 w% Y state.timestamp = timestamp/ C1 ~1 ?4 s3 C/ f, w& Q! p
const progress = timestamp - state.startTime E: G! q, o: B" J) _5 a* Y, \
state.remaining = state.localDuration - progress5 D6 o! B" K- }0 C. {& d! S
// 是否使用速度变化曲线+ L( B4 S. F$ h4 r. q1 S6 m
if (props.useEasing) {8 j6 ~6 X. h, ^+ v
if (stopCount.value) {
* j; G1 n3 g3 J- e* }4 N+ ] state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration). m q! ]. x/ R) E
} else {
1 u8 R2 w9 w A state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)* M- a& G8 X. c, T- ]# e! o/ e# B
}
5 M% l, V0 V1 W; u' k } else {
. L3 ~! G- w7 r/ ^, Z8 q if (stopCount.value) {
9 k' ]+ x) z Z* x3 f% U state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))& {/ \( ], F% i; C/ d1 [8 b& D; Q
} else {0 p/ l" _- {( f6 h& ]" R1 Q
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)/ o9 j% X6 X9 W" T8 U( C2 _6 G; ]
}
! t6 I8 p" S$ \- C( w }
, |4 e* d2 D5 W) ]4 K, w. e if (stopCount.value) {
, ]. X$ ?$ C# K( d" H% P state.printVal = state.printVal < props.end ? props.end : state.printVal+ E) ] @/ r# ~* r( M
} else {( d& \, ~9 [5 t+ d) W- L
state.printVal = state.printVal > props.end ? props.end : state.printVal1 A9 W( h- y. }) q& }, e* a$ A
}
0 H, A" N$ X$ ~3 r6 \* ~
+ M) g! P% S6 p. T Y3 c- ^2 S state.displayValue = formatNumber(state.printVal)
) M/ |" O8 |8 b6 s- } if (progress < state.localDuration) {$ R0 B: w5 e" e' y1 a
state.rAF = requestAnimationFrame(count)5 l0 g; ~& N: P/ N
} else {
' t. y# ?) e% C- a3 X6 a emits('callback')# P0 g9 G* K3 j7 p- M7 G4 B
}+ i% K8 x7 A/ i% B; r' K- b' Y
}
" ^ C, \; P8 {
* ~# H4 Y0 v: g3 a( v
! d1 c. Z( }) J* J// 格式化数据,返回想要展示的数据格式) e; t" C8 A3 H0 _
const formatNumber = (val) => {
) W/ _! N$ q3 {$ L/ ?+ u val = val.toFixed(props.default)
+ d* z, N: o9 A+ v( j' W' E7 D val += ''
2 z% m; W5 C" r" E% l R9 l const x = val.split('.')
' e8 q+ T8 _ @/ i let x1 = x[0]+ o3 R( Y9 u- @5 A1 d$ h# {
const x2 = x.length > 1 ? props.decimal + x[1] : ''6 F& p2 V; k) ?! a
const rgx = /(\d+)(\d{3})/, y3 O4 U& z; M: z0 u* Q O. h: b
if (props.separator && !isNumber(props.separator)) {
' u; W" {: s& l while (rgx.test(x1)) {
8 Y- ]8 d1 _+ X x1 = x1.replace(rgx, '$1' + props.separator + '$2')
3 @- @; C/ G1 |0 y }7 a. H Y# H8 h v2 i/ b
}: q4 }1 b4 U. }& |6 J; Q
return props.prefix + x1 + x2 + props.suffix6 j! c5 M3 R) C+ t% p9 m9 u
}4 P4 ^$ F, h4 }/ a
* Q/ V9 Z; P |, w5 }1
! G! i0 c9 r. F! I" a! J* _22 R3 ], I1 O: h+ [* y9 @, g& T4 U
3" D* f7 |; z4 K5 ]9 I0 V4 ?
4
% `" @' N( u/ ^3 [8 K5
9 x- Y8 i. e+ a! S0 r' _# P* n6. S4 i. D9 H( L/ F' E
7, G0 E' e! n9 [2 k3 |
8
- W0 C: `2 d3 l( k, B; B9 l9
( B1 N e. R5 H2 e2 p10
8 [' F m9 D: U M" i117 w" C$ t5 M, P
12
_) I1 e! d7 R8 s- T13
5 `' |& a# ]/ k: U14
5 Z7 I5 d1 S7 O+ P* z* I15
0 I) z5 q6 W2 F2 V$ B16; \% X; V d4 Z9 k9 E4 ^
17
( q# O' S: Z4 w18- G# @' b; `3 z/ k. h4 z
19
9 Q. u$ j( {6 x20
& Y6 c. O- p( J9 K4 q: F8 `- Q; f X4 w21
6 n1 Z9 q, ~) ^% U0 ?3 j22( R& C& ~9 a% c& b6 H% M
23( K; A, P7 I% I$ k, u4 @
24+ h9 ?$ b8 Q: |: l f! j; I3 d4 K! J
256 K0 {" L% g6 ?& p3 a+ m
26
, M4 X8 I0 Z9 {+ }/ N/ d+ _277 r2 s+ {- y# }1 w' W
280 Y$ u4 B* ]7 g/ C" d3 C
29# Y, {. B7 g: [3 [. o
30
) C* m6 \# ]2 w) s9 D: }31: ~% s/ q5 j1 ^, M# ~+ `: _
32; B3 h$ h8 f* T7 d- q% e; M
33
' Y# G/ W3 J1 ~0 K! m34. i3 ^! P; n8 p) F
35
3 `. W1 c9 ^; ~36
* Q% i! X5 i+ T$ o378 N) I( E8 T" A# a, z
38& m7 j$ F) ]6 x+ x# b; [
39/ u+ Y7 D! M! z6 o: P y
40
8 k/ l' r6 n; O5 c8 s41
- @! ?7 @. g) S0 N2 N$ L42; `7 h% M1 l* m9 M" p. F+ d
43
3 ?" o5 m9 A3 N( T/ `444 A3 M; p6 ~, @1 i8 X6 m0 K
45* n Z! Y9 A4 k3 |, r3 i
46
' O9 U6 r+ h I* W: _2 y47. {* F# p G( Z( j! z
48
6 M! V1 A& A! G; F$ Z$ c取消动效
- ^7 |! k/ m9 y; m4 E- y
5 h$ ?, V( y, \1 [" d* G// 组件销毁时取消动画 K, j6 R5 A b& g; L ]+ a
onUnmounted(() => {
2 f- H* U( z: Z% k8 i4 x cancelAnimationFrame(state.rAF)* I) S+ b. O% Q- i+ a
})
* g6 C' {; Y7 u( Y; o1
2 l. }) \2 J# I7 i( o5 t, ^24 i% c& E( n* T
30 x# T" e, Z. s! w7 m* R
4 @6 G- A. w# U+ l( A$ i8 C
完整代码
# Q/ K$ l7 L5 v1 r$ g) T; `
! t8 ?: q9 h! g) z. T<template>
; }7 @1 Z* m7 t2 c" }8 o: d1 Y {{ state.displayValue }}/ p% K! {% t9 E4 D$ w
</template>/ N+ w9 }/ j3 O: g
7 j7 T: A7 l% P& a/ @4 ~ K9 D
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
% ?1 G' g4 I8 t$ Z6 wimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
( i% I0 G7 Q2 n) y1 x- Vimport { watch, computed } from 'vue';
p3 d/ z8 g; @; rimport { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
" @' s* t- Z8 e; @3 \: }// 定义父组件传递的参数# _, n2 v/ G9 V! L
const props = defineProps({
# \1 ?! n7 l" W; Q start: {0 p; B7 ^0 T3 C
type: Number,! O0 }* u. t2 E0 }6 p; b5 }
required: false,
5 T: [% c% G- |) c, G& Q default: 00 D0 T- u' O' x
},
( B4 {4 ?: H. E5 S& s8 v end: {7 ]! o* J) k- F& t
type: Number,
+ D; R+ \( j. F0 k4 G3 @5 S- p required: false,
, h$ [: E! _! Z- D4 M5 N+ f5 z default: 0+ n" }& R* B6 V+ B0 e- y
},$ D6 M$ t) b2 Z7 V) G- I
duration: {+ I3 V7 a2 B' c$ j2 F- P8 ~; t
type: Number,0 X$ \" G& l2 H2 P
required: false,# K0 }& s5 d* D: K
default: 50009 ?# ~+ H1 k: A9 K \7 y, i' d$ ]/ W
},
; ~, v8 y4 s2 P autoPlay: {
% Y0 A9 Q- e$ L# r" c type: Boolean,+ Z7 s e+ v9 W& p% u' Z8 D+ z
required: false,* [7 I% D$ G- n; K3 u
default: true
8 ?. R5 {5 m1 Z- D8 p4 J* W },6 g; \2 k" y+ C" g. W0 g9 {$ u: ^
decimals: {
: B8 \: {# S/ X, _" S# D# c. ` type: Number,8 O1 z: H. y& ^8 Z5 d
required: false,* q K3 J6 Q0 s3 q% Z$ L! Y
default: 0,
9 ~: e' n% Y2 _5 G validator (value) {9 Y* G) e: p8 p$ m; Q5 {% c
return value >= 0
. X1 o2 _, w5 @' B9 _/ l }
, N7 Y) d$ Z+ p },3 g9 N5 n8 q8 r% x3 C" l
decimal: {6 ^/ K/ H" H5 B- l
type: String,2 y' L- i- h% b3 s# T0 Z
required: false,
- d8 z2 _, }2 u" y. M6 v( F" G; C default: '.'& h4 T3 |4 F5 S6 a, X7 p% J4 ^
},
1 |. ~: ~( F. O2 @) b. v I* n' z separator: {
$ W, x6 p* _) @, i type: String,+ E7 [2 \* a0 f2 b+ ^8 ?
required: false,
3 F" {3 ^# Y: r: a& m# v default: ','
: E8 K- F6 n; O: e9 }& c },! R) S1 M( `; X5 t
prefix: {& e9 Z( _ [3 k+ n `9 g
type: String,
# g6 B8 T% l( r; \! j" ] required: false,9 c H- A$ w$ @! B
default: ''5 W% a* T" q5 j/ |0 x( V
},: Q; `8 n j }. T* |
suffix: {
* t$ `/ y+ Z4 |8 R type: String,
6 ]& }% \* y( {8 t4 |; e' @ required: false,6 Q6 }9 a8 g8 w k4 U: ?6 C9 {: H
default: ''
( l! u8 R/ O$ \% ] },
6 g* D. I# l& b2 L useEasing: {
/ H% F" S, X9 }( j: [: {; V( n type: Boolean,
% ?. r. `/ q5 G3 C; c. u required: false,& @2 m2 x' H& Z' J( C
default: true
9 B! E+ c3 h, I7 U1 J+ _ },6 C" N! z( Q4 V$ }9 j
easingFn: {
- ]$ k! U" i5 Y7 m c) @0 p1 E* w type: Function,
4 o( M. \$ ]1 n$ f- C4 W default(t, b, c, d) {
2 ^! }- J- b' \( X0 I! K- V return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;' ?1 g, H! V+ _- \
}
" k9 G9 Z! Z7 B5 {- y- p }5 ?; g% \( s/ `" z8 |
})
5 Q; L% z7 p% d; k0 w# d3 t
* e- D" r/ ?% I. X$ q& Aconst isNumber = (val) => {; ~& G: T! w9 u$ _) I6 I$ b, ^
return !isNaN(parseFloat(val))7 I: M. H$ s. V0 m2 J# M w* _
}9 O6 @$ ^3 S; ]! Q
7 z4 X" q; q+ P0 }
// 格式化数据,返回想要展示的数据格式
$ x! f0 O3 K" Mconst formatNumber = (val) => {/ n! M: H1 l {6 I' ^
val = val.toFixed(props.default)
; [! h: g; G$ O9 `$ ` val += ''
0 _; w) a H0 F% n const x = val.split('.')
3 J( ]3 Y7 b* Y let x1 = x[0]
7 E v+ W( A0 p; J5 K. n const x2 = x.length > 1 ? props.decimal + x[1] : ''1 b5 a$ n$ t- ~
const rgx = /(\d+)(\d{3})/, M c1 ]. M" [5 ^0 I' F) Z$ K
if (props.separator && !isNumber(props.separator)) {; |. y: g: A) ?& W5 w) E
while (rgx.test(x1)) {! K7 a% z7 q% [+ `/ |6 b8 x& Z
x1 = x1.replace(rgx, '$1' + props.separator + '$2')* z/ V9 ]8 l2 B
}8 y- E8 y+ k( l: ^: W
}
0 K p$ E; k* G; {7 x7 `& i return props.prefix + x1 + x2 + props.suffix
7 |+ l# c5 Z7 T, T+ D# Q}5 ^+ x8 x) V# d* [0 y: y
3 J- t6 e# r% y# d! \! q6 y// 相当于vue2中的data中所定义的变量部分
: [9 Z" c. A7 Vconst state = reactive({$ |+ [$ p' W! }& Y) m( s X& u8 v2 c
localStart: props.start,
% B% ]" Z6 ~/ ?5 Q& J displayValue: formatNumber(props.start),, C+ q r6 Z5 N/ D* a: I4 o
printVal: null,( J9 R" l- u* e4 j( ]' ?
paused: false,
8 X4 D5 {3 q* d. \ localDuration: props.duration," i* N( R" |" @% T% Q# i8 R
startTime: null,1 \+ H7 @! S, [2 K U$ {) D
timestamp: null,
; d3 `/ G% _! F remaining: null,9 {% f$ G; {- E2 d4 O
rAF: null
M* D& g7 h! R. h3 e})1 E/ ~2 |/ V7 ~+ K6 p0 X
# N+ d9 T* f9 Z! }9 E* c
// 定义一个计算属性,当开始数字大于结束数字时返回true. u9 D" J. \# z0 O0 Y( N
const stopCount = computed(() => {
- h0 ^! o* d* c2 M; _0 B return props.start > props.end+ n c0 w. e0 p6 u$ N+ Z* t
})
) {( k+ r. ]+ O! o// 定义父组件的自定义事件,子组件以触发父组件的自定义事件% u( y9 J+ e" J- o5 o
const emits = defineEmits(['onMountedcallback', 'callback'])
( b h& R5 }/ i% {; r
0 Z$ D4 j' V1 hconst startCount = () => {
& Q8 V+ j4 u, g% ^ N state.localStart = props.start
2 P* }8 H. D, Q* T state.startTime = null; W, ^1 Y8 y5 V6 E7 o, v; j% D
state.localDuration = props.duration
5 A$ e2 W, a; a# u) X: X) U state.paused = false- y- u% `$ }( c0 m8 e
state.rAF = requestAnimationFrame(count)
- U& D5 x7 c) G; w( @' O}
3 d8 }* P" k2 {5 K. O/ E! ?7 M$ E( d/ S3 G! Q4 d
watch(() => props.start, () => {" U$ a; A$ Z' i: @' l
if (props.autoPlay) {
& Z3 u! q* q: J- R startCount()7 }: H8 I! z) h
}6 I( m0 d6 I3 W
})% C7 y$ E' z2 \2 ^+ H7 A
! z1 A( v# W1 \: V* ~( {. g: [+ nwatch(() => props.end, () => {, o" n, y) o# t F: j# b/ D
if (props.autoPlay) {
) l6 l/ s: K- q startCount()
; v5 ], I* }7 H) q' y$ @+ ? }
! t0 J. h4 ?2 b7 E})1 w6 I8 a- G6 i* `# e B2 T7 j
// dom挂在完成后执行一些操作7 ?, O# u2 Q+ b* b
onMounted(() => {
; A" K; z i8 m/ T5 h- H" d8 h if (props.autoPlay) {
5 K W; d9 |' A. z; r startCount()
8 O" z4 J9 G3 y( p/ e }0 A6 m& S/ F. V" X3 ^. n/ ~( Y- I2 S
emits('onMountedcallback')4 p% |' g9 I; x" }! Z
})
! e5 d" n6 t" q1 R' l// 暂停计数
f; q) y# r4 _3 q+ [ a# [const pause = () => {; r1 O- B$ Y/ o6 s$ S. C' A' S3 y' {
cancelAnimationFrame(state.rAF): `9 } z5 ?, X* T
}
: Y( U! x9 f6 ~7 f9 {8 \// 恢复计数
# O5 ~8 p) v# z4 W# nconst resume = () => {
" t C9 O6 x" Y, A, n8 N state.startTime = null
7 Y! k! P# @* a6 _+ R state.localDuration = +state.remaining. d/ g* k8 ^/ |$ M$ ]2 X
state.localStart = +state.printVal# ~1 v q+ O% Q# S
requestAnimationFrame(count)
# l9 [0 ?0 Q. R `}4 J- E( D0 h7 t, l
* s3 }" [+ g; hconst pauseResume = () => {: G' D! X; `7 Z, Z `+ j: S' T
if (state.paused) {
5 c8 A& V# z5 r$ B8 \. ] resume() Y" D4 L; A5 a- o! `
state.paused = false
X, f' F+ ?$ O$ ^8 w( ^& w, H" n } else {
3 p% T8 U0 X( q pause()
( l7 k% y0 f- @# q7 l6 T state.paused = true
6 ~0 M: S5 Z. l6 E: v }
, ~/ d: J6 b. m6 S, d& w6 j}
" [# C" G6 o+ ~3 C" g) D7 o+ o' K; }" Y
const reset = () => {) c I# `$ h) r: C a& X
state.startTime = null* `: c/ ]0 j( Q5 H9 N
cancelAnimationFrame(state.rAF)
) d W3 J4 x: B3 m state.displayValue = formatNumber(props.start)
. w, h& K) B8 E}
2 e4 D" A3 N# o, F9 c: b3 J) y1 j5 c
const count = (timestamp) => {8 E9 K1 x+ p% Z* z
if (!state.startTime) state.startTime = timestamp& T t5 A+ G4 y. ^/ g
state.timestamp = timestamp
5 @, v& M5 o5 @# \# I' y, C6 j; g const progress = timestamp - state.startTime
, [- ]% |, w" \: v8 O( J state.remaining = state.localDuration - progress
8 J: {* p4 Q' J2 ]2 d // 是否使用速度变化曲线
0 q4 Y0 r9 I7 g( a0 z* w* G if (props.useEasing) {
/ W* z6 c- `2 g9 T" c% R; X& K if (stopCount.value) {
M) J8 W' ~8 A. p% j state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
# P. |4 s0 {0 W! A } else {# }; F) ]6 L6 {$ @
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)9 t2 T* R' L( C( k$ Z4 g
}
( _: G2 W9 o, J } else {( v7 ]2 N7 g9 X, O: y/ a6 q
if (stopCount.value) {
# j, r1 t& C' f# g' v& Z state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration)): K5 R) K. d/ Y) c& H* e. t
} else {
) Z) R) o: e$ `, @* y1 Q/ W! c state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)9 d, e; U# X6 E( j8 c& a0 V
}- v$ j9 i# _( Q6 B, \
}
0 w8 D4 w) z' ^; y if (stopCount.value) {) X' X l0 t" v" m6 V+ O. |
state.printVal = state.printVal < props.end ? props.end : state.printVal" \( R2 }8 m! k, ]+ C
} else {
& U0 q' C6 q. p# v state.printVal = state.printVal > props.end ? props.end : state.printVal
* R1 W6 G3 q& F9 H9 R }( ]9 I7 S3 W* {7 [
# |3 v# H& N; Z; o2 @$ B
state.displayValue = formatNumber(state.printVal)! o: i" E0 v9 U/ T+ h) J
if (progress < state.localDuration) {" Y5 L7 Y. n$ R% J
state.rAF = requestAnimationFrame(count)
8 P( W, B& r" P9 D& v } else {
9 P6 G6 d; t8 A4 k emits('callback')
* D' }1 T# V( B0 @. R, K3 [ A }
+ d$ j' L# [" W$ ?8 ^}7 t" S) j @6 {/ J. ?. q
// 组件销毁时取消动画: O5 e: ]2 R, n
onUnmounted(() => {
. W' y; z6 E: C cancelAnimationFrame(state.rAF)
9 E( i- E7 `) }8 H0 n4 u})
5 r" F6 }" W+ U1 S</script>, B7 r! [0 s( ^! P6 r; s; R
! G/ w/ N+ f/ J3 M5 D4 E% A% K) w( b1/ o% B# N; \7 D, O
2
* Y3 t' h* g9 J/ I( T4 b0 G) ^3 x7 Y& D; o& `, J5 Q
4
. Z- }$ v5 y5 C/ `0 _ S5
; N( i* A% f- M6, U" n3 n6 y& l* `
7' t7 U6 z3 g* ~' ?8 }, t6 M9 y
86 x; Z- m* Y$ |6 Y! t# _# Z# k7 k
9" e7 n% H. V6 s% ]7 X/ G9 u# }
10
, X' L n/ E6 S9 @9 ~5 n" j115 g9 o" h9 } J) ?5 F
12
7 q) y, S/ a% {# v) ^" P, a1 L13: b' M9 ~: F0 A
140 G4 [5 A. H% K( i4 d# {' t9 w1 O
15
& n! n% E+ J8 @3 v% H6 q2 U16% R' d4 K, X+ j! o# S8 a# }4 `
17
! c9 D) V- q" x* f, z18
: y, C/ g$ }+ w' C$ S2 w* y, C19
6 c" s( O& V! o7 d! O- K20
/ U: n# a" z- z$ O5 V21
5 G2 D) K0 C$ n2 |4 o22
+ o% c! T1 T$ f7 t$ t23
% i6 D5 q, T0 g: `4 L24
/ J$ V7 \) @+ \25
; F( {/ L* y5 e# l: c& }# f26# z- f8 C. Z, I; k" t- N' R& k
276 O g; Y& e5 q* x! F0 l) D
28, P# D8 |2 b9 S$ \: T! @* `
29- x' }* t* Q6 q3 r; s2 t7 d
30' l! H9 B- S m' K3 {* g
31
2 w5 [: U& i2 {! ^. F1 X. q- }321 N* P& t4 A/ r* c6 M
33
0 P) f* a, {, W% ]34' M* F+ h4 \ h! N! _3 g9 D
354 v3 x0 w! N, D4 i) l9 `- k) m
36) B, V, |* E% d T* i
37
% I& C+ @+ ]8 C: |* H7 h0 y9 @38% \2 c" K4 q) J
39
# N V# S5 I, h9 o% ~" d5 \1 J, ]1 ~40' ~8 L7 q% H0 \( X0 s! `3 Y" g5 O
412 q8 S. s+ H7 B. a0 \
42' `; Z+ S/ ?) d) ?7 S; W2 e& r
437 F8 w9 Z7 d+ W' k' K
44
N/ m7 {4 m8 {: O7 u45
( c' f1 M. m; R46) I* t% z3 G3 i; F/ ^
47: A6 R8 h# g$ [* p0 `
483 \# F: f# I- C) r9 V; y% D
498 X& O8 S% v7 q' f2 ~/ H+ A2 W; R
509 e$ \+ I, [- O% i2 H
51
8 G. N( J% S. X" @. C2 X( @52
# C9 K1 e# z% n533 K7 ^6 c6 [9 N& h, L3 Z/ _
541 g* B2 e, i. ~ ]* H
55) t/ |/ m# W9 h9 C1 W
56
, `0 v$ i& ~/ {. v* V" I0 {57' g' x+ U) Y- P1 o+ \
58
; I S, y* _" g2 i: Q+ \59
( h* u5 Z m+ ]& |! N60; m6 a2 T* ^0 g8 h- @ V* o
61
: B7 V. N* t2 J6 \% L5 K- _' j627 v3 g$ j7 m6 `: j- Y- Y6 i& ?+ S
63
$ h. V: H4 x) P( `64
# @+ r1 v ^$ c# c! [' o! K' D/ b1 T653 D; Q, b! E) Q' g4 j$ ]% a
66$ M0 i+ V& m) M% \" w3 i
67
2 d+ Y& Y' k; O" h' ]68
0 ]( v1 n" F- @0 I9 B5 y69 s9 m) \# {) k; Z- _1 b* e
70
5 P$ a, v. s2 F: a0 s716 ~( p) b- a" f0 ` W" w
72; J( j8 X9 J% @8 P; n
73
% P8 C% j6 G# z8 Z8 B O. E0 {8 v: o745 S3 j) u S& z
75
2 o6 B' u$ p/ _* ]* ~) ^ d76
3 J6 s4 s( V( \& y' r7 @! _77, Z2 a% l @8 v
784 w# N/ d! m2 H
794 I% l, L+ F- ~0 d' J0 M* U; h
80/ R2 g6 ^. ?$ P$ a, [8 Q3 [
81
" B6 z$ m: U) N82& y& ~ o& Q3 ~6 B4 N
83$ X6 P# l. c6 s" I
84
; s, z/ f! ?+ t* ~4 G/ W: L( t6 j857 z2 u& n' \7 X* Z8 [; q
86
- J1 X2 T9 |. ?, N' F ?877 y3 A! `' i9 @
88
1 h% C. y+ `& H9 w0 m: E89; _* G0 `. \/ ^5 A
90& i4 w& I. S8 p: l C# H
91" g' d2 _# A2 ?! Z, Z/ _$ m9 e4 a
92
: ~: D, |/ ^2 O. ^' Z. p93
% r P1 Q4 |7 v+ Z: r/ @) T94
1 Z T8 Z6 h* n9 C# i3 ?95
2 |) H: f# }, g |5 g96
$ |* k+ x1 Y! G- f+ c5 A# i97, z) s5 ?7 i4 x. i/ L
98
2 s0 H n. _3 J" C99
8 `: {4 ^( N9 e& @4 M" b" C* }6 |( b100* S. o& e: l" X, h2 X( E3 S
101" t2 K! _# g( t$ [/ D& c7 T
102
+ t9 X# ]5 D1 z% R1031 x& H$ I* m, u' Y, f0 o
104. F* t% x* \! C. K$ G. f" n% Z
1051 P8 Z. B& g1 l- C
106
! g9 J7 x3 Y M" {; \- R0 V9 N7 o107
% T% s! O1 B) A. y3 p. P108% [5 ?9 ` D% C( |( B6 y; L
109& z* J6 T: r3 e* N
110
7 {: ?9 m5 z, o5 v. g111
, N" R) M+ r( R4 z8 i112
4 r; j6 V. a" c8 X113, Y) T: n4 p6 c4 B3 I
114
: W; V5 d; Y _& Q% Z, h. z1153 _: m2 r5 F0 G' [4 Z9 w+ K/ y
116* k8 T! [$ J8 O% z
117
* Y6 F- p6 o. o/ ?( [5 n118
2 E* T) d# m V1 m& h119& `7 G# ` c! y5 a
120
( M; m8 X3 k4 [* a) \121) k% b8 I5 T2 r: Z9 ~9 A, h
122
, f6 A, f1 r1 }123! w* j/ _, S1 X. N
124, |" c" h, U0 b7 W5 R: W
125. v7 h0 F7 ?5 i" f" Z* _- P# B, v
126
* `$ w. d( X2 R0 i! L+ b% D127
4 i* c# W F( F; K2 r1 d5 D* g/ z/ [128; l* ~) J. D- E! Q" Q
1296 X' Z9 j4 N5 z# @7 M/ W( k
130- i e3 b! t2 U- V# x& o5 T
131
: Y" f# F+ n6 B. t( Y( Z/ a6 h# ]132. R; h4 W \) G% k, x
133, D8 |6 j$ ?2 J, h
134
% D& l: T, @; W% J& `$ v1 R135! E' u3 `- H \! L
136
& u$ f6 m& l3 b' Q1 t, L137: E4 u9 X O5 ]9 o
138
' e* B6 f% @: n D( i( o139
. P: a b1 q0 r0 w6 z8 n7 y140
2 H% O R0 p5 r7 x0 C, H141, ?, m9 i7 M+ n( T
142& k9 i$ d' W6 A3 g/ a6 B9 c+ X: |
143
2 ~7 l; e! j2 j K2 G$ J1440 v: V- e) m4 J: U, @' `. X4 H
145+ m, U, ~. X3 R0 {3 T; C9 v* Z
146
% U. d* E7 n) o) N8 P/ P147. f% s3 x* Q+ x$ b4 Q
148
1 c& u( N! Y. Y8 o% B& i* _149/ K3 N6 I; P1 K e5 _" e
150
) O* i0 Z' S; u151* `4 \' _$ r! O+ |6 w
152
5 v! R5 G, t* d" [153
8 J) m. b3 l! k, P154
3 x# [3 Q1 O9 f- S: s4 l155
1 T* D! q/ e1 z* d: p; Q s156
9 x3 e7 Z# `/ z* q157
" F# E% i% _3 P7 y0 J$ _158) f4 T n, D! ]8 |, ~. P+ B" q
159
4 L) H& k, u7 U/ ~! [160
, w; U6 g( n+ V2 T. U+ f. p( }161' }! v" Y3 q! S" |' m' Z- @: A
1624 p) P1 X: X5 n1 P
163) X$ C0 S$ x0 }+ p
164
6 Z: z" U- U# ]: N& ^165
+ Y6 A& b2 L% @166, J3 y3 I" t1 d, ?5 m5 @, p
167: \" s% f( f2 t$ S0 a, X
168
3 x! F# g5 j8 T169
4 A/ P M& {9 ]# m6 A8 r170
" b Q# y \" K9 Q4 p( R0 o171
, Q1 P2 J4 `7 o3 a: }) o* g172% j3 a' X0 d; O( q% p1 C: d1 D
173: D' Z7 q- X$ ]' t
174
$ n! |. t7 ?$ i$ j$ m Z1 N175) \# D" w' P E
176
7 X& B3 H* s& k/ P# V1 C177
3 N: y( [: p3 I% e178, n& O$ h0 \1 `3 N E
179
% g+ f) T) x, p+ a9 |% H180
* q: O) f* Y/ Z& l2 R: A! T181) Y! V. T4 u+ G. {6 C, h% ?
1823 b4 G' ?1 Y2 M& A
183/ y, m# ~. \) U( ^7 H
184% O0 H, |- {$ M( W
1858 V' b: \0 j. Z* E" n+ \
186
2 h0 a# Q2 s! p4 X2 p6 L187
8 V) j5 ]" q& J. N: [! f: X4 r188% [9 h; ]5 y! V0 _/ R: L
189
0 j! m! B# ?" ]; C9 o( o190. }4 A9 _/ o& p: z7 C% l
191
1 z" V0 f& Z/ e1928 K$ R( g, s/ E3 B
1930 f' [* d" c: B
194! [% m: w5 {) b; i% M" S) Q
195% p+ c0 ?4 W" H- p# F+ j
196
1 Y/ W. _% e! f/ l197
( H; |( W3 Y1 P. x9 E6 P198! C7 V7 T# [. |( N) K; b6 J( S
199
4 ] d# h- `& j/ r1 ]2 O2004 Y" U. Z) m; O4 |1 E
201
& o J* h1 s/ W" j G. q4 M+ A202, ^3 I( |7 L7 u( f: c
总结
4 u0 P& M! h1 h- y自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
7 i! _. R' V8 b' V
8 m' g7 G+ G5 B- qdemo演示
) u1 u+ M* M5 x+ N8 z; L后续的线上demo演示会放在" I, u! `4 {3 N- x/ L* B7 c: I& F% Q
demo演示
( S7 m% V- u6 h* K- u. I完整代码会放在
- v' I q+ V5 O4 S: F个人主页
# s4 q/ [# o8 p9 ?( O- K
, m; }3 L4 q I `6 r% o. v希望对vue开发者有所帮助~0 T0 f3 d9 ?$ ?1 L, A1 W1 Y- x: ]& E
/ L% f+ A5 w! l+ z) v8 I% B
个人简介:承吾$ C/ D: k1 A6 E
工作年限:5年前端
0 r v7 E+ {* |, [地区:上海: Q( k" _4 v4 K4 i+ R' ]
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!, T& {$ a- N7 j% O/ {- |' f* v, L6 c
6 w' V, @1 M/ }2 S7 L6 h
- q/ N: f- C, _0 C) k1 n
# u4 G( [6 d8 s, i6 M
7 z* _) {; `% I. ^/ x4 `% h————————————————4 u, }% e6 t4 i0 v" n
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。5 g0 d0 j4 E% O
原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
$ G; p# w4 b# `. w4 ^9 g/ @9 D- E& z% n d
) ]* L7 {0 q' w, I6 y& k1 a9 I
|
zan
|