Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
najiu-admin-template
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
najiu-frontend
najiu-admin-template
Commits
87fcd0d2
Commit
87fcd0d2
authored
Nov 01, 2020
by
vben
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: optimize lazy loading components
parent
35d2bfc5
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
180 additions
and
166 deletions
+180
-166
LazyContainer.vue
src/components/Container/src/LazyContainer.vue
+36
-54
types.ts
src/hooks/core/types.ts
+0
-92
useCounter.ts
src/hooks/core/useCounter.ts
+16
-0
useDebounce.ts
src/hooks/core/useDebounce.ts
+18
-5
useThrottle.ts
src/hooks/core/useThrottle.ts
+17
-5
useTimeout.ts
src/hooks/core/useTimeout.ts
+3
-3
useTimeoutRef.ts
src/hooks/core/useTimeoutRef.ts
+2
-3
types.ts
src/hooks/event/types.ts
+0
-1
useEventHub.ts
src/hooks/event/useEventHub.ts
+0
-1
useIntersectionObserver.ts
src/hooks/event/useIntersectionObserver.ts
+48
-0
useNow.ts
src/hooks/event/useNow.ts
+35
-0
useRaf.ts
src/hooks/event/useRaf.ts
+0
-1
useMessage.tsx
src/hooks/web/useMessage.tsx
+5
-1
No files found.
src/components/Container/src/LazyContainer.vue
View file @
87fcd0d2
...
@@ -12,12 +12,21 @@
...
@@ -12,12 +12,21 @@
<
script
lang=
"ts"
>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
PropType
}
from
'
vue
'
;
import
{
defineComponent
,
reactive
,
onMounted
,
ref
,
unref
,
onUnmounted
,
toRefs
}
from
'
vue
'
;
import
{
defineComponent
,
reactive
,
onMounted
,
ref
,
unref
,
onUnmounted
,
toRef
,
toRefs
,
}
from
'
vue
'
;
import
{
Skeleton
}
from
'
ant-design-vue
'
;
import
{
Skeleton
}
from
'
ant-design-vue
'
;
import
{
useRaf
}
from
'
/@/hooks/event/useRaf
'
;
import
{
useRaf
}
from
'
/@/hooks/event/useRaf
'
;
import
{
useTimeout
}
from
'
/@/hooks/core/useTimeout
'
;
import
{
useTimeout
}
from
'
/@/hooks/core/useTimeout
'
;
import
{
useIntersectionObserver
}
from
'
/@/hooks/event/useIntersectionObserver
'
;
interface
State
{
interface
State
{
isInit
:
boolean
;
isInit
:
boolean
;
loading
:
boolean
;
loading
:
boolean
;
...
@@ -30,7 +39,7 @@
...
@@ -30,7 +39,7 @@
// 等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载
// 等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载
timeout
:
{
timeout
:
{
type
:
Number
as
PropType
<
number
>
,
type
:
Number
as
PropType
<
number
>
,
default
:
800
0
,
default
:
0
,
// default: 8000,
// default: 8000,
},
},
// 组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器
// 组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器
...
@@ -40,6 +49,7 @@
...
@@ -40,6 +49,7 @@
>
,
>
,
default
:
()
=>
null
,
default
:
()
=>
null
,
},
},
// 预加载阈值, css单位
// 预加载阈值, css单位
threshold
:
{
threshold
:
{
type
:
String
as
PropType
<
string
>
,
type
:
String
as
PropType
<
string
>
,
...
@@ -51,6 +61,7 @@
...
@@ -51,6 +61,7 @@
type
:
String
as
PropType
<
'
vertical
'
|
'
horizontal
'
>
,
type
:
String
as
PropType
<
'
vertical
'
|
'
horizontal
'
>
,
default
:
'
vertical
'
,
default
:
'
vertical
'
,
},
},
// 包裹组件的外层容器的标签名
// 包裹组件的外层容器的标签名
tag
:
{
tag
:
{
type
:
String
as
PropType
<
string
>
,
type
:
String
as
PropType
<
string
>
,
...
@@ -62,20 +73,14 @@
...
@@ -62,20 +73,14 @@
default
:
80
,
default
:
80
,
},
},
// // 是否在不可见的时候销毁
// autoDestory: {
// type: Boolean as PropType
<
boolean
>
,
// default: false,
// },
// transition name
// transition name
transitionName
:
{
transitionName
:
{
type
:
String
as
PropType
<
string
>
,
type
:
String
as
PropType
<
string
>
,
default
:
'
lazy-container
'
,
default
:
'
lazy-container
'
,
},
},
},
},
emits
:
[
'
before-init
'
,
'
init
'
],
emits
:
[
'
init
'
],
setup
(
props
,
{
emit
,
slots
})
{
setup
(
props
,
{
emit
})
{
const
elRef
=
ref
<
any
>
(
null
);
const
elRef
=
ref
<
any
>
(
null
);
const
state
=
reactive
<
State
>
({
const
state
=
reactive
<
State
>
({
isInit
:
false
,
isInit
:
false
,
...
@@ -83,17 +88,10 @@
...
@@ -83,17 +88,10 @@
intersectionObserverInstance
:
null
,
intersectionObserverInstance
:
null
,
});
});
immediateInit
();
onMounted
(()
=>
{
onMounted
(()
=>
{
immediateInit
();
initIntersectionObserver
();
initIntersectionObserver
();
});
});
onUnmounted
(()
=>
{
// Cancel the observation before the component is destroyed
if
(
state
.
intersectionObserverInstance
)
{
const
el
=
unref
(
elRef
);
state
.
intersectionObserverInstance
.
unobserve
(
el
.
$el
);
}
});
// If there is a set delay time, it will be executed immediately
// If there is a set delay time, it will be executed immediately
function
immediateInit
()
{
function
immediateInit
()
{
...
@@ -105,9 +103,6 @@
...
@@ -105,9 +103,6 @@
}
}
function
init
()
{
function
init
()
{
// At this point, the skeleton component is about to be switched
emit
(
'
before-init
'
);
// At this point you can prepare to load the resources of the lazy-loaded component
state
.
loading
=
true
;
state
.
loading
=
true
;
requestAnimationFrameFn
(()
=>
{
requestAnimationFrameFn
(()
=>
{
...
@@ -120,9 +115,7 @@
...
@@ -120,9 +115,7 @@
// Prevent waiting too long without executing the callback
// Prevent waiting too long without executing the callback
// Set the maximum waiting time
// Set the maximum waiting time
useTimeout
(()
=>
{
useTimeout
(()
=>
{
if
(
state
.
isInit
)
{
if
(
state
.
isInit
)
return
;
return
;
}
callback
();
callback
();
},
props
.
maxWaitingTime
||
80
);
},
props
.
maxWaitingTime
||
80
);
...
@@ -132,12 +125,10 @@
...
@@ -132,12 +125,10 @@
}
}
function
initIntersectionObserver
()
{
function
initIntersectionObserver
()
{
const
{
timeout
,
direction
,
threshold
,
viewport
}
=
props
;
const
{
timeout
,
direction
,
threshold
}
=
props
;
if
(
timeout
)
{
if
(
timeout
)
return
;
return
;
}
// According to the scrolling direction to construct the viewport margin, used to load in advance
// According to the scrolling direction to construct the viewport margin, used to load in advance
let
rootMargin
;
let
rootMargin
:
string
=
'
0px
'
;
switch
(
direction
)
{
switch
(
direction
)
{
case
'
vertical
'
:
case
'
vertical
'
:
rootMargin
=
`
${
threshold
}
0px`
;
rootMargin
=
`
${
threshold
}
0px`
;
...
@@ -146,34 +137,25 @@
...
@@ -146,34 +137,25 @@
rootMargin
=
`0px
${
threshold
}
`
;
rootMargin
=
`0px
${
threshold
}
`
;
break
;
break
;
}
}
try
{
try
{
// Observe the intersection of the viewport and the component container
const
{
stop
,
observer
}
=
useIntersectionObserver
({
state
.
intersectionObserverInstance
=
new
window
.
IntersectionObserver
(
intersectionHandler
,
{
rootMargin
,
rootMargin
,
root
:
viewport
,
target
:
toRef
(
elRef
.
value
,
'
$el
'
),
threshold
:
[
0
,
Number
.
MIN_VALUE
,
0.01
],
onIntersect
:
(
entries
:
any
[])
=>
{
}
);
const
el
=
unref
(
elRef
);
state
.
intersectionObserverInstance
.
observe
(
el
.
$el
);
}
catch
(
e
)
{
init
();
}
}
// Cross-condition change handling function
function
intersectionHandler
(
entries
:
any
[])
{
const
isIntersecting
=
entries
[
0
].
isIntersecting
||
entries
[
0
].
intersectionRatio
;
const
isIntersecting
=
entries
[
0
].
isIntersecting
||
entries
[
0
].
intersectionRatio
;
if
(
isIntersecting
)
{
if
(
isIntersecting
)
{
init
();
init
();
if
(
state
.
intersectionObserverInstance
)
{
if
(
observer
)
{
const
el
=
unref
(
elRef
);
stop
();
state
.
intersectionObserverInstance
.
unobserve
(
el
.
$el
);
}
}
}
}
},
root
:
toRef
(
props
,
'
viewport
'
),
});
}
catch
(
e
)
{
init
();
}
}
}
return
{
return
{
elRef
,
elRef
,
...
...
src/hooks/core/types.ts
deleted
100644 → 0
View file @
35d2bfc5
import
type
{
VNode
,
Ref
}
from
'
vue
'
;
import
type
{
ModalFuncProps
}
from
'
ant-design-vue/lib/modal/index
'
;
export
type
Fn
<
T
>
=
()
=>
T
;
export
type
AnyFn
<
T
>
=
(...
arg
:
any
)
=>
T
;
export
type
PromiseFn
<
T
>
=
(...
arg
:
any
)
=>
Promise
<
T
>
;
export
type
CancelFn
=
()
=>
void
;
export
interface
DebounceAndThrottleOptions
{
// 立即执行
immediate
?:
boolean
;
// 是否为debounce
debounce
?:
boolean
;
// 只执行一次
once
?:
boolean
;
}
export
type
DebounceAndThrottleProcedure
<
T
extends
unknown
[]
>
=
(...
args
:
T
)
=>
unknown
;
export
type
DebounceAndThrottleProcedureResult
<
T
extends
unknown
[]
>
=
[
DebounceAndThrottleProcedure
<
T
>
,
CancelFn
];
export
type
TimeoutResult
=
[
Ref
<
boolean
>
,
Fn
<
void
>
,
Fn
<
void
>
];
export
type
TimeoutFnResult
=
[
Fn
<
void
>
,
Fn
<
void
>
,
Ref
<
boolean
>
];
export
interface
PromiseState
{
loading
:
boolean
;
error
:
Error
|
null
;
result
:
any
;
done
:
boolean
;
}
export
type
MessageType
=
'
success
'
|
'
warning
'
|
'
info
'
|
'
error
'
;
export
interface
CloseEventHandler
{
/**
* Triggers when a message is being closed
*
* @param instance The message component that is being closed
*/
(
instance
:
MessageComponent
):
void
;
}
/** Message Component */
export
declare
class
MessageComponent
{
/** Close the Loading instance */
close
():
void
;
}
export
type
MessageMethods
=
{
[
key
in
MessageType
]?:
(
options
:
MessageOptions
|
string
)
=>
MessageComponent
;
// Note that "key in".
};
/** Options used in Message */
export
interface
MessageOptions
{
title
:
string
;
/** Message text */
message
:
string
|
VNode
;
/** Message type */
type
?:
MessageType
;
/** Custom icon's class, overrides type */
iconClass
?:
string
;
/** Custom class name for Message */
customClass
?:
string
;
/** Display duration, millisecond. If set to 0, it will not turn off automatically */
duration
?:
number
;
/** Whether to show a close button */
showClose
?:
boolean
;
/** Whether to center the text */
center
?:
boolean
;
/** Whether message is treated as HTML string */
dangerouslyUseHTMLString
?:
boolean
;
/** Callback function when closed with the message instance as the parameter */
onClose
?:
CloseEventHandler
;
/** Set the distance to the top of viewport. Default is 20 px. */
offset
?:
number
;
}
export
interface
ModalOptionsEx
extends
Omit
<
ModalFuncProps
,
'
iconType
'
>
{
iconType
:
'
warning
'
|
'
success
'
|
'
error
'
|
'
info
'
;
}
export
type
ModalOptionsPartial
=
Partial
<
ModalOptionsEx
>
&
Pick
<
ModalOptionsEx
,
'
content
'
>
;
src/hooks/core/useCounter.ts
0 → 100644
View file @
87fcd0d2
import
{
ref
}
from
'
vue
'
;
export
function
useCounter
(
initialValue
=
0
)
{
const
count
=
ref
(
initialValue
);
const
inc
=
(
delta
=
1
)
=>
(
count
.
value
+=
delta
);
const
dec
=
(
delta
=
1
)
=>
(
count
.
value
-=
delta
);
const
get
=
()
=>
count
.
value
;
const
set
=
(
val
:
number
)
=>
(
count
.
value
=
val
);
const
reset
=
(
val
=
initialValue
)
=>
{
initialValue
=
val
;
return
set
(
val
);
};
return
{
count
,
inc
,
dec
,
get
,
set
,
reset
};
}
src/hooks/core/useDebounce.ts
View file @
87fcd0d2
import
type
{
export
interface
DebounceAndThrottleOptions
{
DebounceAndThrottleOptions
,
// 立即执行
DebounceAndThrottleProcedureResult
,
immediate
?:
boolean
;
DebounceAndThrottleProcedure
,
}
from
'
./types
'
;
// 是否为debounce
debounce
?:
boolean
;
// 只执行一次
once
?:
boolean
;
}
export
type
CancelFn
=
()
=>
void
;
export
type
DebounceAndThrottleProcedure
<
T
extends
unknown
[]
>
=
(...
args
:
T
)
=>
unknown
;
export
type
DebounceAndThrottleProcedureResult
<
T
extends
unknown
[]
>
=
[
DebounceAndThrottleProcedure
<
T
>
,
CancelFn
];
import
{
import
{
// throttle,
// throttle,
useThrottle
,
useThrottle
,
...
...
src/hooks/core/useThrottle.ts
View file @
87fcd0d2
import
type
{
export
interface
DebounceAndThrottleOptions
{
DebounceAndThrottleOptions
,
// 立即执行
DebounceAndThrottleProcedureResult
,
immediate
?:
boolean
;
DebounceAndThrottleProcedure
,
}
from
'
./types
'
;
// 是否为debounce
debounce
?:
boolean
;
// 只执行一次
once
?:
boolean
;
}
export
type
CancelFn
=
()
=>
void
;
export
type
DebounceAndThrottleProcedure
<
T
extends
unknown
[]
>
=
(...
args
:
T
)
=>
unknown
;
export
type
DebounceAndThrottleProcedureResult
<
T
extends
unknown
[]
>
=
[
DebounceAndThrottleProcedure
<
T
>
,
CancelFn
];
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
export
function
throttle
<
T
extends
unknown
[]
>
(
export
function
throttle
<
T
extends
unknown
[]
>
(
...
...
src/hooks/core/useTimeout.ts
View file @
87fcd0d2
import
type
{
TimeoutFnResult
,
Fn
}
from
'
./types
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
watch
}
from
'
vue
'
;
import
{
Ref
,
watch
}
from
'
vue
'
;
import
{
useTimeoutRef
}
from
'
/@/hooks/core/useTimeoutRef
'
;
import
{
useTimeoutRef
}
from
'
/@/hooks/core/useTimeoutRef
'
;
type
TimeoutFnResult
=
[
Fn
<
void
>
,
Fn
<
void
>
,
Ref
<
boolean
>
];
export
function
useTimeout
(
handle
:
Fn
<
any
>
,
wait
:
number
):
TimeoutFnResult
{
export
function
useTimeout
(
handle
:
Fn
<
any
>
,
wait
:
number
):
TimeoutFnResult
{
if
(
!
isFunction
(
handle
))
{
if
(
!
isFunction
(
handle
))
{
throw
new
Error
(
'
handle is not Function!
'
);
throw
new
Error
(
'
handle is not Function!
'
);
...
...
src/hooks/core/useTimeoutRef.ts
View file @
87fcd0d2
import
type
{
TimeoutResult
}
from
'
./types
'
;
import
{
Ref
,
ref
}
from
'
vue
'
;
import
{
ref
}
from
'
vue
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
export
type
TimeoutResult
=
[
Ref
<
boolean
>
,
Fn
<
void
>
,
Fn
<
void
>
];
export
function
useTimeoutRef
(
wait
:
number
):
TimeoutResult
{
export
function
useTimeoutRef
(
wait
:
number
):
TimeoutResult
{
const
readyRef
=
ref
(
false
);
const
readyRef
=
ref
(
false
);
...
...
src/hooks/event/types.ts
deleted
100644 → 0
View file @
35d2bfc5
export
type
Fn
<
T
>
=
()
=>
T
;
src/hooks/event/useEventHub.ts
View file @
87fcd0d2
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
import
{}
from
'
vue
'
;
import
EventHub
from
'
/@/utils/eventHub
'
;
import
EventHub
from
'
/@/utils/eventHub
'
;
const
eventHub
=
new
EventHub
();
const
eventHub
=
new
EventHub
();
export
function
useEventHub
():
EventHub
{
export
function
useEventHub
():
EventHub
{
...
...
src/hooks/event/useIntersectionObserver.ts
0 → 100644
View file @
87fcd0d2
import
{
Ref
,
watchEffect
,
ref
}
from
'
vue
'
;
interface
IntersectionObserverProps
{
target
:
Ref
<
Element
|
null
|
undefined
>
;
root
?:
Ref
<
Element
|
null
|
undefined
>
;
onIntersect
:
IntersectionObserverCallback
;
rootMargin
?:
string
;
threshold
?:
number
;
}
export
function
useIntersectionObserver
({
target
,
root
,
onIntersect
,
rootMargin
=
'
0px
'
,
threshold
=
0.1
,
}:
IntersectionObserverProps
)
{
let
cleanup
=
()
=>
{};
const
observer
:
Ref
<
Nullable
<
IntersectionObserver
>>
=
ref
(
null
);
const
stopEffect
=
watchEffect
(()
=>
{
cleanup
();
observer
.
value
=
new
IntersectionObserver
(
onIntersect
,
{
root
:
root
?
root
.
value
:
null
,
rootMargin
,
threshold
,
});
const
current
=
target
.
value
;
current
&&
observer
.
value
.
observe
(
current
);
cleanup
=
()
=>
{
if
(
observer
.
value
)
{
observer
.
value
.
disconnect
();
target
.
value
&&
observer
.
value
.
unobserve
(
target
.
value
);
}
};
});
return
{
observer
,
stop
:
()
=>
{
cleanup
();
stopEffect
();
},
};
}
src/hooks/event/useNow.ts
0 → 100644
View file @
87fcd0d2
import
{
ref
}
from
'
vue
'
;
import
{
tryOnUnmounted
}
from
'
/@/utils/helper/vueHelper
'
;
function
getTimestamp
()
{
return
+
Date
.
now
();
}
export
function
useNow
()
{
const
now
=
ref
(
getTimestamp
());
let
started
=
false
;
const
update
=
()
=>
{
requestAnimationFrame
(()
=>
{
now
.
value
=
getTimestamp
();
if
(
started
)
update
();
});
};
const
start
=
()
=>
{
if
(
!
started
)
{
started
=
true
;
update
();
}
};
const
stop
=
()
=>
{
started
=
false
;
};
start
();
tryOnUnmounted
(
stop
);
return
now
;
}
src/hooks/event/useRaf.ts
View file @
87fcd0d2
...
@@ -49,7 +49,6 @@ if (isServer) {
...
@@ -49,7 +49,6 @@ if (isServer) {
};
};
}
}
}
}
export
function
useRaf
()
{
export
function
useRaf
()
{
// if (getCurrentInstance()) {
// if (getCurrentInstance()) {
// onUnmounted(() => {
// onUnmounted(() => {
...
...
src/hooks/web/useMessage.tsx
View file @
87fcd0d2
import
type
{
ModalOptionsEx
,
ModalOptionsPartial
}
from
'
/@/hooks/core/types
'
;
import
type
{
ModalFunc
,
ModalFuncProps
}
from
'
ant-design-vue/lib/modal/Modal
'
;
import
type
{
ModalFunc
,
ModalFuncProps
}
from
'
ant-design-vue/lib/modal/Modal
'
;
import
{
Modal
,
message
as
Message
,
notification
}
from
'
ant-design-vue
'
;
import
{
Modal
,
message
as
Message
,
notification
}
from
'
ant-design-vue
'
;
...
@@ -6,6 +5,11 @@ import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-des
...
@@ -6,6 +5,11 @@ import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-des
import
{
useSetting
}
from
'
/@/hooks/core/useSetting
'
;
import
{
useSetting
}
from
'
/@/hooks/core/useSetting
'
;
export
interface
ModalOptionsEx
extends
Omit
<
ModalFuncProps
,
'
iconType
'
>
{
iconType
:
'
warning
'
|
'
success
'
|
'
error
'
|
'
info
'
;
}
export
type
ModalOptionsPartial
=
Partial
<
ModalOptionsEx
>
&
Pick
<
ModalOptionsEx
,
'
content
'
>
;
interface
ConfirmOptions
{
interface
ConfirmOptions
{
info
:
ModalFunc
;
info
:
ModalFunc
;
success
:
ModalFunc
;
success
:
ModalFunc
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment