- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 554645 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 171766
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效# x% j& ]3 ]* j. F6 V
4 ]* F+ F U' N
前言' @3 \8 M5 p9 |$ _. Y: d
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:. u+ p' ^/ d+ J e1 B, x5 Z
TypeError: Cannot read properties of undefined (reading '_c')2 v; I( c, H, H6 r- D9 ~- V: v' |
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:
# U! x! M8 b2 h; P* c3 h$ \0 A3 }. E" b, ]1 l3 @+ j: b
9 a3 |% Z Z9 N1 d5 s! p思路
: _+ H2 ^; j' ^. R+ Q$ O% C: I使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
" e: P* Q& d0 z3 |7 o4 O+ Q( r4 S( G7 b; Q6 N
文件目录
2 _, Q | i# y$ h
' o/ b) z# p K' x- P L$ d( K9 X2 q G
使用示例
, W# l8 `) E2 H, x- f6 g4 |<CountTo
( v# K1 y9 O2 E6 k: [5 w: s :start="0" // 从数字多少开始
k% g+ D/ L/ G u8 L4 n :end="endCount" // 到数字多少结束( [3 J. N. K6 O" e; {% w" e
:autoPlay="true" // 自动播放
7 k( z2 m* ?* j3 _2 w :duration="3000" // 过渡时间7 x3 U. r" U. c+ V. O, W
prefix="¥" // 前缀符号& `& a$ c L* ~9 a, o4 ]$ Q
suffix="rmb" // 后缀符号! h# J+ k! i) X& q8 d' m
/>1 I8 B/ {+ P3 T7 m, P
1
( [9 `: x+ v9 R; y; P3 @7 m2
& h* m' {/ q$ ~) N3 d# k35 [5 c) h2 Z5 w8 \
44 B5 O+ l4 a7 ~
5
. z: ?% [/ s' b& D8 B6! J8 X7 D$ N' S+ k/ H, h$ a% }
7
# @. x8 g; C8 t5 M. y84 P+ U7 r9 q% J( P+ k1 x0 `
入口文件index.js
0 E/ x* _* Z7 Y) B* z5 ]! e7 v! ^7 `2 j7 z7 V) {
const UILib = {
- g0 f9 S' u: N' D! B+ } install(Vue) {% m) j* e0 G$ s1 ]6 p- A! j
Vue.component('CountTo', CountTo)
, I3 V, V# o; g3 `1 A+ k t }
+ U" i7 b# |/ F/ [" S7 ?+ L}4 o: d% T8 k% ?1 Y* o( i
9 a4 @: D2 R/ W* x3 G) A1 s0 y; Y' \export default UILib. W5 Y: l/ O3 ~, o t( m7 P
9 l# V$ o( h1 T& f
1
; k/ z9 n, @1 j- u( d2
1 W9 h4 m& R, ^7 J1 R# ?3
7 s2 c3 u! Y) U7 Y- A4 X9 y45 W- q, E% I% C( W& Q
5+ C) V+ M; Y# z' f7 M$ J) c
6
& q3 T( V4 q; b, Q8 }7 \/ g7# l: H! ~6 E$ m1 B
85 t0 ~" Q5 ~: \0 ~9 s2 n; {
9% @- V$ Y8 h" I/ Y) E5 k
main.js使用' ?& S! o3 I) E% h. e
import CountTo from './components/count-to/index';( a7 `1 a. Y ?' s F" l
app.use(CountTo)0 n2 N; n' [# A7 g) E4 e6 l% D
10 Q _# b) t9 e* U, m
2
& O3 }: k* _. e; WrequestAnimationFrame.js思路
9 ^- g" H' p k, y2 Y8 o先判断是不是浏览器还是其他环境
, G2 {9 ?8 z$ ]5 ^如果是浏览器判断浏览器内核类型) `" I' Q* ]( C8 e/ w+ q6 A
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器6 d, H3 Y) s8 u7 l9 N
导出两个方法 requestAnimationFrame, cancelAnimationFrame
1 ]. Z! X, K; ~& k: X3 V) Y各个浏览器前缀:let prefixes = 'webkit moz ms o';" ^$ T- @" w6 g! X! y1 ?
判断是不是浏览器:let isServe = typeof window == 'undefined';
7 _0 P3 o7 w+ M2 {) d: s9 q增加各个浏览器前缀:
% [7 A0 G" K* C+ X! X7 Ilet prefix;! r5 M1 Y) b) d; h6 h4 |1 R
let requestAnimationFrame;+ C$ l9 `" d: @6 B% h6 B) D4 q- e0 g
let cancelAnimationFrame;+ s% A& V% p+ ~! E; `
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
' }+ j s, i& ^& D0 u" g' W. R for (let i = 0; i < prefixes.length; i++) {/ y' |1 r# p# D
if (requestAnimationFrame && cancelAnimationFrame) { break }
. P& h- d i3 O/ D) U* ^: f prefix = prefixes
9 m2 \9 a) F0 R+ o requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']* u+ b6 Z* ?! t) _* S
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']. @& C: F* u3 D; h7 c
}
; X% S& P/ u$ k [$ y" T7 A g7 x: b
//不支持使用setTimeout方式替换:模拟60帧的效果5 |4 r: A5 S$ `
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout2 Q" U! d% h+ x% }" `4 P. O' f
if (!requestAnimationFrame || !cancelAnimationFrame) {
2 |/ O/ W6 |) S- ~: V- e+ o/ A requestAnimationFrame = function (callback) {, T2 C1 Z7 i u5 x6 D/ h5 \3 I% ?$ p
const currTime = new Date().getTime()
* M' b, ]( N$ P3 I // 为了使setTimteout的尽可能的接近每秒60帧的效果
2 W. W) u z$ m( r h1 K9 @" `. Z const timeToCall = Math.max(0, 16 - (currTime - lastTime))( L- E4 {- Y4 S5 z4 e5 [2 n
const id = window.setTimeout(() => {
& l4 K5 \ J- e4 | D2 b) y" C8 \9 s1 c callback(currTime + timeToCall)0 T3 W4 m/ c c! C% e$ v+ f2 g
}, timeToCall)
7 P8 ]- I$ b3 u lastTime = currTime + timeToCall
: `- B+ ?4 k4 Q. W return id a9 u z+ `* U- ?
}
3 O8 Y' M" f. M' \' N+ @8 V
7 y. }& R' O) g5 B cancelAnimationFrame = function (id) {
0 \3 Z# R5 j" ]3 c1 R$ I) w window.clearTimeout(id)
+ T( y7 h: c8 \9 p3 T3 \ }
; G3 }4 v, l* c- a* R }) S. v: w: y4 i0 ^" b8 x
, C( L# E/ ?, S16 K4 d/ @# c2 e- q
20 \8 E5 ?8 c6 N
3. z2 n! ?& w( o
4- [* D7 k5 f; Q
5; x5 f: a# r7 v6 D2 a
6) `, U- p0 K0 x3 M% d: A- t% x
7, Q) [' }3 U' O+ |7 D
8* f3 U1 o5 V/ |2 E2 a7 V; u$ s2 ?
9
+ y1 z7 O& S4 j4 E" p10% \5 {3 L' T$ _0 n$ M1 t6 F
11- p& u$ m$ U( e# T# ^
121 ?) d! N# i, d& F: Y
13 H; K% X* z/ L0 n( g
14
5 u' ^; g2 f; c/ C) r$ e, K15
X9 M& r8 p- [/ a; Z, i16
, ?* b$ l! @1 e% @* {8 j6 B171 j0 u: }: h- B7 {; B
18( O9 T- A3 H* v" m$ p
19* B/ U1 g: | |$ D6 Q2 `+ h9 x1 u
20
7 ]' w" Z" s9 d4 ^. h. G210 z6 ~! n4 `$ h# k
22 z8 [2 B- K5 }/ D. w$ V$ @; C% \ F
23
/ z) ]3 k. P9 _. S' d$ ^' \24) y$ c* b+ Z% z1 K
25% h, r: L: K" L3 |- J4 C U
26
! F# w8 n: t+ A3 l2 M* M27& a6 q r: R p8 k8 X6 u
28. O0 Y- L: ^9 V
29
/ x, X! S% v- n30
5 O% A- ]1 h2 \8 F+ K( ~31
- J* \5 \3 j6 p0 M8 w32
3 D0 j7 ^6 X: \2 R1 H4 l: Q, L& y完整代码:
# C# [- s o) I# Q) q3 FrequestAnimationFrame.js
2 ]6 Q$ C7 j' ^% M
6 a! t( U1 n0 R0 f2 Rlet lastTime = 0 z. l) l7 F3 y/ E" @( k. Y
const prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀( S0 a0 W* I: l4 ^3 h
5 v2 i3 Y3 h2 i ^0 C: y$ o& ?
let requestAnimationFrame
: A/ U+ w$ l" ]) Y- l( Mlet cancelAnimationFrame
6 m( O j6 a4 d8 R0 o$ f) z& h3 r; t
// 判断是否是服务器环境! ?) f8 u7 l4 ` i8 ~3 q
const isServer = typeof window === 'undefined'6 J2 `1 \! g/ W! q2 }2 m0 r( ^
if (isServer) {
% Z, J7 f6 E5 V/ G' C- N requestAnimationFrame = function () {4 v! e% [2 d! V. f
return
" I. }, _$ l8 W- m: v }! x8 I% ]4 U5 O2 \/ ]$ e$ ~' m% V* M
cancelAnimationFrame = function () { |# L; h8 W: F& `$ r
return
- _/ _2 R! k U) s/ x/ r* k1 ~1 C5 [ }
, }6 E$ @! o5 _} else {
% I6 z8 t$ H0 W6 W requestAnimationFrame = window.requestAnimationFrame
o8 V8 n: m3 Q4 \ cancelAnimationFrame = window.cancelAnimationFrame8 C+ Q& ?: z. o) M$ \6 t4 z6 h- _4 T
let prefix6 X& s7 R8 O2 _. x. }+ p, `8 F" z
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
2 g) H c6 \) t8 c7 J, { for (let i = 0; i < prefixes.length; i++) {
" W. Q( f1 E: w+ m if (requestAnimationFrame && cancelAnimationFrame) { break }
+ E' H1 ?3 S0 Z$ Y prefix = prefixes. H8 a4 k" o/ O
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
7 w- b6 o) u6 Y5 B! u0 y cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']+ s) U" M6 n0 L! y' G1 n2 J/ E
}' P- e2 l# K: C) E1 [
/ H7 u+ Q% Q0 s+ x9 e; k9 m
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
D$ {. F4 i4 S/ P if (!requestAnimationFrame || !cancelAnimationFrame) {% I3 R" Z1 L- y6 H- \
requestAnimationFrame = function (callback) {
$ m1 b+ T- N* R' Y# R const currTime = new Date().getTime()5 c9 k3 @6 E: i! W" G
// 为了使setTimteout的尽可能的接近每秒60帧的效果; K! m7 s4 n. L, m5 X
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
) J. ?! K9 }. C const id = window.setTimeout(() => {
! t$ t& M! T8 H9 }$ t callback(currTime + timeToCall)' b ?- N' ?. R. R
}, timeToCall)3 D2 N: G2 D9 R' O9 _8 e/ R3 ~% F
lastTime = currTime + timeToCall/ @) `" \5 l8 e b
return id
8 l0 q: e) W5 ~" \ }3 n+ v: f \* P3 A" L
% H! i0 }- T1 N7 z3 P
cancelAnimationFrame = function (id) {5 w9 f8 t. j0 X8 |
window.clearTimeout(id)
* d5 B i1 @; B/ q. K }
7 C' L: Y$ Z: D9 c4 { }
+ Z$ p% B' y# h8 E}/ T# |6 _- h+ o: s
' s. V! E: Q# L" s% lexport { requestAnimationFrame, cancelAnimationFrame }
+ N/ U" V, Q$ i$ t. O! c% k% H- G! @+ y
/ o1 L) K: _; P, u1 R7 j
14 d3 m+ h4 E/ K( A X0 L1 m) z8 S
2! m, T$ @* \5 E5 @" w& X; ]0 \. A
3
1 ]" ]; [8 i6 q5 A. q4/ E8 u7 y' s1 Q! u# `2 ~
5
8 T! z* @+ ~9 |/ j3 S6, w/ u" b+ Y7 {- ^/ H* s
7
, F& q. g* C6 i- x' O! K/ {85 @: d3 @ S2 r, d" i1 W( J
9
- E0 S1 b# ]. C/ G$ y* N5 ^2 ~10
, b/ \" h$ h6 l8 A* \8 s7 z$ `11/ c# f, S2 E: Y$ j* j" |6 W
12) J& S2 E! K$ z) B
13" C; B# a: n h- m, m" J$ k [
141 n& C9 W4 w2 u8 J& Y+ T/ E7 U
15; n' H% f, ^, G: w s+ {5 W
16
! O0 R3 z2 ]+ D0 ]" u3 T17
+ y5 t5 c- A3 a* d/ V18
0 _4 R3 ?7 L, \& b8 Q% _19, T, w4 M' c( `! r- B/ Y
20 ~% W* X: t1 k. L/ T$ l
21
7 ^- s( X% v3 q22
# e; `, Z) N- K23' E5 Z6 }& `" f( d3 ~& m) c
24
, n& g4 u6 k& F8 ^25
. ~" z2 d# J+ k. ?) [) P4 A! G267 R! X. \9 H3 v
27
. A2 H6 s1 B5 [' b7 `* r1 r: t" K28
: s+ k: p( g, O/ D, g% p) U$ {29/ U* V& _8 e4 K# O5 n. e- E7 F
30
7 v: I- W# H1 `% @2 k& I8 i% g31* n3 R0 J8 m: X0 K! E
32% R M7 Q6 I" H7 `
33( O2 B; J$ o+ E6 L# n$ j8 [
343 G+ M4 y! j5 ^, x
35
( `! p4 j N' i, N; ~4 ]36
% D+ G l' P$ X6 @4 p37
' ?6 b- p% i6 _% Q+ ^7 M" s38
7 [" N! R$ {! R. ^* i! b+ v: O39
6 H$ l4 O8 H l# `" W% N406 V" K0 I7 T8 g' T
41
2 K: ?" y0 A! { r' b' N+ a) W42
( V4 t' }# n7 Q1 a0 B3 Z43
$ Y) S( f5 d: P) A8 A44# c# M1 X# `. A! S
45, t+ h6 L5 w. O( L+ d, E- ]
46' g" w+ D' J, Q3 B0 V1 w
47& r) S4 V8 r6 _4 x M C
48
9 D$ |: N0 p/ {7 x( ?& gCountTo.vue组件思路! w0 d( \5 v$ a6 v |$ w1 I
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。: F% H. E- ~3 g7 C; ^
0 ~( a2 ^4 a! H1 f/ X- s2 E
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
% M3 R6 c0 E: `0 W+ A) r1) O: @# n' E- t8 ^
需要接受的参数:. ]& F# I: B h! U$ h
) E6 |' a8 W0 j4 g/ S7 y( s
const props = defineProps({
4 j- @: h L7 Z, I+ r start: {# j, x# |: v. Q+ C; }) h
type: Number,5 C$ B u! k* S- C& S
required: false,
d: p9 U! B8 y7 r5 t default: 0
5 E) w4 \; a) }. l },
& \( g K) Z: a; z0 l end: {& a4 w8 W1 ^* M9 L; c
type: Number,. B( `4 O) V6 ~1 q
required: false,8 }4 @ N* S5 E/ a* H c
default: 0* C- w2 z$ Q5 h. ^6 \ ]+ H1 s; D
},
' ^& F, `! x, B$ A0 \* v duration: {
4 E7 y) M0 r B) J1 ~ type: Number,& i' m6 ]: j- E/ \( z/ s3 p
required: false,; a4 r- M) @4 d9 ^
default: 50004 f) W! h) j. q- f9 y
},) w2 G0 n& B0 E- p# d0 t
autoPlay: {
D7 v6 {- F( x% u+ N) H% J; p type: Boolean,
' z& s- c; O, Y6 G8 W required: false,8 l5 ]8 } s3 S- I' }1 ?2 G4 I: }
default: true
$ } j# d+ p; H# z) h2 t+ a; T, Y' J },
' b9 b" F, P& j L8 E8 t decimals: {
; T7 o& ]; [/ G type: Number,8 a) H% v. d7 T, p( W, ]
required: false,' f. n; N/ O( K- m5 |) C
default: 0,( G: Z3 ]5 X' K
validator (value) {
( S) n; ~2 S9 P4 S+ |% ? return value >= 0/ s0 _# Q+ R1 u8 W2 Z) V4 q
}% ?; Q$ m/ i8 ~! X0 @% i
},& _; \5 }/ E" o1 V- {$ _
decimal: {6 b# i) s# [0 @2 [! T6 ?8 N; i
type: String,
* H2 J9 r; L5 L$ _' z1 \4 c0 N required: false,' h3 {% l3 l0 K& ]! P, ^( d7 X2 E. ~
default: '.'" Y3 \3 j; M$ e$ M4 w7 Y5 P9 C: K
},6 O2 @1 y5 J) d% l7 f
separator: {
! N0 `. Q8 T J( U' T* G type: String,
/ X5 ?: v: g7 @6 P, z7 E# y required: false,
, d6 {6 \6 b! ]- J6 c+ n default: ','
8 m4 I. U( ^1 x% h9 U4 g6 m( E: o( C0 g },$ {1 } C- T8 _$ d
prefix: { j" O) n/ v- x
type: String,
; Z7 Y: C( s K I% b( |! J5 D required: false,
+ ?1 b$ T# b, N) Z/ D M default: ''
& z! G: I, O) C, S, [0 V },% ^& k, w9 {1 N/ g! n0 z
suffix: {+ r x. O# W7 @( D8 c6 e% s# c
type: String,
6 i6 M9 H- N3 K+ Y required: false,/ [% g" n: e5 @8 k* C
default: ''% ^( x# n: x( d1 j0 t. B
},6 d. Z! S% x8 } X# S4 U
useEasing: {. O. L4 E- Q+ r+ K7 T4 b
type: Boolean,5 h* L' ^" y' m+ N9 J, N+ j0 p
required: false,
0 H2 `- P* P6 ? default: true6 ^) z/ K1 r1 s/ ?/ P% p
},4 ]- w: t3 B8 o4 X+ u: a& p
easingFn: {' i( h& h3 o3 j! c* |0 {; b4 s- `
type: Function,7 P% K6 J/ @) o5 v* c
default(t, b, c, d) {
5 r+ V0 O; H" h' N( c# X* l return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
! y; ?/ |1 {5 f8 s ? }
" [# q9 k2 I0 s7 ^ }
/ b8 S0 Q/ F1 k& U, x})
% K. s3 z# K* y" Y# Q9 V @- \% l
5 x% L8 W! p& e! O0 Q0 }8 O2 i! \- T! M T
1
/ j/ ~& Q. o9 C0 o5 s2
# `/ t- {$ l( w, N9 B) G- U3
H0 p9 @+ \( `' f1 j42 s2 L% o% \: X, E9 c
5
$ q& Z1 u/ ]% d% F- @- x+ [6+ e) b6 P L0 B- h/ \1 s& F- |
7
: ^) m. E4 N% o86 b" n$ C- P! E1 p5 w3 B4 Z8 F
9
) w) ?0 U) d5 ^/ q4 u. D10
7 G( X4 ^7 q3 B8 d11
8 f' d$ b0 x9 K, d, g$ N9 e; f12, v# V, N {* i: V% s. r
13
9 M! B1 j( d/ Y- i6 i7 a; c14
# ^9 z6 ^; W6 p7 c, h: q% M- ?4 y# F15) B% A; q* B/ r1 R8 w7 T; r, L, p; c
16
) L: I. S% B$ S* s# _2 t17
" [# F% e2 Q ~4 ?18
6 n* K% k- X. T1 d) P% D6 ^19* V7 ~2 W& B0 J3 |
20: j, K3 P. ^) r
21. g) z! m" a, K# D3 C
22
$ H) {6 D! p* P5 ^ G; w, {23
0 s+ D; \. I8 d. D9 j+ y! ~24( d; m6 F- y, C7 O1 L
25
, |( E1 G& W, E+ I26
1 d0 u0 f: A/ e; |" K9 ~$ G0 V2 S27
4 D8 N% Y2 \+ a4 u( I28# T! B" b3 k) J! P5 a( m
29' p( A6 ?: L& e% N: C
30" }9 ]: i ^, b
317 H" M. ^& I: z( B: b# w8 w
32
) ~2 V" X* I5 L# m) i g33
: e6 X6 a$ ^8 i9 `" `! s34
6 n3 w! b9 n8 i/ `7 x) M! ?. G35/ C \, O- r5 W; ^# W+ y
36" q9 Q# {! y, i. ^% y i
37
- T4 I1 k" j% q! T38) s) Z( I# Q; I5 G+ H/ B: b
39
7 i& Q9 x; t# o409 Y9 {" P, S7 a+ t
411 G9 B' u; n5 N0 O+ o4 e# D
42
2 J5 k2 C+ ]# y$ _43. r# q' h7 W0 M5 k' c1 s# Y3 _
44( r L! C2 \+ [0 g. x5 K! F
45
4 s' k; O/ J6 a6 b# ]2 G, v' h46
# r6 T( O3 [$ f" V% O" e5 ~; }47
/ }2 p$ g! C* n6 _& b V48* i4 _1 e* E( B& X! y! i
49: y9 s$ |% W4 K$ \9 r5 f
50
* A' p# {7 x, V- E1 @ {/ ?4 m51
% ~$ H8 a% W5 l; ~. w52
) G6 v5 m; V% V. r( t7 ^" T) c/ m2 s53' C& X( D5 \1 w" N! `* C& f
54( o" z% K2 J1 Z
55& t% z6 S: u# C; x
56: r& `' _6 p6 E& n2 Q/ l8 {4 s Y
57, s$ P0 H5 S0 t) O0 k2 T
587 F/ E8 w1 M% P/ z. `/ U( n
59
% L3 P' W t6 [6 v0 N* h60; C" \3 r* _6 y* E5 `9 B" t2 b
61
5 |/ x2 i$ S& W# k62
t6 p6 ?2 c. Y" a8 l* Q启动数字动效
4 d0 R2 R9 ^5 J% Y5 l1 D# Z( d: M# g/ v, f K% M
const startCount = () => {. r* M$ c$ X! Q) k% W
state.localStart = props.start
+ F! Z4 h' N' G8 n state.startTime = null
* w/ E5 I# ?( \- _3 J0 O+ @3 J state.localDuration = props.duration% }* U7 F! `- o" v% ? A
state.paused = false
) K. l3 A3 i. p( e6 A/ z7 l! W state.rAF = requestAnimationFrame(count)& o) [7 c# ?( z1 c, U% e
}- q. Z, v0 t1 ?! q( D7 g6 R
10 x- t& Q1 H9 W8 w4 P
2
$ [( f! U A& s- d8 a$ g& E% ]3
# n5 H0 @ [) |5 y1 K7 P4: R8 x% G9 A3 V% X* j. i
52 B# k9 L/ {# v1 W) d( m
6
' _) Y4 B8 ~1 U( Y ]7% E+ K s! j% T9 Q
核心函数,对数字进行转动+ _2 d4 ~9 z. @! t; a% Q
0 g9 G% m, P& a! X
if (!state.startTime) state.startTime = timestamp
; y& I }8 z8 \2 s state.timestamp = timestamp
8 a$ }2 e" U- J* A6 r6 ^* R const progress = timestamp - state.startTime
4 Z$ D4 @5 S* S: Q state.remaining = state.localDuration - progress
/ N; i: @5 l7 H9 Y, `4 } // 是否使用速度变化曲线0 @+ y- b8 M0 I6 r2 t: n7 ^6 t
if (props.useEasing) {
+ H$ P- r# A# B2 U3 z+ N: K1 n if (stopCount.value) {
4 S4 k- L# f- ?2 e1 y; q8 j state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
6 P# R6 D* K. N } else {
: N7 O& {' u0 C! D+ Z; y; p4 o state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
( I1 n7 d2 W" x' e! j4 T }8 E9 w3 {- O4 R- D
} else {
7 Q+ Y' V3 m( w1 V! A) O if (stopCount.value) {
U/ Q; {2 r ]+ H( x, O* v state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))1 n& c* {! H6 j$ N/ C
} else {
: p2 w# y# b7 l2 M$ J8 o$ I2 } state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
- Z" X& f/ S1 J* k+ f' L2 ~( i }
+ g8 t3 h, h4 _" u& _ }3 _# r9 D0 { K; v! O n/ m
if (stopCount.value) {/ c! U; c) Y# H
state.printVal = state.printVal < props.end ? props.end : state.printVal) H- ~8 ~" |. g' C5 l+ D( t
} else {$ T) c- _3 Y" l8 s, _* b% U
state.printVal = state.printVal > props.end ? props.end : state.printVal9 F `0 ?* u: H% U" D
}
/ C I/ |( |" q5 N' i: U+ S: \) y2 C, R/ N- H
state.displayValue = formatNumber(state.printVal)+ P4 h: O, H0 b5 ]
if (progress < state.localDuration) {0 X, X! v' r6 p/ T
state.rAF = requestAnimationFrame(count)
% S2 _. |& _, K! j% v } else {
2 ?; F! O# v, c emits('callback')
* z/ X4 e0 Y) k6 M3 o* g/ S6 B }( V' h3 _: U1 X2 j
}
5 I7 H- W9 }! X$ A( T( ]. {' q- \) n! D/ C
, x" e5 y- j# o: x// 格式化数据,返回想要展示的数据格式
0 m% c6 ~6 x% l. |/ P- W7 |3 Hconst formatNumber = (val) => {* S3 G z( _/ t# C4 N- ^ b) q
val = val.toFixed(props.default)
/ D* K( n) h$ N: B) D1 C" N val += ''2 W! V1 G5 f' A' K5 j
const x = val.split('.')" B1 ~0 a; s9 p
let x1 = x[0]! {7 `3 A* Q* j _
const x2 = x.length > 1 ? props.decimal + x[1] : ''6 a; ]- ^2 o9 a% n/ O( z; F8 X9 p" r
const rgx = /(\d+)(\d{3})/- @7 l/ ]1 S. i
if (props.separator && !isNumber(props.separator)) {
) Z5 e+ n% s, A2 M% ^4 c! U while (rgx.test(x1)) {4 O) ~$ F- v* N8 y
x1 = x1.replace(rgx, '$1' + props.separator + '$2')" w7 E8 H9 K+ b$ m& {' n6 p+ M4 E
} A% U' ]5 Z& H9 p' n5 M6 t
}
, l2 P, e: k3 `7 g; N return props.prefix + x1 + x2 + props.suffix
6 m$ [5 F8 r; ^1 N}+ A+ L* E# _5 J$ E
( n/ J; W3 s4 ]8 g1/ {! S0 k. F0 R3 ~
2; Q' {9 ]5 T- W: ]9 O
3
# A( \6 w; z7 ]" O+ L4
9 `' v4 I2 @0 i+ y2 B1 f5
6 A( R6 C/ ?/ I1 |6# g: n" c# Z0 }; ~) M% ?+ q9 |# s
7% r$ |" \2 @9 {, L
89 c' B% ~4 _' A6 a9 A+ m1 v
99 l% H7 }& ?# Y1 y6 H5 E- S! k, H
10% x( A, a+ Q, ?2 C1 W# }' V
116 }; t4 N7 r& Q% L
12
5 S- j1 ^+ D5 I/ f13
& B+ Y4 i1 f/ K! Z8 c5 K H14
3 R) }+ N d) H) ?: a15
5 s @7 F* }4 R) Y# }; a16
$ |$ c+ }9 ?4 D2 h, [17- q. |9 u2 o) M( e
187 n9 R6 |7 ~: p7 N( e
19, e2 N4 p* w& g& B/ T
20
! l8 C8 o! D! ^21: [% c5 G4 n. A
22
" ^# u+ H- {3 \4 L% K7 A' T23 D' i' C" [ C2 f6 C
24
8 L! C7 F9 v- B& N9 d25/ _- M# g4 I- Y- u. I" a
26& L# n% x. |! m6 ^5 n5 z
27
9 Q1 K/ T( i$ ^; y2 c! K3 \28
p+ [4 L# Q0 Z& I( e) s29: N% N, B# u4 u$ S$ e3 o8 e
30
! @1 q- p q' H31
% G" i+ L, y* J0 B; l/ [8 n/ i. n326 T4 @. @& f g% v5 n
338 [& v/ C; l' O' {# T* g
34
1 \& L* {+ w# s. C9 `. s, `35 Y1 T% a2 B' k( u, R
36% G/ v: O3 g" x. N2 g
37' X( h: @1 K8 P v! n1 b6 c [' _! a
38
0 ?2 n4 U8 l9 p0 M: y/ D" {! S397 g$ t! a% B- s: z" w4 {
40
/ Y- t/ H5 J7 ^: k9 ]7 N' ?- ?41
* a" {3 a, c1 ^ Y425 r2 x6 x/ K' }4 Z' e
43( F) S& t8 _% n7 s6 g3 O( F% o
44
/ { r7 t0 I8 m; T; g4 K3 T: P45
R/ D4 @4 a+ L( ?% m+ M46
+ _4 q5 S* b( {2 u! F$ n47
* V. `7 q; b- R483 d* {1 r$ {+ x
取消动效6 q& w; {& V6 z" [2 J% ~
; }1 [8 U( \# E5 F: d7 @// 组件销毁时取消动画- b1 G0 q, g% ?6 `4 i
onUnmounted(() => {( {4 |0 w- J8 N7 w" M
cancelAnimationFrame(state.rAF)5 F' C Z! X' R; F( V
})
9 f, D0 N3 u& k( ~. o- M$ j1
" E1 ~4 t1 ] m5 S" t3 y2
# u0 p, ]3 @2 F. H- p* c0 u9 `& q3
7 w* Z9 i) _6 i' S8 Y* ?4 {47 S, o) w: e2 k; U/ w' w
完整代码* h% `& `- F/ g% h, e+ e- x" p
; F' `% ~% L6 T1 ?: O
<template>0 t K* H% m) @9 @' I' ~# u& w
{{ state.displayValue }}: B. o* W( \( P Y
</template>
, y2 [2 [: F5 k0 Y/ N: t: ~0 L: p( A3 T4 b9 A
<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
9 |7 l1 r+ R! mimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";% b5 l u7 a0 c; K+ ]
import { watch, computed } from 'vue';/ g9 R% g: E- T1 G
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js': S' g& s+ m% V8 z- d( `
// 定义父组件传递的参数$ a! Y* Q' X! n9 q2 {' x/ V
const props = defineProps({6 @3 G" s- w* X$ t+ U( A
start: {
$ {- _" q. p7 }) e: T type: Number,
A$ N0 y5 x% K' z( \! P4 v- t required: false,. J8 t$ H3 O* f" j9 ]4 ^1 a# k
default: 0
5 P+ Z1 p+ h$ c ~# H+ d },, t6 {: M8 S" p5 H4 l7 s) L( N
end: {. f, O; ?% J/ r9 M- O
type: Number,: x. O4 _: v+ E
required: false,, _6 k* j/ c8 r/ }
default: 0 ?; G1 `4 _; W$ r- Y7 U
},
, ^" x( H1 T2 S2 E( E9 D% b3 C& w duration: {
# X/ j/ i3 M9 g6 g1 g type: Number,# w; Q" M, I/ V. O) x6 a( @
required: false,
" f; w8 T6 F" d( _$ `+ F/ y default: 5000
( g" ]1 d( ^% A/ m, u1 K) v. v },
$ |( C$ J h% a/ w" r# X autoPlay: {; y! k- `" d8 T
type: Boolean,
% f1 [! G$ N( q) f required: false,- T7 t5 P/ [; T6 Q; F- F
default: true1 ~* \' o" K' ?( ~0 P1 G1 R" U9 n, ]* c
},6 K3 L" b8 I$ I T- q1 W7 g2 c
decimals: {
! M6 v1 }0 z7 e) M0 R9 ~ n) y1 P type: Number,$ a6 g+ s3 O& e: z
required: false, D3 G1 T' u( l
default: 0,
& N- R5 J+ E3 k validator (value) {1 M5 `4 P/ s/ ? }1 S. B
return value >= 0) V4 C, z/ n+ A8 B! v- w
}
+ p( T. e D- B/ f D4 n$ j* \. a },4 q( l3 ~9 m, C2 S5 ]
decimal: {
9 @1 p6 h3 Q7 }% C, Q5 E type: String, W* D b3 S/ Z% q- a; C) \
required: false,( P, a) @1 y, M3 }/ h- X4 D
default: '.') R; Y, _0 V. o: q+ w. m# n" {& v
},/ n# j+ B R) [6 L* d; M8 @: i; m7 {
separator: {
" w3 v8 ^ ]$ j; k5 F5 r, j type: String,
. v Q$ v. s9 W, {$ y/ ` required: false,( ^% k- _2 y. \& x( y- q/ L2 F
default: ','
5 i% X# l, B. @ }," L; i$ m2 Y. Z. N8 i5 p8 b
prefix: {
6 J. c. B6 G# V2 i8 N type: String,6 j+ m u( f7 f
required: false,
0 \3 _8 ?6 {# v6 c: W default: ''
& p; I: f7 ?) r$ _ },0 ?+ p2 O% V6 }5 F7 e$ u/ w
suffix: {
. N+ A! [* L- v2 e2 I* {: V type: String,% C$ G1 q5 [% p2 C
required: false,; U5 C1 I, k, I+ G) r- L* W+ ]
default: ''( h* i4 ~2 b& L0 [) d4 }( M
},: `2 s6 X+ x: x' J. C: d- W2 c) E
useEasing: {
- W" S6 A8 _- o4 d; j- _# c type: Boolean,
. C( x4 v- t) c) _0 l& q" e required: false,
; e4 ^5 `2 }4 W. c, f2 l) D$ M% l default: true
1 {& ^& N" a B7 Q$ H },
" W0 s. `' f& H5 [( y/ G, \: q9 H easingFn: {
8 _& R R; D: V5 `6 q' [! I. V type: Function,
2 ?! G$ X5 T! w7 i default(t, b, c, d) {
- f/ C% E6 `( }0 D3 _ return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;# \' K( \( r1 V3 L! }; z
}3 B/ c0 z2 o) C
}
3 D. t H' ]$ x3 d( W})' U8 V6 W8 a; E* }0 Z& `3 O
. g& d, M3 M! ?: g6 ~( [; sconst isNumber = (val) => {
1 F O, L5 _8 X' [! h% ~% `1 t" ~9 o return !isNaN(parseFloat(val))8 Y2 ]8 O* p2 K) Z# u
}( \$ V x: C5 w' z
* l$ U% }# ?- r) T0 ^( Y" c
// 格式化数据,返回想要展示的数据格式
1 Y, v5 Z* |4 l& p' {3 Bconst formatNumber = (val) => {$ M2 M9 E+ h6 l2 r. j# R
val = val.toFixed(props.default)
1 G$ \9 r U$ I) n val += ''! M: d4 N8 q& ]5 n
const x = val.split('.')
* R3 j4 c" {3 h. h let x1 = x[0]; L; y7 k9 f: r: j$ l& \% G
const x2 = x.length > 1 ? props.decimal + x[1] : ''. H' [0 O4 t/ U8 t) E7 ]4 a
const rgx = /(\d+)(\d{3})/3 b' a6 \- f/ Z h- |: u2 F# E
if (props.separator && !isNumber(props.separator)) {+ {0 h+ B: S) D: T; ] r, F
while (rgx.test(x1)) {
- q! s @* D/ Z: ]. r x1 = x1.replace(rgx, '$1' + props.separator + '$2')
7 w {/ G* C- _. r( o }5 K( B7 [3 P3 X9 R: a
}
. q, [0 ], p% w8 R return props.prefix + x1 + x2 + props.suffix
4 r* Z3 @5 R# r9 i( e2 m- w}
* Q: p8 p. e8 i a) j+ q. M* @ O3 @8 K$ Y3 h
// 相当于vue2中的data中所定义的变量部分* N, L5 M9 Y( ?4 E z$ V1 F! Q- p
const state = reactive({% n \$ g* G4 Y, v0 z1 `- D) H
localStart: props.start,
; L) L) G: i- u' x( h displayValue: formatNumber(props.start),
* x+ q+ J8 [5 D& }; d" H, K5 H printVal: null,
7 \" S2 O9 o) t' e, I1 m paused: false,' l8 \% O% k, m( e
localDuration: props.duration,
1 b9 L# a9 U9 r# v# s: f0 _, u; v startTime: null,9 u' V% i$ v+ {& ^
timestamp: null,+ o" o, R4 P+ S1 p9 v; [& d
remaining: null,9 v. o2 X# ?( P2 ~- l+ w9 F% X+ I
rAF: null8 M' J1 c, \8 c* a
})* `. @+ Y( T" Q, l' i4 o
/ @5 ]" I, s# u0 g# g
// 定义一个计算属性,当开始数字大于结束数字时返回true
8 e8 F9 D$ k4 r3 n- U' A7 t' Fconst stopCount = computed(() => {# K9 U; \' m: s# p, ]' U0 o
return props.start > props.end1 k% `( ~1 V7 V" A; e
})
& u7 T) V: g: l( B# p- t+ {// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
6 O2 ]3 {8 [) _# \& b2 N# S1 Aconst emits = defineEmits(['onMountedcallback', 'callback'])) m, C. M2 Q1 W
$ r/ L* K# I! p: _, [4 p( \8 C
const startCount = () => {
3 W) c8 U$ P* L7 G _ state.localStart = props.start9 @8 O4 l5 N! _1 I7 S" y
state.startTime = null9 X4 i( U+ t; ~# |3 M
state.localDuration = props.duration
. a( W6 _1 Z9 O state.paused = false$ ^- C, m- }* [) i
state.rAF = requestAnimationFrame(count)
+ h8 I( F) h B7 X. T- K$ v}
% W& d% o0 s9 P# `; w0 W& F* ~. f9 P9 j9 F1 q4 G4 k
watch(() => props.start, () => {
5 r$ h0 c1 t: o6 L( V if (props.autoPlay) {
, X" M- m3 w1 q9 P- p startCount()
; y7 g+ N! g. {8 N# B& t }
u* ]& `2 Q! a, _6 a}), j) u( `- S, P: u4 z$ }: I
/ R# a6 x9 G/ J3 T: i5 M) ^watch(() => props.end, () => {
. k/ u3 a# N- s, W4 g8 \ if (props.autoPlay) {
; e" {: H, A2 A; s startCount()
N! j3 Y% s4 J# u }- C u4 i! y1 v& E& B# v. i* U
})# T2 {4 C6 d7 z# W% W3 ]7 Q) J
// dom挂在完成后执行一些操作7 S- K$ u$ E+ t. i0 Z& E: \
onMounted(() => {; [. M6 A7 H1 }4 O m e
if (props.autoPlay) {' z1 _6 \8 S0 a X$ V% j- H. Y& Y1 q
startCount()
4 L0 m9 l3 z4 Z/ b+ } }
: m+ K. G/ h5 q emits('onMountedcallback')3 [- q! j4 { j1 f6 u# h
})+ n1 `% P: z9 P R' e# M
// 暂停计数
# {' C! } C) B1 M- l2 sconst pause = () => {
( |- _% S9 A* z* S+ \ cancelAnimationFrame(state.rAF)# J9 N& F; }. V* b$ @7 n7 A
}' @& ]9 e t. b. j6 J; o% u4 p( O7 O$ C
// 恢复计数, s9 ~5 @) y8 r/ t2 V
const resume = () => {: Q, O* ?7 [+ `9 l
state.startTime = null# w- K* v/ E9 U9 x; g
state.localDuration = +state.remaining6 S I- [: `0 q7 O) s- z" z" ?% B* U
state.localStart = +state.printVal) y- O* E" w$ `
requestAnimationFrame(count)2 L, q- u4 ]4 I; `0 E6 y. u1 V1 M
}
3 {! n& d2 l5 }) Q! r2 j+ ^5 T7 G3 b% u! T9 ^7 o6 Q
const pauseResume = () => {( m6 v( T. Q4 f
if (state.paused) {
# I- d# N7 z! C3 d u$ T+ p0 M resume()) H5 U# ^1 P% R, q+ p C
state.paused = false; M3 |$ \0 f3 D, T4 w+ P
} else {
2 k) `$ U! ?: }: @4 a2 f pause()
8 u: N1 X! x \8 n2 @% } state.paused = true% Z3 Q% c& y! h4 L. o9 p+ Y
} V: c. _- |: X* {+ @! ~& D7 Q [
}% u! G/ A7 ?3 I. n
1 V" e% O: ~* f7 C1 }const reset = () => {7 r9 B- x& u, d: S) m6 P
state.startTime = null
$ Q# ]$ l) J' v) i cancelAnimationFrame(state.rAF) n9 ?; Q, N7 O, E3 W
state.displayValue = formatNumber(props.start)5 g5 _1 x( e w' Y) |& l
}
2 b, d$ S, I; l+ E: d, e5 E" l& M: t
$ `, U3 x% a+ Aconst count = (timestamp) => {
7 M P7 J1 |5 K- X* h" Z( L: i. b if (!state.startTime) state.startTime = timestamp
3 T" k$ F+ r$ b state.timestamp = timestamp
, M( R5 h3 a8 t7 o. R/ l const progress = timestamp - state.startTime
+ g# g% z5 x3 N! e" } state.remaining = state.localDuration - progress) G( b- U9 Z) g$ q( u
// 是否使用速度变化曲线5 W& x& S/ b/ a2 E4 f f U
if (props.useEasing) {1 K3 u8 O; J& j$ H
if (stopCount.value) {2 ^1 r/ W1 z' ^, B, l
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
# @7 C$ g/ d) t. q } else {; r! n9 g1 |4 U) S; h$ g% Z9 E6 U8 P6 i
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)4 |5 r% r% B2 \( g" m, x. Y
}8 Q; ^# P9 v5 P1 B e6 m
} else {9 E; l1 @. l% q& | L7 {
if (stopCount.value) {4 ^0 F( T, w, r' U! @
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))
9 X% J: f$ G+ c& u& J& G( W) @7 \ } else {
5 B3 r# I% m8 T1 F6 i% \ state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)/ |: n0 o! A4 P! t& g
}, C4 E4 T1 r$ ~: W; z
}, o! }" X' \+ k" r
if (stopCount.value) {
7 h5 U/ M O# s2 V% p state.printVal = state.printVal < props.end ? props.end : state.printVal
) k- f. A& S8 a* O# C& m; r } else { ^4 k* }9 y( z5 v }' @
state.printVal = state.printVal > props.end ? props.end : state.printVal5 E1 s0 T, s5 c! W: f" q$ V6 g
}
+ r$ u O& {) b+ ]" G, j) w N
) g! ]# o/ ?& [, s1 c" t state.displayValue = formatNumber(state.printVal)6 Y# s, l3 v: n8 `8 V, p
if (progress < state.localDuration) {
$ m. H+ q3 b0 L& K state.rAF = requestAnimationFrame(count): }3 o. q t; S- L4 g
} else {
5 \* s6 m. Z. D1 ^* z emits('callback')# K, ?( n+ b! j" k$ D0 W
}
* K: d6 N& n% W" O) Q6 _. x}0 u1 s: \# ?6 G
// 组件销毁时取消动画
9 C9 S |- m# z+ @% honUnmounted(() => {* z6 O- l5 P, a( ?* D
cancelAnimationFrame(state.rAF)
/ f% }( V, G1 |7 u' ~})
" Y& R+ ?" g* l1 @+ V</script>4 c8 O9 t- m- b$ s# I: L5 c
8 C" Q6 \! @, o" o7 I/ J1
- ?" S0 `( [9 a0 l/ `% K# h# j7 r2! ?) u# e/ n( Q/ n6 Z0 a
3. ?: l1 D" ?9 ~( w6 \3 U2 h. ~8 `
4
) D& C) \0 @# E: C* Q% f/ x+ X7 m E4 {5
, E Q% Q: N3 _* P" q% J66 t( a0 S- ^# z$ w7 r6 K4 O, r
7
; x8 M, g0 H6 _0 F8
. X' U7 l4 Y4 r$ n( r4 y# x. g8 d9" c6 v; P( u- ~( {9 [% [3 [% V) E3 d
10
0 E* b$ r9 v/ _$ q) h11
* A4 v+ N* w1 R/ r$ a- v3 ~. r12
9 B ~- R4 S1 X2 }0 `( l5 z* a13
, }. B9 o6 Q1 Y14
% t6 N/ {$ G' J15
5 r' L$ J) O6 l6 [. ?' c166 S6 P4 p+ i$ G: H4 P& u ?+ S G
17
- c7 J ?- N8 P5 T5 X6 d18
+ J4 q+ g3 U) ^7 [+ Z6 }9 c( f19- K; U7 a# `- f @6 m4 x
20
w: [0 p' H1 m) ~ l21
4 q: P5 x- L4 A) l) [) k22! p) x& s& z4 P, v! ~$ i8 A1 W |' k
236 ]% W' P: w/ l% N4 Z
247 E# S2 a' h4 K$ c
25
' l% g# ^ G9 @+ L; A26
& v) h+ S- J0 b" R, O9 d27" h0 w. O* V2 N2 V$ M4 Y! v" T* e
284 q U5 m& @4 Y7 s; v2 v
29
9 L( _- `# n, O30/ g8 v3 w/ A& ]% K/ v, T8 k; W
31: { r3 y# h" O& X; i
32* H: ^) W& I9 T7 F
33
. C/ M* {4 Q9 F5 U& m% L9 \3 ]. }34
4 R; b1 R& q) I6 `9 s O& g35* A5 V& {1 b0 W0 I
36
: Z: i: U& }2 E( v, p37
/ E K5 b- m* P" s) f/ ^5 m38
0 r; o$ h0 M; W395 [- R7 m, D+ y1 k3 Z# U9 u! p0 h" C
40
, w: \; ?5 \7 M8 M5 J Z411 x( e" Z; @0 A0 t. h
42, s( l( r" m/ K+ h
43& v# L1 j+ S1 V( I5 Q9 g2 t/ n
44
5 a( `" V: y, G$ u; V* i0 [8 _7 p45 X& @6 |- {3 J; X) q8 `5 d6 u# D7 D. ]
46
9 x. [! i0 s1 r& u" t+ O' h47
! }& |+ j6 v, ~1 [) f1 f* q48/ I5 X/ j" ^! ?' q" C
49
/ G j- H1 H/ B+ L50: ~2 H+ ?: a# |" F! I
51
3 Z/ R" z3 ]8 j, U ?52/ f0 ?" G! K) \( \* _* f
53* w. e+ }5 f! p
54
; w" T/ V: X4 k% B: }3 k6 V55
/ z* E/ M9 ~+ y568 X( R- j5 n: e7 M2 K- _) h
57
( W" w$ Z) y% L2 P58
4 v8 K" m$ N) S: z% h59
4 b5 l6 _4 P3 C+ u! @60
7 J0 h2 s8 p: n2 ]" W# }. o61
2 p$ K1 g% M) Q, d625 n* h+ N: j# \
63
3 i i" g D, q4 S8 P( h645 y1 R$ H+ T; g; W: a) Q. N
658 z ~' i5 ~- l% `+ ?
66
) \) u3 m! `# o( O) u67% f2 c& J1 z2 Y' r z
68( S4 a. _0 x; k# N+ F
69
& u }3 ?& l5 K2 u- `5 T) ?2 j& O70
& y+ j: h' K6 K+ D. U" K71
5 r! b$ y4 d# _4 y$ w8 y! h& o72
" ?* p" t0 u+ Q0 E6 H3 i6 Q734 P4 e& ^7 x2 a# j% W' p2 s
74
8 b% o% p3 f2 \0 e6 q* A4 s1 r75
! v ]& m- a) k4 {3 ]9 m) _9 r76
+ D4 T" J" S2 {77
3 l; E- q" e7 y- T6 n78, {+ G& N: q0 b4 N- k" e
79& m* C0 N/ w r7 A+ V" N
803 Z- Y; m" d6 |- ~0 V
81
0 p4 A- l& z. W7 `* }825 H2 z& |. V" ?; v
838 l+ K6 L# r8 h0 f9 \/ ~# t
84' D" n; }9 e9 d* W& V6 O
856 h$ T9 H4 |8 W% l* L
86
' p3 V7 Y7 _6 ^4 R87
3 M, v, D ~2 u3 `: l/ W# f88
+ ^7 v# ?4 T/ ~7 n. K! W x89 |. i+ S D% R6 T
90# h2 U4 h# f8 i* ?& | q
91# [! _# a% F/ P c+ S; _4 o+ K
922 o( n. n5 h. ^! o, g, [
934 J7 ~1 ]7 r- Y' H& `
94/ r, R8 k0 \1 ?% D2 r F6 U0 f
952 N* e, ?' ]" V
96' P) j% M% P& r N; k
97& T) ^0 y) c8 @8 i- x" d. y E+ y- q
98
: S$ D+ f8 i2 {' z! a: w% d2 e6 C998 C! @# F( I `/ Z3 s
100. Q& Y: I# z5 |" X
1019 ^8 c2 x3 s2 U a" n- [
102$ e; K4 x3 z# u) z2 R0 z& z0 I
103
7 U5 K* ?+ t8 X2 }/ Z104
; P! R6 e: ?9 R5 c1053 Y- V Y4 v* N" H
106
R/ _4 A, A% X107
1 Q) R2 y8 |+ J108
# O+ S; G: u" Z$ }" K1 [" w* L109
3 D8 _( Z7 }$ n/ |' J9 L110
0 m* m, Y q: B! V: Z111
% d, A) p) z$ M/ e: W; n112- n8 ^% z+ x' ^2 ~0 ?
113
0 u( m' G) V) l1 {114
2 C* G) B$ _0 U115
6 i* o, C: L3 L2 Y6 I116( l( }0 j, ] z& C9 `4 p
117
3 o, g5 u4 e" K( y I) i118
2 l' ^2 [+ Q) g$ h) f( c119
' q* r, c7 `& K! C6 `1208 h" A& e8 O" S E+ U- E
121/ y6 z- N/ t2 G4 Q0 U3 a- v
122
4 O0 X! y6 N: _ K123* H" b* U) R1 O+ ^! n9 E
124
0 R1 d; ?6 k& b# F% v5 x0 z125% \4 _3 y& ]/ i) T( P
126
( l( `- f$ R- l127
/ n+ I4 o/ } o6 z& T# F1 `1 c8 |128% m) `5 h* `/ O
129
/ u; Z% g: W/ ?5 s130; ?9 E8 H2 y! L. N/ B& M6 N* x# U, y
131
8 Z m: k; h% l132, d \& M9 X _) W
133
/ n, F! o; g; }% M0 `1 @; `" J134
n$ Y) R3 G- L$ x. X! _135. h% n0 `+ e/ I
136
& b. P, B Z. {$ d2 \137 ^: C$ {; |7 A/ q0 w y. ~( @% v
138
/ s! `- N* ^4 q$ f; s6 h" G1 K139$ y _2 t: e# A P/ m! {; R+ Z! f
140
. H r k5 r9 _7 b1412 `8 |: Q; K+ \
142) R: L3 {/ _3 W7 P% D9 W* e
143# G9 E+ l7 J2 r
144
8 B1 \6 z% s- o8 a; m6 e- E) r145, }( Y7 f! U% @1 |: L ~) L. o, C
146
3 y& J8 q" S. B* I! x147
: R) w T/ d" ~+ b* e148" I+ [0 e: G, L/ D) ^
149
) A2 f1 l4 j& d/ }. E5 y" ]150
* R/ a+ e( X' y0 r- P151- Q% w$ f* S5 r9 ^* X, C: u) {
1529 S s% E. N" g$ Z# s0 y6 x
153
$ d& u$ _0 e3 } [/ u, u! f& y8 H154
. H6 |, W; v' P. i1 S$ C4 T155
" O1 b5 R% l/ D5 K$ p156) T1 t Z( I; B" i7 I* S D
157' W) Q9 R! U g
1588 b4 ^! N N' g
159) M0 J( x; H+ J( A. w" Q
160
2 g6 h# R) V/ H$ k& O' @5 x161$ U2 ~- p3 Z7 q1 {2 ~) u% M$ @$ P# H
1627 B" \9 ~6 w3 i
163
5 R, q4 _, Y. ~! n v1647 G+ C, r+ l, S! A/ X+ w& e3 D+ F
165
4 u0 M0 x: v P5 s+ m+ j" ]166$ n' b9 W3 T% ~2 V0 @1 ~
167
" h& O6 y: [5 I' t6 c9 F& U168$ k# q, T" {, s9 y2 ]2 V$ v
1693 m( m9 Z8 [2 Y5 g3 v
1708 N* J \" n& F5 ~
171
2 v8 `8 f: b. N( f$ Q8 S2 r172' H i5 c% U8 O- M
173; P5 ]" l' G9 W* F: p& g
174+ O6 w( L+ S* ~) {. Y9 F9 o
175/ N7 ?3 z2 `& g2 ?' c! X- U
176+ w1 ]2 o3 m/ u
177
: _: ~) k$ w0 @178$ ?: m- ~5 g( z3 P
1799 m+ w, w, S: s0 @2 z
180
: e, I) N: z! _) s. J" j181
$ r8 C0 m% f. z M182
9 ]5 e8 E6 e# m$ O3 }183) s4 j; }$ @ I
184
+ f8 T4 I: R( E185# ]+ ]6 g) M! Q. M
186( Y" o' a T' Z3 h8 o+ Z
1872 n# U4 R0 m F( t6 `+ X
1886 O; e- e$ K6 d2 L9 ]
1896 c: E7 ]' D, h5 s) Z. C" o2 Y
190
6 q0 ~2 g# ~, w$ n4 v1 ]% i191
# j0 Q" F1 }4 f1928 F b" U K1 h
193
! s2 X9 q3 Z: T- Z' K' ?) v5 A% g, e194
$ S7 h6 W3 L% R4 H7 @1 H }; ?) ~8 |195
; F* N# p4 m7 j( o196
' m [, s# p" h4 e5 ^197
2 o- L. ~* }' V8 W; R y, a# _9 E198: o' [0 t; _1 t! z! w1 X$ Y$ ?* d
1992 V. s4 D$ h7 \4 P
200
9 U5 S V1 C- G( \201
S, X) W" `& r5 _# n202
* I! n: W+ s) a, X+ B; Y% ?: I/ }总结* x" o; O: S" W
自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
, E; ` m, t( {. l$ I
( B7 ]3 _% T: k% P' A* ]demo演示, i; z; D- _( J5 o- F+ M
后续的线上demo演示会放在* C6 I3 Q3 t% D* i/ b3 @2 C
demo演示
[! T$ O1 m: f+ A完整代码会放在: E& U+ ?# ]* w2 L
个人主页1 v& d# T/ m7 l, A* Z2 F+ Z p
& Q4 x) T, ^! L4 P1 l希望对vue开发者有所帮助~
! [- R4 p5 u; E: W0 d$ l
/ v+ c7 s! R9 d$ b& Y2 X个人简介:承吾4 w5 }6 _1 d& d& n
工作年限:5年前端
5 ^, M8 B% S, x1 l* |9 |地区:上海
* j1 I6 n: l+ D( |个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
. M) w. J! \3 b+ b, X. ^
: d* \; c% j: `' N+ [) i: a2 s+ z9 Q7 o* q* D" s
7 }+ }. F& o+ S$ P8 V0 r2 a$ `& ?2 k) E: t" Z1 E0 u6 g
————————————————
2 m+ l) Q' I/ ^7 L2 g版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- ^5 ]' z, ]' Y: @原文链接:https://blog.csdn.net/weixin_42974827/article/details/126831847
. Y- ~: }# u# \: c/ X: a- B9 ^( i8 I; ^
! U! ^/ ?+ L' x* L& ]
|
zan
|