- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 569616 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 176108
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
vue3 | 数据可视化实现数字滚动特效8 Z% K; P0 ]& M' i9 k
5 u2 ^0 G( D# o5 y% Q) y, w
前言6 M. u6 O* U4 L6 d
vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错:* C. b4 |( w; \2 } K ]5 ~; B
TypeError: Cannot read properties of undefined (reading '_c')' y! n; i1 b% q8 W Y# B
的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图:- T+ u- i' f9 D$ @2 a2 K
& ?6 ^+ Q" H! u: f* i* V1 O
0 q& ?: ~5 ~; b. h0 M5 v: [3 M
思路( O8 [8 o9 ]+ D3 l J/ J4 e' A
使用Vue.component定义公共组件,使用window.requestAnimationFrame(首选,次选setTimeout)来循环数字动画,window.cancelAnimationFrame取消数字动画效果,封装一个requestAnimationFrame.js公共文件,CountTo.vue组件,入口导出文件index.js。
0 r' T4 g1 g( e! F
# l" Q4 G+ R; x文件目录, q) U. G1 ^) g" s: Y0 V
/ H+ t5 K; u B( b0 e; l0 \1 Z* l5 |2 y6 ^0 \0 a
使用示例% }# @ L- b& w& \% t: P, Q/ A3 H( H
<CountTo
; i5 L" s5 {. \ :start="0" // 从数字多少开始
+ R8 P$ `( E- K. R6 F3 B :end="endCount" // 到数字多少结束5 Q5 ]+ G* e% U! p
:autoPlay="true" // 自动播放
6 e( ?% V5 X( u$ A1 [0 N1 E :duration="3000" // 过渡时间
6 `/ Y2 ], a/ W W prefix="¥" // 前缀符号 l# i4 Y( m `8 i6 T
suffix="rmb" // 后缀符号" N$ x. M. t' t* }; w% A* t2 H1 n
/>* e% C8 D0 C5 t7 O
1
& k& S# C: k6 |2' ?3 P/ Z# [3 ]
3
% C6 q6 S: X7 R8 I' E) y K1 ?4/ c& i7 D, E# s. M3 f% B( D
5
, Z3 E" y1 ~+ X0 C60 {. n" a( o2 V7 }% V5 b
77 K9 {3 Y# {+ h. C0 ]+ ^' {' H
8
; C' n) |( X6 o `$ q. `2 g3 }; @+ B入口文件index.js
& j& H( W0 o' m4 ]. x% S3 L# \/ t& t# S0 ]2 e b) [+ g
const UILib = {, i4 q W; R, K& _
install(Vue) {: t" a. Q9 ?( E4 X$ s# c9 u
Vue.component('CountTo', CountTo)& y# \* {4 P, W& h
}
. G3 }% b( n$ z7 `2 m3 [5 j" ]4 K( W}& c) a3 I2 W3 R+ `+ [/ G7 C; N
% N3 }9 w6 @$ j* Z+ c1 @, L
export default UILib- g1 E, F) B2 v
. w# K. W% U' S+ n9 E
1- h: X d. u. Z \
2; g; N9 m% P: v3 D3 \$ m
3# h3 J0 r0 H0 E3 [" J+ H$ s, W, O8 ~
4
* O8 I5 I' L" G) C5 T51 o6 |1 r1 }2 u& j& g+ T/ X
6
, ~% e1 P. j7 I# \7 x4 ]& o7
1 G) O9 o1 C9 z4 ]% `! K8
* ?% T7 i! V6 U S) Y/ P) X9
! ]3 Y1 n. X X% G% \# R* vmain.js使用" L) u+ {$ [, u
import CountTo from './components/count-to/index';
% C# d, W6 D0 ?app.use(CountTo)1 b* C* Q2 a* S( f3 `; x
1' S. @$ k' O" A( z" x, j- d8 E
24 t$ v7 W, z) r5 H. W$ \: Y
requestAnimationFrame.js思路; e7 M" ]& i& i
先判断是不是浏览器还是其他环境
' `2 k$ v6 q/ \3 m如果是浏览器判断浏览器内核类型' Z; |8 Y" W8 n5 d0 F3 t
如果浏览器不支持requestAnimationFrame,cancelAnimationFrame方法,改写setTimeout定时器4 i0 q8 e2 {3 L0 h! c
导出两个方法 requestAnimationFrame, cancelAnimationFrame
# i+ p, z6 r& D; n7 R各个浏览器前缀:let prefixes = 'webkit moz ms o';1 Q6 H- j7 Q1 x5 |
判断是不是浏览器:let isServe = typeof window == 'undefined';" w: f U3 y0 b3 q
增加各个浏览器前缀:
7 \% k) A8 r- w& D6 klet prefix;
! x9 I: c$ Z3 U- l/ A" t Flet requestAnimationFrame;
# N" R9 C3 Y* P4 P, qlet cancelAnimationFrame;4 x( ~2 Z- p% o" W& N& P: P
// 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式$ n3 z+ a6 ]' b5 A
for (let i = 0; i < prefixes.length; i++) {" J: j2 [% Z# ]2 L4 b) d; `
if (requestAnimationFrame && cancelAnimationFrame) { break }$ j1 V5 e2 o3 W& ~% P" U( z" ?
prefix = prefixes8 y& H/ e1 p, Z
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
5 u: M, Z1 ], E7 t9 s$ G0 u. T( L cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']9 P5 Z! D* `+ w% m
}+ E9 T6 I5 { ~0 q# x+ s2 c$ s
2 C9 I6 S: D7 P1 ~
//不支持使用setTimeout方式替换:模拟60帧的效果
$ R$ ]1 K& S0 ~" g4 J* v+ t2 v; ^4 p // 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout( F& R* {' H; g2 E
if (!requestAnimationFrame || !cancelAnimationFrame) {
. v- b$ o2 y7 m+ T4 {# _2 p( T: i# n requestAnimationFrame = function (callback) {1 _- P1 i2 \3 Y
const currTime = new Date().getTime()
+ `, i4 q1 c' J& n# F7 X5 e // 为了使setTimteout的尽可能的接近每秒60帧的效果
; M3 ]; p% P. Z# q9 [" l+ } const timeToCall = Math.max(0, 16 - (currTime - lastTime))5 |' _% z: n' Y
const id = window.setTimeout(() => {
( b i: x% h2 h" x callback(currTime + timeToCall)6 C4 Y: z2 p& C) z7 j
}, timeToCall); k& ?4 l3 E" P0 \9 A1 f
lastTime = currTime + timeToCall
3 w, d5 E: W. A2 U return id& t! X0 w2 G' E: C
}8 @3 @' z4 C4 t- j; [' X( U4 |
4 k6 K+ `. L' C6 x8 V7 S; B
cancelAnimationFrame = function (id) {
/ ]& ?5 F- S' L+ e6 ` window.clearTimeout(id)7 l# W4 Q+ y: k0 r
}
& K4 |2 H3 r( V9 |% W5 F- F }4 ~3 {2 f8 q# f5 @7 Z
h: _ `! P7 ~7 [. [ i
10 C. G; n& D ~# i
2
) o! ]0 O( c0 }" S3
" _4 t2 ? Q" i4/ F- n) A4 Q& y+ e4 e
5
; r3 O0 c( h, u }, A6* ]2 b9 }, r9 P5 ~$ C
7
0 b& z( Z3 c7 S) X5 I7 z8* B$ @! V6 F- ?8 U' b1 L0 u6 }
98 T: S% ?9 k- ~) ]
10
( i* x* c; M' O115 N' [* U) S; u" W6 E2 L
12' @& P! z/ V; o. L7 U
13! ?0 A4 u. C% n! t
14; _: ?$ f; U9 b2 X0 B$ J6 g }) u
154 u! j- h p. Q& g
16. B4 c) r- l5 e8 ]
170 z. L# o# n; F
18
& ]2 d7 m2 V! F1 H, W f" J9 B5 K193 l9 o3 a# {" M6 b
20* t9 Z' X( \9 S* \ r0 T
21. I. U3 r' U4 U: q Z0 B9 |
22( Z. L( ~" R- T) g- k5 Q
23 w+ }6 u0 U0 I# P
24
" D9 m3 B) o" L+ G255 q- |& L) s4 q A0 F
26
" y+ ^0 D! A3 R0 d Y27
8 k3 [: t7 i% o! @3 W% n% h: \28
C( R1 Z7 a0 d/ d# ~29
# `" l* k5 }) Q0 q# s4 l306 O! I- X1 d. t" D8 i* ~
31
/ [4 Z9 a! M5 Y4 w" o/ ?! C# i1 X; m32
" G1 d. L+ s5 d; S完整代码: L- m M, F- }5 Q1 y1 G' w0 V
requestAnimationFrame.js
+ O+ S* T/ A: X& \" z" L( K/ ]5 l$ h- S4 i& k, q( }; H/ d
let lastTime = 0
0 \8 h z3 t) R' @ @9 `) tconst prefixes = 'webkit moz ms o'.split(' ') // 各浏览器前缀
0 q" `8 | D9 u; B. x, V9 J: i2 Y; G) e$ \7 P. k- d- y$ f1 m
let requestAnimationFrame$ N. T( z/ g* V" |% X- b% D
let cancelAnimationFrame! n! b& J" P) F8 s N# k7 l! S6 P. k
9 @, k( u5 D9 Z9 k, e7 b& o// 判断是否是服务器环境
0 _9 R3 _/ ~( n6 p0 H6 q+ p& L2 X) Q1 [const isServer = typeof window === 'undefined'
; z" ^, s. S, Wif (isServer) {
" S% D1 ?. r \) k! I1 X requestAnimationFrame = function () {# L4 e. W8 J% p0 k! L- c3 `
return
1 P3 G& }* B, ?1 b: D: r4 w }+ P r% E2 A# X! [
cancelAnimationFrame = function () {
- B. u1 F N; b, q9 N return F2 n7 ~2 y9 s
}: D1 b, J0 X7 \0 r
} else {# q( i. p+ l O5 _
requestAnimationFrame = window.requestAnimationFrame5 ~9 h0 e5 L7 k3 g( n. z! r' D
cancelAnimationFrame = window.cancelAnimationFrame3 L, Z/ t8 G; X- f( ]# u
let prefix
4 z; L; [! C8 n // 通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式1 E8 k u" Z+ o* ?# d
for (let i = 0; i < prefixes.length; i++) {
5 ^7 z; F+ l: l: a if (requestAnimationFrame && cancelAnimationFrame) { break }& c# B$ @7 Y( ]; g# L4 q# _5 x
prefix = prefixes$ r. u0 x2 @* ~/ n( S4 b3 M/ v
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
1 ?; c' ]/ }# J7 M* J4 Y/ x% V* U/ U cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
. n r' H" Y: t. _ }
6 x8 S+ u6 O* U3 P2 M& q1 q8 a4 {4 }" z# z2 g: {9 _
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
& n8 A* r& F* O( \' p if (!requestAnimationFrame || !cancelAnimationFrame) {
' @$ y f# y/ w6 z& K requestAnimationFrame = function (callback) {
: `, l4 t4 S: C const currTime = new Date().getTime()8 J1 }4 b5 M+ c: }9 \- y$ x
// 为了使setTimteout的尽可能的接近每秒60帧的效果
* U( t8 ~! v5 Y const timeToCall = Math.max(0, 16 - (currTime - lastTime))# B+ s( R0 o6 Z7 E
const id = window.setTimeout(() => {+ Z9 Q( F6 I/ W9 b3 {4 K
callback(currTime + timeToCall)
: V, c/ _5 a- F1 u* b4 N* G }, timeToCall)
6 e% i: Z# R9 n lastTime = currTime + timeToCall
) S1 _* ~* K0 q& [3 y8 U return id
* d: a- Q3 R6 l }! O8 N- r" I1 H; s
K: t8 @( f! @+ q# ~! g
cancelAnimationFrame = function (id) {) @* R* H% W' O* [9 r3 M5 {. e
window.clearTimeout(id)
t$ j7 H- q( o2 G- D, I }9 B+ r% |; x- K4 I+ Z+ z
}
1 b# D- c% K& m, \! i/ T}2 G9 V- k& j2 p' K- G5 t; J
' M' ^% h3 g8 Y* }export { requestAnimationFrame, cancelAnimationFrame }+ `0 d- @# X2 u H9 ]; J9 k
7 A, N! y" A3 Q( s% l8 Q
# r- D3 o" U: \1 e% `' Q1" V4 s, `. G( `
2( \6 N& ^# {. o! r# i' Q' a2 e
3
- m& z2 B Y3 ?+ G. E" }) R4 h) E4
4 L9 n) C& h, |9 Y3 \+ e9 y$ b5
0 ?$ c8 X3 N9 K0 m8 @1 _2 U6
4 H/ z8 W' f1 N* S( `- ~' v2 p7
& C" B0 A8 `9 `5 R3 x8" D: I4 m! ^, @6 R/ c7 _4 |
9
% }' b& E/ { y( G, o$ m10
; U. f' E2 U5 s ~/ u! Z11: U* N ^ H+ ?% Z, f
12* j7 |3 L9 u3 p8 o2 G4 \
13
* d/ e. Y: L) x3 p; e) E14
7 B+ g% Q; N$ j1 ?% d15
1 ]* M4 d5 N" B Y4 Y16* k; I# N! W' S0 P
174 P7 Y. @! J0 U, L3 a9 G
18" z/ W1 j, E9 l4 C) ]1 R
19
1 B) S+ d) D d+ x' O6 m3 G20
0 U9 z: H! x, u6 O0 D21
4 ~) k7 L% D% q3 |' S. z22
# e9 Z" ~' e9 ^& z" `239 B# M, G0 L4 | W
24
- P c6 I% X8 a2 r( S25
3 t0 i; f2 {' b7 e' S* y26( e& F& ?- |7 }' m8 \. u: y# Q
27: V/ U) \$ k) w; F% e! ]
28' {7 w c% L) {
29
- x) I" ]+ D0 ~( d& j30$ D8 v; D! Q4 Z" }9 N. j
31
2 t( s9 v$ N+ r7 E0 x# j. I, p- p32; d P F0 [. ^& P& ?8 T
33
/ A9 c- V3 F: m7 z( h6 i" f) [( R" U349 H! z5 l9 I" S" T2 X" K% m3 |
35" `( ?5 U! ] k: R L0 c/ q
36; [$ A+ w2 x$ G& q3 i" H
37
) F# b! ?8 k" [+ k: ?- z# s4 G$ ]38
2 c9 j# r+ J5 g9 H: M7 N w394 u1 Y- W2 R; j" U5 `5 B9 \
40+ U2 X' C8 I. K9 Q" G* R$ W @
41
4 L9 p m/ {2 J, l1 h: H1 @3 j/ e424 W N- u" @0 O# l) Q/ @
43
2 }: p% M6 m0 B1 P44 N! N0 Q% O% |( O; P
45: u2 b2 i0 C# `
46
0 D; h" ] O& b+ m47
4 y# {+ W# W" J. A5 |6 h% K486 v# Y& m, z7 Q% s
CountTo.vue组件思路1 l5 \1 Z, ?- w- l- M
首先引入requestAnimationFrame.js,使用requestAnimationFrame方法接受count函数,还需要格式化数字,进行正则表达式转换,返回我们想要的数据格式。5 D9 f3 j( Y& _/ L1 _) T5 h0 }
( a( Q( A1 v# A2 N5 K
引入 import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'1 S% o% l- U- }* i
1
; Y1 z- c4 f g需要接受的参数:8 X3 O( g0 T. q& d! x `4 Z! }
, @. }9 I9 j' L; v7 M5 K
const props = defineProps({0 x! `5 G+ c* U/ f1 d
start: {
% ~( O/ P' [$ d F3 s& I# e type: Number,
6 C/ q9 d$ ]5 `6 J) L$ o required: false,* x5 l3 ~& W' {; S
default: 0
+ z# V, n7 S4 c5 v/ u! w5 h },
8 [" D! k! z8 a2 M! J) w end: {
: R2 P! t& `( f' F type: Number,6 T- H. J4 C8 p" {
required: false,5 v* O( [ L5 g# Q1 i
default: 0
7 R4 t, x1 w9 S# ]: E3 q& P },& l& C3 t9 W2 [! ]% Y% X
duration: {
w8 I: i4 Y7 O5 `* A type: Number,% d( l1 M9 v3 W \2 ]
required: false,
* B }& T( L3 h2 `& I default: 5000
4 {) H2 A8 E/ d( ~# n3 [1 k },5 {5 \9 q" C0 @0 {8 V! a5 W
autoPlay: {
1 i2 D" y( d- n type: Boolean,$ b! i/ q1 O, W9 c |
required: false,; i, H/ ^( u& x1 Z8 F
default: true
: p$ y& O& [4 T: G9 L! R8 A0 r },: Q) q+ S: b- Y1 j1 d& z% [6 u
decimals: {3 u+ w& v/ I9 c
type: Number," Q2 p1 T6 t2 q
required: false,
1 R+ S: }8 I) b0 ]7 f% G default: 0,
/ G% x* I. E+ J. V$ I, y+ b( K) w validator (value) {6 s# l6 v# m" W: t8 q& R( V
return value >= 0% K5 y1 O {7 W' |( Z( O
}
* y! o' ^9 O% _" p3 | },' B5 ?; P+ V3 o
decimal: {3 T |9 J$ `$ F/ D
type: String, F, @/ A+ z: A4 d9 U$ M H+ d3 R
required: false,
% n( h% [8 K+ j7 y default: '.'& E ^4 n3 g& a" d; s
},2 s! e; Y7 R' `4 n; B. N+ O
separator: {2 H9 p( m# h+ H5 e6 G
type: String,
& S* ]! _( _1 o/ K5 j" O5 ]& B8 L required: false,
3 B$ J# ]' ?% R default: ','# p" n4 u3 t8 s1 t
},
' ~5 g" h8 t! _- v0 l/ O prefix: {6 c e; i; o9 e) _) C8 A( }# C
type: String,
8 K" [ q* V& o" B8 j required: false,; E: r) D% _) d: b/ G5 d8 g
default: ''0 ^4 t) T s5 g* g; q
},% b, V9 g; l- c7 l! g
suffix: {2 ^7 ?# [( R/ S
type: String,
1 u0 c& @3 a# H" s/ N# _ required: false,
0 t, S" e& `7 A f2 \; o) V default: ''- A) s$ R4 j( U8 i- J* U5 z: T" `
},, S) ]! A+ E ^" o
useEasing: {* R: O( [* |: m8 S
type: Boolean,5 e) a. D+ i' R& U( K
required: false,( i0 e+ ^$ o' {! A
default: true1 w% x$ W3 d$ d1 p$ i
},
. q8 S* ^% d7 Z8 Z easingFn: {
* P1 w3 `1 F0 J2 F type: Function,! \# f" F# D4 {6 a
default(t, b, c, d) {
1 o: @4 p1 v; ?3 D return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;+ k$ i6 u8 U3 O2 ]
}2 N" F( Y+ F7 t. @. ?
}0 q' F9 x! m2 J5 c
})
& Q, K8 Y5 `( n5 W
, @) I0 {! c) A, e; @* ]& m* I! B! g& r, ~1 u. z6 X
1: B2 _% R' }; U! I+ E8 x
2
! n/ {9 ]: O" u7 S4 b3
3 B6 e& Y3 y- M6 K4( P: w! D+ ?/ g. D1 ^0 i$ U8 ^. j
5
8 |4 D- t$ m/ ]0 Q6+ c# k8 r' Y8 X
7
$ \. u# n4 u' a+ Y+ j! O. w8
# x! E. G3 U" Y3 M' ~8 G9 ?9( }; J1 n& B+ l7 r
100 O8 U$ U% o; Q: ~& }+ h& \; f
117 R0 r9 e' A4 Q( n* C! u( w
125 w6 Z- F4 M* b3 o) E0 y/ s
134 _/ J1 k% F# D3 |# o
146 N, L& H1 X2 i6 M% l
158 B5 A3 H U9 B5 `
16: _* \! b! [8 I' @1 b# k
17
5 z; R0 k4 }. A1 V/ } j, @( Y185 F/ E3 l) |! e3 _1 C
190 I9 `) @- k0 t) y, Z1 ^% T
20
5 `' Z* W5 M- _# h$ T' Z2 _ T21
/ L1 V8 H* [" k! t0 k! R* j) A22" h6 Z) u* S% f! e+ w5 r _
237 M/ ~; f& k+ p$ a3 L$ @3 E: K# |
24/ T7 n' z$ M$ g' }
250 o1 ?3 Q8 \" Z
261 X) F) _ n @9 @1 x
27( _/ ?$ N3 U8 n$ L" s& j$ c( Z
28; V4 Z. [( d1 i; m$ m+ Y+ e( v6 \
29$ S8 R- e7 D9 Q
30, X, Y9 M; J3 N: u \% p
314 K- ?' u& U3 r' y# i+ v6 ]
323 M- `$ r. t4 S$ ^! _- u
33
; O% Y) j9 v- t2 O7 ?* l346 g$ J! ~- ]; Q* r6 o/ m, S5 d4 U, h
35
; W& J) }: v! w" U$ V36
1 |& J8 Q! c- N& B/ Q, P" f37
- M3 N2 }4 [) I380 v0 Q& \7 F" g' f" [; C! d% f' x& k
39. [# Z X3 K& p
40
# y% G- N5 l C4 ~ M41
! y* D0 K5 y& D+ |0 t L2 K) C423 s6 N8 U5 Q/ Y# J
43
1 t* T: T. z! l2 a! |44
+ G9 ~+ y7 V, u0 M( ~# `45
y" y; D* u2 i P46$ B3 U" q c# S9 A0 y8 o& [
47& p2 g; T7 S# O3 m& x3 f
48- `9 D/ J) d! s
49
2 U4 C: c3 Z! B$ w, I& F9 F0 U50 p* }5 f( s' z6 q: B) L
51: P, w5 |- m' ]& y
525 c( M8 g& F t, U) [& N
53
! j/ n& |& ]) e: K$ d540 @) M) o4 U5 W8 h- i H' {, }4 F
55( Q* r7 F3 ]% T' N2 N
566 V+ `' z4 Y- _/ T
57/ l) L6 Q$ }: f! e
58
1 t; ~! a- |( Z; g59; }) C' K3 {/ k& z; P
60
# B4 K9 ^# m0 }8 ?. M' y6 e617 J+ e% V/ z9 L8 f d
62
) f U0 Q; l/ {% ?; |% M启动数字动效1 f9 B0 b4 L( ?: T% l
4 u$ d2 ~0 x, E' f* I' wconst startCount = () => {9 j1 }5 u4 ^& Q6 ^
state.localStart = props.start
3 m2 z. }- R6 \: A: M state.startTime = null9 h3 e0 M6 e4 T* j3 c7 }
state.localDuration = props.duration
& {6 A* Z; d0 e: y# x" O state.paused = false
$ ]8 p6 y4 d+ j state.rAF = requestAnimationFrame(count)
$ D! L+ G$ Q7 k* R/ l* S- P}
' p1 N( l, h2 P$ i. l1# A. b3 G* F& x& O/ l
23 Z; U4 f' H1 o. V) k5 G7 I
3! U( B' i2 A% b6 H( O, k
4
4 d$ h2 I Y' I% h* y/ e, v: m5
- J; h. G3 U4 C66 m- a6 N3 n3 X1 F2 S: b' h$ ^
7( i; p' e1 m2 r! T3 {8 L( Q0 Q
核心函数,对数字进行转动
3 M# j2 O0 ]' {% D! i' y% C( O: d" h* U
if (!state.startTime) state.startTime = timestamp5 ]/ I5 X! t8 N& z$ `
state.timestamp = timestamp+ m" T# k2 l8 N
const progress = timestamp - state.startTime
1 h. u3 o4 l' I! ^- |- K4 b state.remaining = state.localDuration - progress
/ G5 N5 Y0 _ V: C/ e, O // 是否使用速度变化曲线
3 t4 y, `9 i& G3 W if (props.useEasing) {+ E/ Q* S2 N+ _) A: b
if (stopCount.value) {
( v L# s2 f* l$ j state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)
* M: u* {) S5 }: [% Q } else {) K' _$ U5 a5 m+ w' O+ \$ }
state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
: T: |" X4 ]7 v% I0 O* D6 U }5 L6 ]: S9 n& {
} else {
H8 K$ Q! o/ _( B/ m$ M if (stopCount.value) {
9 ^% p9 m* u1 e: O8 M$ g* U state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))' w" M2 J. E, p) B7 w
} else {& K6 t+ R$ y8 a" J: s
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)
; [/ G, y0 @: H# p8 b. \ }
8 P* N8 T4 C' s# s4 h0 w1 { }4 p+ j" }1 n5 e+ l9 v7 v
if (stopCount.value) {% Y- K, \' B/ G. H1 S! u
state.printVal = state.printVal < props.end ? props.end : state.printVal
7 c$ s8 u1 {: s5 f3 d1 R } else {" X$ a, l( K0 N0 y; c/ N
state.printVal = state.printVal > props.end ? props.end : state.printVal3 Y( j; f( V; X! U
}$ R$ o/ h2 f$ T/ H: P( m2 E
) c2 ?1 ]( ^4 O5 v9 f) B* u" N, j state.displayValue = formatNumber(state.printVal)
( g; G$ C# N. r5 E& u; A8 }4 d* l if (progress < state.localDuration) {0 h) x: z4 z' C/ ^ B5 E
state.rAF = requestAnimationFrame(count)
9 @ ]0 x( Q+ U } else {
/ K2 e# l$ O' b+ t5 U2 e+ L emits('callback')$ |- L# H% o4 e7 O% ~
}
/ L7 q5 ^5 P+ |8 S3 U7 H9 k M! K}
* f: S x/ }- i* ]5 K5 L( ]$ r" Y2 _; E
" t) k$ ~( M5 l
// 格式化数据,返回想要展示的数据格式
) _8 R2 M. r( sconst formatNumber = (val) => {
! c3 S, p' k" \& m! I val = val.toFixed(props.default)
2 K) T: e; J+ u* j& u3 A& C val += ''+ O, G8 X0 |7 d2 A
const x = val.split('.')
7 N6 |# ^6 I) R Y$ Z let x1 = x[0]
s H4 @6 P1 s K8 K const x2 = x.length > 1 ? props.decimal + x[1] : ''$ d! i4 ]# l8 R0 [1 ^9 s+ Y' v% A
const rgx = /(\d+)(\d{3})/" w3 C# c! c" `) ^ g
if (props.separator && !isNumber(props.separator)) {
: ~0 } J6 o( j: S while (rgx.test(x1)) {0 y) _% u9 @+ t" E
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
: W2 e" k1 a S/ F5 ?& K( o7 V }
5 j% E8 x) g/ Y# P b }0 h& f/ _6 }3 X
return props.prefix + x1 + x2 + props.suffix& k5 W1 O5 u& G7 X! s
}$ {4 e+ B9 t% s* P/ C& x5 V
- _/ l$ [( a4 v/ U
1
7 y' H( ?# z" y28 |& R. S. H5 o! f% O M
3
5 l, ?+ n6 F/ T; S% W: N- e4- \9 i9 g2 w# p+ w: S
5
1 {2 E/ i* u$ f0 j6 h6
! Z# d0 i$ A) f# Y! p5 I* o) E72 ^2 Y0 a) A" X9 U) N, j1 q
8; u6 g# e" I; d( r
9
6 J2 l2 ^- Z E# T- {10$ v _9 P/ h Q) Z W; l
11; ?* K: I4 t" ^# L1 w8 {4 Y
127 b5 c1 d/ L5 c' h8 M! N+ k
13
2 W ?# J2 J$ r' p: d148 f" N3 T8 c+ R" c% M; g. s
15
+ O. C0 g" X$ X& ?16' p+ `' m' Z( M7 l
17' v3 I$ m2 Q* M5 u/ A/ d
18
7 y1 O2 @. d5 ^) _' I8 P, g+ S19. e0 q" f; n3 z2 W2 o9 F
20' v* m' ]) K+ T
21
$ U8 ^) B5 m' Z2 n$ A22
7 q/ l$ w9 G; g0 O8 W0 Q* o# {5 L23
9 `9 x& c/ Z# N) B6 m+ T2 g: e24
& ?2 X% f+ I$ A4 A: E0 P. D25
; Q" T0 c: q7 C1 O% K26
. L* o' H0 }2 H2 g/ _27
! T! {, Z; I# \+ v3 B1 _' Q28
4 y$ ], t( m0 |) f29. [" K) w( A( t: C
303 T7 G: O- y9 ?
316 l1 v# W5 a( y7 T( f" W0 C9 X7 C: e
32
: T" O, X- K( [" }$ l$ b33
3 w6 w: }8 d4 P) T34
) `2 J- D7 g/ H ^35- `* Q/ }! B' z3 Y0 I
366 S" H: y+ J) [, @7 {
37* U0 e2 X2 m$ y* d" l
38: O$ c9 }! y3 ~" O6 [2 }4 E9 f
39
+ P2 ~) C+ u4 V9 J [40
; H; e: P+ ^3 K4 c' z: G2 h9 Z411 J S- n. Q4 @1 G. s. Y
42! f* Y: J+ `1 X9 s9 Y4 x% m' u! q
43
3 @6 }. h4 F9 O' I9 }; y44
* Z' Z# |# r5 d0 Z( l, v45
; M* `2 E% j* Q- p3 f46
0 s' w, i, l; s8 q& p470 b: Q( Y& m- e, t2 P; ~3 S3 A
48
0 l- v, f0 A" u% r6 D2 y# c取消动效
( d( A" |: S+ _$ E! a2 Z9 l K; L$ ]. e( y5 l- f- f3 V' ?
// 组件销毁时取消动画0 Y: Q% j; k- m$ w8 F, s( {) ?) t9 h6 [9 d
onUnmounted(() => {2 k' w9 B" O0 {$ t3 z
cancelAnimationFrame(state.rAF)
% a+ |. ]/ o* L: [ X0 W( |8 B! F})
" q0 {+ }! |* y( r1
2 X5 |$ t0 n5 _! F& [0 n+ T! \7 T2# G# |7 Q8 k5 u' T" \( R
39 g( G, N' f2 @( d' Q$ M
4
) D. O9 ]6 X$ W l5 ^2 F, r完整代码
# N* ?! J. A7 t" @/ h6 C0 y$ m
; \7 P/ G2 U% U6 {3 [<template>
+ _9 A% h4 r O% b# D9 r {{ state.displayValue }}1 `# [3 N; e3 x$ j" h- Z) V
</template>. _ c ~6 ^0 V( c4 {, X! s0 _" u
1 u; r1 b$ V1 e/ t<script setup> // vue3.2新的语法糖, 编写代码更加简洁高效
1 E1 P+ |. b8 }2 l0 ~1 {0 Vimport { onMounted, onUnmounted, reactive } from "@vue/runtime-core";
2 f" `9 N3 E" J% |" N/ rimport { watch, computed } from 'vue';
) ?8 x8 ~5 x, e5 H8 A3 dimport { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
! D7 _$ y8 ?% i( v. J/ H# s// 定义父组件传递的参数
+ O* G5 f$ B: Mconst props = defineProps({/ A. Q- j% } p6 q3 S; K
start: {; H2 }; c& f8 S$ J3 K
type: Number,
7 }& B0 N( U* Y. F required: false,
- _: Z2 j# p o, \) { | default: 00 s/ f+ {0 p2 w# H7 `* |1 j5 s/ ?
},
5 E4 I! v2 [) {( J# D+ R$ L7 j end: {
1 m3 G+ d8 w* d3 l type: Number,
. Y) s$ ]4 w5 Z3 w( {& i required: false,' H1 y- z: y: P7 W
default: 0) R" D- p7 m1 K1 N0 J5 m. V# `
},
/ g7 V3 K5 p j, U( R duration: {
7 r* x( a! Y) b, [5 S( m4 Z type: Number,' |7 n! Y" K% A0 C8 u1 F
required: false,2 A, Z. L& s2 y* V. l
default: 50007 T4 F. V9 _, v: e" D. C
},
g: B! W9 l3 l3 S% d0 Q# M- t6 \ autoPlay: {( x# i) P% z4 H, X" ]. H( ?: S6 G
type: Boolean,' N0 a8 _0 F) V% a/ z
required: false,
- U7 f$ V! d+ l- d, g* K default: true
9 ?# h8 @/ C+ Y8 A6 b, _- z }," I+ l6 d, U. o1 K+ z: n8 Q
decimals: {/ U. c8 \/ {+ Q# B
type: Number,' k; c6 \5 U. C% Z1 s2 Z* {
required: false,
$ n6 P# g6 J2 Z$ X! i |& Z. h4 S default: 0, y4 Y+ Z' L7 n/ h' L2 z! C' S" T1 n; O
validator (value) {
3 p; ^: w+ E/ `* A4 w) h8 h return value >= 0: X+ o- C* z% L. y4 E# [' J; q
}
1 O' e% c. p' Y/ m6 s! @- r/ w3 Y# i, E },# ]1 R9 i2 t# _
decimal: {
! S2 k+ r$ t: V type: String,
- x# g. o5 d( l. u6 r required: false,' X2 M# w+ h) u
default: '.'5 {5 J9 E8 S5 J) ]
},( C8 V% G M& N0 F: B/ D: l) K5 h
separator: {% g( }! w& G4 p9 n- x. j) k7 D
type: String,
3 u4 u* E6 ]0 h! v4 A/ L7 [# g required: false,
+ Y9 T: U: n3 F! o; N default: ','
" c `4 P8 ^( m+ t6 t; } },6 D3 K) D4 z3 P
prefix: {6 D0 t/ Q, m" F n. i3 K# A
type: String,: D2 R+ H9 {- h0 o, Q* `
required: false,
) X- |# {( Y/ s7 n8 Q- P; q5 I+ c default: ''
5 c1 p8 H1 Y) Y6 P \9 M },! I5 x0 e1 o, r$ `# n4 U) `
suffix: {; }) E; f1 ~" Y- m, e, C* v3 P6 @, c
type: String,
1 c5 ~" Q, C6 p- U4 q: y! a required: false,
4 K" ?' H# m" ?/ S2 a default: ''
4 h O% Q4 Y1 {0 B; X& r },7 c! `$ M# G8 T3 ~& e8 G; W! r$ A
useEasing: {
4 }3 A+ e* Z: U type: Boolean,
5 F- O+ A0 ^5 J" {/ `* N required: false,% }' f: }+ L" s" X8 D' S) x7 p: e
default: true
: ^5 _, i9 D1 d8 O/ x/ ^ },& y. Q; S9 o0 U9 k- c7 A
easingFn: {# A) T0 }4 v9 |4 J. \) K
type: Function,( |- [8 y$ `; O( }
default(t, b, c, d) {
, A, _6 Z8 t& M; T return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;) z) _$ D3 b b1 z6 i1 |9 y0 X# d
}
1 g4 i# H. |0 z% r N& ?8 { }
+ v3 b; C# w$ i})
- B' L0 E# _9 W
8 C: z# l* r' M0 mconst isNumber = (val) => {6 }0 I* X* C7 m% X( l* a9 K
return !isNaN(parseFloat(val))9 T) z. X( F) j% P8 ~6 C' ?0 Y
}
1 Q- T/ x, O5 s0 Y$ w2 O2 f( W# h) ~8 ^% A3 _
// 格式化数据,返回想要展示的数据格式
$ @ S* H. m% h/ tconst formatNumber = (val) => {4 u+ s6 w) N9 f3 F4 M
val = val.toFixed(props.default)
. J. i E$ ?3 q9 o val += ''0 ], y4 X% g* Y A, |. d2 Z- N
const x = val.split('.')" M! b T. A% G+ w$ B& F
let x1 = x[0]0 ]" e8 \, X J5 W8 }3 w5 X% m
const x2 = x.length > 1 ? props.decimal + x[1] : ''5 X; f' x- |/ p0 l4 w- H
const rgx = /(\d+)(\d{3})/
7 y$ R; a9 V. g1 \8 h% y& F if (props.separator && !isNumber(props.separator)) {
5 S' P( c+ { J* v2 m* ~9 z$ x while (rgx.test(x1)) {+ k# O. u+ x8 K
x1 = x1.replace(rgx, '$1' + props.separator + '$2')
x" C" O7 W$ |8 e0 A4 O3 \ }
# F n1 f v, q# R9 C" K. Y }
' x8 E% o. L2 D/ O* M7 F" C return props.prefix + x1 + x2 + props.suffix
# y+ q% O! E# L! s}
* x( l. q0 ?) v2 m: L9 S Y
* g9 ?9 {2 T# l: ~% C3 F9 p// 相当于vue2中的data中所定义的变量部分
, f% l' \* ]" e- |6 yconst state = reactive({
2 j4 f3 y$ Y2 j) n1 B. E- W localStart: props.start,* k0 a* n6 q6 D; o( F* r) x+ _
displayValue: formatNumber(props.start),
; K. `+ H) i4 g, P printVal: null," k; C& |1 M- t* K) k6 _) K
paused: false,
- E3 W0 Y4 t9 _. [2 j* B localDuration: props.duration,
_( L( `1 R& ?# [ startTime: null,
9 x+ R# o! f8 v: D+ f* }$ t timestamp: null,
, t; f2 O v/ d' ]" q$ W remaining: null,, ]' n5 O/ f1 a E
rAF: null
4 f( V7 ^& Z& p; g})5 m" M E# ?; @9 n
) D5 C1 B; S; s; d& ~& F/ ^
// 定义一个计算属性,当开始数字大于结束数字时返回true
9 D. J# e) |! u) {const stopCount = computed(() => {$ n- P W4 D: e' ]
return props.start > props.end
2 k& C1 R0 _" R a |. j0 |/ |})
% v6 ^: }# }2 N7 A// 定义父组件的自定义事件,子组件以触发父组件的自定义事件
, A9 Q1 l# m9 c0 c! P: i3 Oconst emits = defineEmits(['onMountedcallback', 'callback'])+ {2 M) Y9 A' C( A e
3 N/ W1 r: N% x! n Fconst startCount = () => {
/ J7 j5 x ?7 C. j6 `1 u. ^+ P% j state.localStart = props.start
9 V: D6 _# d- Z. \ state.startTime = null
, L9 H; m0 F8 d0 F @5 Z9 g state.localDuration = props.duration
1 A }3 i; H+ W& N; |( y4 O state.paused = false7 _' t% ]/ V# l+ ~
state.rAF = requestAnimationFrame(count)0 G; A- ~6 N! s, R7 L
}5 i) }/ a$ K& r9 b# U
# W& F9 d/ ~1 a& _( }* i$ d. uwatch(() => props.start, () => {/ g- h# s) d5 r! x5 p9 |9 b* s/ I% T
if (props.autoPlay) {- \" i- d7 ~9 X# [5 u
startCount()0 z, q1 n# \- \) c3 i2 a
}
# n- ~" f: x' R K3 V' W})% l& @2 Q( m/ O9 `: q! S8 Q: G) ^# Y9 q
( O# S9 ?, |+ N8 a" I3 Q
watch(() => props.end, () => {2 {* s! q0 r% S
if (props.autoPlay) {
, }* E, D+ Y! A8 `: f1 l startCount()" h8 E H7 k6 I% `2 w" t) ]& d/ |6 l
}
8 F" j8 M2 {' x1 A5 r})
7 t4 q7 D- H8 d7 e/ d) _' I2 u: X$ M// dom挂在完成后执行一些操作! x& N. Q& ]6 D9 \# c' b/ z
onMounted(() => {
$ V, G" I& m! n if (props.autoPlay) {2 u( m& Y: r1 @/ H
startCount()
; L# s/ o% z' g, c7 S2 t9 J6 ] }
* r( |: c" K$ h( Z8 ^. K% A emits('onMountedcallback')6 _) N6 [; t" _6 k1 Y& m) v! g
})
: k8 w- A. z/ B- [0 M; @5 y, t# P+ J// 暂停计数6 S4 z* d/ |+ J+ X* T
const pause = () => {
# ?6 }7 w# b4 Q2 l4 b) [+ D cancelAnimationFrame(state.rAF)
* Z" o9 H2 m2 X}
1 S5 y! g. B4 k( f5 u// 恢复计数* p8 i, E3 G# ]2 v% R$ x
const resume = () => {4 N, G; L0 T- v1 Q! q: I" e( l
state.startTime = null
7 C1 y0 N# p& r2 j state.localDuration = +state.remaining
g9 C! O) B: g6 s( O. F state.localStart = +state.printVal
6 y( U4 O& i5 N9 Q: g, b1 T requestAnimationFrame(count)9 W) p3 l5 j8 z+ a% e5 A" t* d
}
, h$ E( G- d/ g! [9 c2 B7 q5 n2 \. F: ]* u6 z1 W! Q. A4 Y
const pauseResume = () => {2 h" Z$ l' h, e+ l3 p
if (state.paused) {5 @# d! s4 z$ t+ u' b- V
resume()
6 _. L& }, Y( t; e% j& j* m i- Q state.paused = false
. |4 ?/ O4 u ` ] } else {
/ f6 D" p: P7 f, k. L, J pause()8 w [2 v7 s# E
state.paused = true
) B, F u6 ?: S. n3 v, l3 P( s; n }0 k" A+ f& P( W6 ]$ }' T$ v
}
+ ~' T8 I9 O, [% }" K1 ^! t1 W# T% ]7 i- |$ C) ]
const reset = () => {
* e# c: f) b+ a6 [ state.startTime = null
/ A! n! i3 j! [, x1 D' X$ m cancelAnimationFrame(state.rAF)
6 x9 q+ ? A% X state.displayValue = formatNumber(props.start)+ t& B% M# T6 ~" k( ?- s* y
}% I, H0 d. ?# U8 f4 O. p
4 P* H& M4 k- {5 ~9 w. Fconst count = (timestamp) => {. Y7 C* p) D" t- I$ j! R# V
if (!state.startTime) state.startTime = timestamp" o/ J' U" x; ~, b/ h
state.timestamp = timestamp
, P3 g' K" l8 n6 ~ n const progress = timestamp - state.startTime9 i. N4 P( s, B1 q" Y* g3 p. y
state.remaining = state.localDuration - progress
1 V8 W- e. `: |) R, R: B U7 x // 是否使用速度变化曲线- i. {+ ?! A7 y
if (props.useEasing) {
/ l0 S- q7 R3 \% v9 J if (stopCount.value) {7 I1 i: t5 \" `) ]0 s ]8 E
state.printVal = state.localStart - props.easingFn(progress, 0, state.localStart - props.end, state.localDuration)/ f9 e% o' B% p0 F) ~
} else {
3 k" c5 w7 I0 N5 K* p state.printVal = props.easingFn(progress, state.localStart, props.end - state.localStart, state.localDuration)
3 S' R, c7 V, H }
v6 s$ F" R3 a3 [ } else {& d% U1 H8 I( x$ ^5 A0 m g
if (stopCount.value) {. L# B8 }& u; W0 G& M- w9 y
state.printVal = state.localStart - ((state.localStart - props.end) * (progress / state.localDuration))3 c: K7 b+ ]8 r& l1 I
} else {2 }1 F2 Q) R% q0 Q# d
state.printVal = state.localStart + (props.end - state.localStart) * (progress / state.localDuration)/ v5 F6 j; q7 B. B: y
}/ d$ a/ {: n" f x) \* \; S
}
8 }1 u" h! [+ N" M if (stopCount.value) {
+ G' l* }5 {; v* V state.printVal = state.printVal < props.end ? props.end : state.printVal* L: @6 p: B; ^8 ^. T. Z% M
} else {8 _3 w7 I7 j# H0 L: s, z, \
state.printVal = state.printVal > props.end ? props.end : state.printVal
2 w2 v" ^/ \1 S6 o; X' B }9 u9 t% l0 {8 w( o' W. i0 A
6 J, o. P/ A4 F9 V- P state.displayValue = formatNumber(state.printVal)2 W* j8 X1 J3 ?! J9 S! P
if (progress < state.localDuration) {
8 D" r, l2 m" |7 D9 s% Z! Z" u state.rAF = requestAnimationFrame(count)
, ~% N- x; l. N/ a! T. ?* c } else {1 G4 H& c! z# K" p0 G( k3 z
emits('callback')* a! {; i- a. x/ {) t( s/ |$ U7 `6 j
}
) g1 y7 f0 U2 k* S. I, W$ b}, b( V; Q; n: H" U$ C% Z2 y
// 组件销毁时取消动画
! }' E w7 p7 }. }8 R4 ponUnmounted(() => {
, \% j1 F* U" V0 L, ] cancelAnimationFrame(state.rAF)- T3 N' ]+ W6 z4 m) I
})3 |5 m4 H0 S* B; y7 G
</script>
" T* H- ~9 n0 d/ w' r! R+ x! y
0 E! _% [: B2 M' U1 d1
/ J" A `3 S/ [1 a5 I2; Q7 U3 |" R p# Q& M
3
5 x1 }& [. _4 I, d; r4 E# U! L47 J0 P* w! m1 r* e1 ^
5; p; _; t) s5 g
6) O" X: k D( f4 D; q4 Z+ C
7
( j2 A9 c3 @6 N85 M" T7 U! n% @' B8 e. C
9: i( l7 v% m7 o# R. r
10
4 A: c K9 S- r2 @0 V% G11
0 l0 a2 K- r, C12
8 ?$ w, c" }4 ^4 ^! V3 w3 Y134 s" u' {* \% q' k9 J, i
14# _7 }' \: C/ o1 V3 H2 C
15! u9 D' o, r; i& o% H7 c$ P
16
; s: Y2 Z2 V3 ^6 e" k8 P3 N; `17# j. p( g9 B2 M) o
18
. P8 c3 z; c1 W; d9 i19% c5 C" r- g$ P S& Q0 b& P
20& n/ i7 W% @2 h$ e u
21
" O7 q1 z& z" T8 u r6 Y6 p22
% v% z6 U1 m8 \$ E233 t0 _& o5 `" ^9 Z& I" Q. F
24
1 N* I% F4 d, y, ^2 |25
7 C8 V: \% p2 R& c: f5 O/ H26
( Q2 e5 A6 A: O27( r+ R1 f8 x: i/ w) J
28
, h' W6 N, {9 L4 g! t0 K3 {6 N29
+ J x( f7 t6 m" Q/ P& y30) V, d: a; X! u1 _; a$ S, v
31
8 R9 l& S" r6 E+ ^322 R! U9 c, i' w- O4 [: y5 _: A' N
339 ?0 L3 ~, h7 p' H2 u( G! U. K
34
/ r8 `7 o0 n. V. x. T( p35
; |. y t0 F" B p$ S& h0 z' S36
: m' T: s1 s' g: P9 a; Y1 n37
, a( N- y0 g, w2 ~38
# ^# g7 ~5 x2 p, ~, @. n5 v8 M/ ]39
/ {5 N5 |. t$ q1 [4 T& Q40
; q& _, d. ^1 `& a# ?. z) T/ X41$ b6 ^) ]' M! R( {3 U1 S
427 E5 f- P5 i, Q+ y# u9 `, i) G# V: ^
43
3 j2 e$ V- [: n+ |44# {* v( K# K. `: M* A; }" g
455 q, ^: V0 `4 d! J$ [* v
461 u% v+ i9 ~5 g
47
E/ Z! J3 ^, }4 @2 O# e% ]48: s) ]% e4 F) [% b/ G0 C
49
% b& C1 D3 e* S9 r8 l( J50
, g0 x2 B" V4 [6 `( e6 z: q4 E2 W51! |3 c% k5 P3 h+ z) o
529 e" ^& h5 o9 _: S/ M& b7 `+ V
53
9 M* @8 A- n# S% U54, r- I; Z/ h U- i& C8 T J2 e
55
; C, h0 r4 N3 b6 [0 T565 J; U( t- g6 q
57" k. z# f3 l1 F; M5 x8 R0 O
58) M2 _# `9 q& Z. Y9 Z! Y
59
* @1 s0 Q, F/ E4 k2 p G. R606 K @7 n% A9 h' j# D
61' |0 M4 q8 t6 R, `, }; _: J6 _* l: e6 v8 c
62
; C' ~) v. P- Y2 j" w& r& D63
' |& g' Z' C& S+ P8 Y/ L64
7 C3 P7 D- z1 P, U65# \' T9 v# r4 E8 p/ q# \4 }2 a
66/ n' M% S0 ` U- g
67# }( i9 V' ]9 J, e2 P
68
, u+ K$ O- F6 P5 r6 ~69
1 Z; X/ @# @" @704 N3 R8 h0 b( q2 D) f& U
71
5 J( M- J3 ~3 Z( ?- m8 U3 d72+ L" r0 ?! ~; q. o
73) ]8 L% K( s( j* G- D; L, [
74! d# y) K/ b7 A, ?; o& H
75
7 I$ G. X8 |! K: w# ^6 x76 b1 h4 V+ O2 w5 o- b+ E- T! w! ?
77- M! f5 x! x! G9 c% C; u; w
78
' h4 X' c, A) s: @# ^' w79) O5 k& @2 \" }
80; v5 m9 M" _% w9 Q& E
81+ W3 g8 t- G" j; g! W1 H0 [
82- t; g' ~6 V8 I4 r. D5 z7 g
83& d$ N; b; j' h6 X+ }! s, M" l
84
1 u0 @. v) Q* m$ U8 D. D85
. c; Q& p, ^- s) J86
, Y p& v: U) C/ U5 H% U87
- {8 e( a; M1 |6 R) Y88
. h- P# H) T$ j8 ?$ N89
, y' j% t/ z1 R3 P" Z8 f5 N1 [904 W' l( X0 c" Z8 v
91
4 m1 [3 L+ [% @8 i$ q. B92
) e9 m5 o5 T8 O8 b93
' T5 d0 |/ ?& e3 v8 @94' C: R2 r' g6 b6 z$ g% P
950 q* p( W; |! u; G% ]1 Y
960 K- f- R; ~( T1 d) ]
974 }5 e% N! A7 W) G1 E
98
3 c F! l( f6 Q+ v3 [( m( c; r99/ \/ Y0 P5 S# c, b, e* R1 P
1004 K8 w) B6 s1 y
101" \# b5 C( Y/ U5 W
102( M3 q: n, m. [4 d$ u+ i
1037 { ?' A/ D7 `& V% z; ~+ _
104$ }0 T* m! ]: W6 m) Y% `3 Y
105/ L9 C$ M* z8 [/ x1 }, Q
106
l" T) p* N' t: @$ b7 M107
; E' C( i+ o5 d+ Y) o! p108, y% c" L7 z9 y& w! S% o" {& e" h
109
" m: P6 W/ V* X4 V" \) O7 @9 d110
5 C+ r) C! Z( k9 ?0 [111
# K/ ?/ f! H+ j4 D2 q; V112" _, |) I) Q; a& Y7 k: \) _
113
! v1 u# ^& }, }1 \" n0 G h2 T' \4 J1146 t) v. b" B7 c1 y* K. k
115) E7 T8 ^. M0 O2 e; c9 V
116 a& F, S/ |. }. _4 D
117. m3 ]* r# e8 J" P. s& A ~& b
118
; D& E3 m5 v5 q" ~ ?! D9 b: Y$ x1196 {9 \0 T. I% q, Z6 [5 N0 I- ?
120
* {" ^2 |, c/ K. g1 N8 _1217 {0 C3 g, \9 i, e0 Y8 J& V* X% l
122
/ ?# m( [3 J5 H123# S$ ~! H2 P6 B5 O! O# G
124
: k: I; K) H, P# F' |' W9 P* L+ F125
% i2 h' u5 @" }2 X7 s% p- S126; s' A. ~( G1 X" C7 Q, w& p$ k
127
' N5 U0 @$ j2 }! K0 s# K- W* o, O128
' ]0 \. p/ H$ H8 u1 z129
* Q7 b+ L2 H1 m) u! [! U# ]1303 @' d! v: {, V! @; {
131; ~+ m5 W; m2 g
132
( J- B4 \/ w0 E3 p( p, n& x- j3 H133
) m* ~% m, R. c$ c134' J5 P' B, n) v9 m) R2 c
135
7 a6 F+ }! I) B! B136
$ z% }9 x! F, \- o6 Q137, O1 u" K) u) m% ? w
138
! P W+ S& [1 {0 }139
0 z O# |* C8 A% G( x+ G/ I140* q k+ V+ L+ Q) X+ D" H) l
1417 Q J9 n+ Y! K' W; z
142
9 l' [! j9 Y; ]. f) R/ c143& ~! X5 D9 D7 h. ?$ S7 L* a
144 j9 ~1 ? c9 y' k# G
145( p4 V% I" g) p1 c( L/ N
146
' `2 n# Y6 n, W4 U2 ]" ]147
, d# q. s+ f# U# I148. J& U! }. D' K4 W& d
149. g' Z" e& f7 F. c9 W
150) l# l% C2 _4 W* u% n; C5 ^
151% Y' e# h& o, d9 a5 [
152
: o% Y$ r: r( ~ Z J- I153
L, W( v4 e" F; I) \, B" G154
0 d9 r! I! T" z; c8 h155
2 p6 x- E% y. n0 t+ l, p156
5 P! P) H* M V& Y# \9 v4 Q! k1 ^# b157
7 g5 S0 d$ P: i$ a158: r6 s1 O) ]$ k" k
159# f# H b/ W J9 j, j1 J2 w2 W% R! {" K
160+ J) ^1 L1 b, F- U
161
& _# G4 t$ S {: {1 q6 K162
' D/ w& d5 F1 ]& k" t3 A163
+ G6 E B d ?4 _7 J( Z164' i" {: Z6 n6 d0 r& c& Z' ?/ q( Z
165' X4 i3 F% j0 h% C: }( P0 L( {) n$ h
166' X3 W/ Z) E3 e- h0 I: A; Y" Z
1674 C- R0 I6 S! D; L/ D# _* P2 y
168
2 B1 m$ d" M! n( g* x3 O169% r7 U1 x& `. Q
170
; Y z& r# P9 e& ]1 T' Y171$ H' m3 H% e% }) h* ?% f! F( x
172
( c3 N% H. ?! n; L) |1738 g$ b; H: r, I
174
: X" L2 X0 q1 J7 J' @; ^7 |175
9 f$ x# n) T+ h, Y7 X176
2 K% }2 W4 F/ { C177' D& S$ ?6 X1 G6 U
178
: _! x6 E: D& C4 V2 D179
. J0 S+ D z) A( q180
1 F1 p' M/ r7 K- Z181
/ N9 w& B Z% K; y, `. A182
+ D$ A9 o2 {( c2 X3 ], ]8 a2 Y1 l183
% {% n T2 f V$ r2 }184
: R, Z- W8 e/ y( v6 t# h6 D$ R185" W% j: V7 E$ O+ T/ _# g* C
186+ [! D2 }' ]$ H$ Q- [
187
4 R' F5 E- g+ k1883 ^# K6 l( d: ~/ {
1898 o" I Y8 K8 _; ~* t- J
1908 O1 E, w- w0 i- V' @+ V
191* q; a. R B" V: g' p6 T
192
1 P4 T8 Q$ i* R! y- L193
4 F0 P8 q2 M. f* i: Y4 _$ Y0 ? B194
( a* ~! K8 P# C& B" x' g; X+ {195
8 n# k8 K- @/ F1960 D9 o9 Q/ D" T" ]) H% r6 k; L+ @7 _- v+ A
197
. Q' Q/ A! |6 m# K O1981 [- b, ~5 V9 P% S# T u! d1 Z
199
% {1 K7 q( A m8 q+ u200. ?9 k, t; q. `6 w8 X
201! N- p$ S; r3 c% m
202
- R( K# l& X) t" @; \* d总结
8 H, h5 ~/ e5 S/ t6 I% a( ?1 U自己封装数字动态效果需要注意各个浏览器直接的差异,手动pollyfill,暴露出去的props参数需要有默认值,数据的格式化可以才有正则表达式的方式,组件的驱动必须是数据变化,根据数据来驱动页面渲染,防止页面出现卡顿,不要强行操作dom,引入的组件可以全局配置,后续组件可以服用,码字不易,请各位看官大佬多多支持,一键三连了~❤️❤️❤️
! Q" E+ P* X/ @) l9 H+ B1 T1 T: t1 x1 \: j" J7 P4 D# r5 ]3 J
demo演示
" X* l/ P1 F3 I后续的线上demo演示会放在
: R9 d& w* m) t s6 v8 ldemo演示- `# x* X7 ?4 }3 I+ ?
完整代码会放在
6 D Y" O5 L5 [8 x, K# [个人主页
! j" G7 R) f: M! v' Q: I) K3 T, L. V6 {& Y
希望对vue开发者有所帮助~, m2 q8 q3 @: k, A
4 U& m% r0 U* P4 b
个人简介:承吾
& y7 @; g$ z9 \: t工作年限:5年前端
" {+ u; [% ^6 m2 w# c地区:上海: O! D$ ~% L1 ?# R
个人宣言:立志出好文,传播我所会的,有好东西就及时与大家共享!
" J* D6 L( z# f1 L% b' A0 t- h( {3 u
+ s5 S. a# m, P i5 J# ^
! }( y4 G* j" B, C% s4 `5 t# }6 z K: o
————————————————" p. k' f b: L
版权声明:本文为CSDN博主「KinHKin(五年前端)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
4 y! \. C5 m6 A2 z1 \- O2 ~# {原文链接:https://blog.csdn.net/weixin_42974827/article/details/1268318476 H# g- _! ~1 v; l& T/ s
! O0 W7 I5 j& G6 q, \ q2 f3 `- B( l
% w6 I) c) n- g# x, N$ } |
zan
|