Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
fdeaa00b
提交
fdeaa00b
authored
10月 26, 2020
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: add lazyContainer comp and demo
上级
a0c31974
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
162 行增加
和
99 行删除
+162
-99
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+1
-0
index.ts
src/components/Container/index.ts
+1
-1
LazyContainer.less
src/components/Container/src/LazyContainer.less
+0
-27
LazyContainer.vue
src/components/Container/src/LazyContainer.vue
+83
-70
comp.ts
src/router/menus/modules/demo/comp.ts
+4
-0
comp.ts
src/router/routes/modules/demo/comp.ts
+8
-1
TargetContent.vue
src/views/demo/comp/lazy/TargetContent.vue
+19
-0
index.vue
src/views/demo/comp/lazy/index.vue
+46
-0
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
fdeaa00b
...
...
@@ -8,6 +8,7 @@
-
表单新增 submitOnReset 控制是否在重置时重新发起请求
-
表格新增
`sortFn`
支持自定义排序
-
新增动画组件及示例
-
新增懒加载/延时加载组件及示例
### ✨ Refactor
...
...
src/components/Container/index.ts
浏览文件 @
fdeaa00b
export
{
default
as
ScrollContainer
}
from
'./src/ScrollContainer.vue'
;
export
{
default
as
CollapseContainer
}
from
'./src/collapse/CollapseContainer.vue'
;
export
{
default
as
LazyContainer
}
from
'./src/LazyContainer'
;
export
{
default
as
LazyContainer
}
from
'./src/LazyContainer
.vue
'
;
export
*
from
'./src/types.d'
;
src/components/Container/src/LazyContainer.less
deleted
100644 → 0
浏览文件 @
a0c31974
.lazy-container-enter {
opacity: 0;
}
.lazy-container-enter-to {
opacity: 1;
}
.lazy-container-enter-from,
.lazy-container-enter-active {
position: absolute;
top: 0;
width: 100%;
transition: opacity 0.3s 0.2s;
}
.lazy-container-leave {
opacity: 1;
}
.lazy-container-leave-to {
opacity: 0;
}
.lazy-container-leave-active {
transition: opacity 0.5s;
}
src/components/Container/src/LazyContainer.
tsx
→
src/components/Container/src/LazyContainer.
vue
浏览文件 @
fdeaa00b
import
type
{
PropType
}
from
'vue'
;
import
{
defineComponent
,
reactive
,
onMounted
,
ref
,
unref
,
onUnmounted
,
TransitionGroup
,
}
from
'vue'
;
import
{
Skeleton
}
from
'ant-design-vue'
;
import
{
useRaf
}
from
'/@/hooks/event/useRaf'
;
import
{
useTimeout
}
from
'/@/hooks/core/useTimeout'
;
import
{
getListeners
,
getSlot
}
from
'/@/utils/helper/tsxHelper'
;
import
'./LazyContainer.less'
;
interface
State
{
<
template
>
<transition-group
v-bind=
"$attrs"
ref=
"elRef"
:name=
"transitionName"
:tag=
"tag"
>
<div
key=
"component"
v-if=
"isInit"
>
<slot
:loading=
"loading"
/>
</div>
<div
key=
"skeleton"
>
<slot
name=
"skeleton"
v-if=
"$slots.skeleton"
/>
<Skeleton
v-else
/>
</div>
</transition-group>
</
template
>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'vue'
;
import
{
defineComponent
,
reactive
,
onMounted
,
ref
,
unref
,
onUnmounted
,
toRefs
}
from
'vue'
;
import
{
Skeleton
}
from
'ant-design-vue'
;
import
{
useRaf
}
from
'/@/hooks/event/useRaf'
;
import
{
useTimeout
}
from
'/@/hooks/core/useTimeout'
;
interface
State
{
isInit
:
boolean
;
loading
:
boolean
;
intersectionObserverInstance
:
IntersectionObserver
|
null
;
}
export
default
defineComponent
({
}
export
default
defineComponent
({
name
:
'LazyContainer'
,
emits
:
[
'before-init'
,
'init'
]
,
components
:
{
Skeleton
}
,
props
:
{
// 等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载
timeout
:
{
...
...
@@ -34,7 +35,9 @@ export default defineComponent({
},
// 组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器
viewport
:
{
type
:
(
typeof
window
!==
'undefined'
?
window
.
HTMLElement
:
Object
)
as
PropType
<
HTMLElement
>
,
type
:
(
typeof
window
!==
'undefined'
?
window
.
HTMLElement
:
Object
)
as
PropType
<
HTMLElement
>
,
default
:
()
=>
null
,
},
// 预加载阈值, css单位
...
...
@@ -59,11 +62,11 @@ export default defineComponent({
default
:
80
,
},
// 是否在不可见的时候销毁
autoDestory
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
//
// 是否在不可见的时候销毁
//
autoDestory: {
//
type: Boolean as PropType
<
boolean
>
,
//
default: false,
//
},
// transition name
transitionName
:
{
...
...
@@ -71,7 +74,8 @@ export default defineComponent({
default
:
'lazy-container'
,
},
},
setup
(
props
,
{
attrs
,
emit
,
slots
})
{
emits
:
[
'before-init'
,
'init'
],
setup
(
props
,
{
emit
,
slots
})
{
const
elRef
=
ref
<
any
>
(
null
);
const
state
=
reactive
<
State
>
({
isInit
:
false
,
...
...
@@ -79,6 +83,18 @@ export default defineComponent({
intersectionObserverInstance
:
null
,
});
immediateInit
();
onMounted
(()
=>
{
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
function
immediateInit
()
{
const
{
timeout
}
=
props
;
...
...
@@ -99,6 +115,7 @@ export default defineComponent({
emit
(
'init'
);
});
}
function
requestAnimationFrameFn
(
callback
:
()
=>
any
)
{
// Prevent waiting too long without executing the callback
// Set the maximum waiting time
...
...
@@ -113,6 +130,7 @@ export default defineComponent({
return
requestAnimationFrame
;
}
function
initIntersectionObserver
()
{
const
{
timeout
,
direction
,
threshold
,
viewport
}
=
props
;
if
(
timeout
)
{
...
...
@@ -130,11 +148,14 @@ export default defineComponent({
}
try
{
// Observe the intersection of the viewport and the component container
state
.
intersectionObserverInstance
=
new
window
.
IntersectionObserver
(
intersectionHandler
,
{
state
.
intersectionObserverInstance
=
new
window
.
IntersectionObserver
(
intersectionHandler
,
{
rootMargin
,
root
:
viewport
,
threshold
:
[
0
,
Number
.
MIN_VALUE
,
0.01
],
});
}
);
const
el
=
unref
(
elRef
);
...
...
@@ -153,48 +174,40 @@ export default defineComponent({
state
.
intersectionObserverInstance
.
unobserve
(
el
.
$el
);
}
}
// else {
// const { autoDestory } = props;
// autoDestory && destory();
// }
}
// function destory() {
// emit('beforeDestory');
// state.loading = false;
// nextTick(() => {
// emit('destory');
// });
// }
immediateInit
();
onMounted
(()
=>
{
initIntersectionObserver
();
return
{
elRef
,
...
toRefs
(
state
),
};
},
});
onUnmounted
(()
=>
{
// Cancel the observation before the component is destroyed
if
(
state
.
intersectionObserverInstance
)
{
const
el
=
unref
(
elRef
);
state
.
intersectionObserverInstance
.
unobserve
(
el
.
$el
);
</
script
>
<
style
lang=
"less"
>
.lazy-container-enter
{
opacity
:
0
;
}
});
function
renderContent
()
{
const
{
isInit
,
loading
}
=
state
;
if
(
isInit
)
{
return
<
div
key=
"component"
>
{
getSlot
(
slots
,
'default'
,
{
loading
})
}
</
div
>;
.lazy-container-enter-to
{
opacity
:
1
;
}
if
(
slots
.
skeleton
)
{
return
<
div
key=
"skeleton"
>
{
getSlot
(
slots
,
'skeleton'
)
||
<
Skeleton
/>
}
</
div
>;
.lazy-container-enter-from
,
.lazy-container-enter-active
{
position
:
absolute
;
top
:
0
;
width
:
100%
;
transition
:
opacity
0.3s
0.2s
;
}
return
null
;
.lazy-container-leave
{
opacity
:
1
;
}
return
()
=>
{
const
{
tag
,
transitionName
}
=
props
;
return
(
<
TransitionGroup
ref=
{
elRef
}
name=
{
transitionName
}
tag=
{
tag
}
{
...
getListeners
(
attrs
)}
>
{
()
=>
renderContent
()
}
</
TransitionGroup
>
);
};
},
});
.lazy-container-leave-to
{
opacity
:
0
;
}
.lazy-container-leave-active
{
transition
:
opacity
0.5s
;
}
</
style
>
src/router/menus/modules/demo/comp.ts
浏览文件 @
fdeaa00b
...
...
@@ -49,6 +49,10 @@ const menu: MenuModule = {
name
:
'详情组件'
,
},
{
path
:
'lazy'
,
name
:
'懒加载组件'
,
},
{
path
:
'verify'
,
name
:
'验证组件'
,
children
:
[
...
...
src/router/routes/modules/demo/comp.ts
浏览文件 @
fdeaa00b
...
...
@@ -99,7 +99,14 @@ export default {
title
:
'详情组件'
,
},
},
{
path
:
'/lazy'
,
name
:
'lazyDemo'
,
component
:
()
=>
import
(
'/@/views/demo/comp/lazy/index.vue'
),
meta
:
{
title
:
'懒加载组件'
,
},
},
{
path
:
'/verify'
,
name
:
'VerifyDemo'
,
...
...
src/views/demo/comp/lazy/TargetContent.vue
0 → 100644
浏览文件 @
fdeaa00b
<
template
>
<Card
hoverable
:style=
"
{ width: '240px', background: '#fff' }">
<template
#
cover
>
<img
alt=
"example"
src=
"https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png"
/>
</
template
>
<CardMeta
title=
"懒加载组件"
/>
</Card>
</template>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'vue'
;
import
{
Card
}
from
'ant-design-vue'
;
export
default
defineComponent
({
components
:
{
CardMeta
:
Card
.
Meta
,
Card
},
setup
()
{
return
{};
},
});
</
script
>
src/views/demo/comp/lazy/index.vue
0 → 100644
浏览文件 @
fdeaa00b
<
template
>
<div
class=
"p-4 lazy-base-demo"
>
<Alert
message=
"基础示例"
description=
"向下滚动到可见区域才会加载组件"
type=
"info"
show-icon
/>
<div
class=
"lazy-base-demo-wrap"
>
<h1>
向下滚动
</h1>
<LazyContainer
@
init=
"() =>
{}">
<TargetContent
/>
<template
#
skeleton
>
<Skeleton
:rows=
"10"
/>
</
template
>
</LazyContainer>
</div>
</div>
</template>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'vue'
;
import
{
Skeleton
,
Alert
}
from
'ant-design-vue'
;
import
TargetContent
from
'./TargetContent.vue'
;
import
{
LazyContainer
}
from
'/@/components/Container/index'
;
export
default
defineComponent
({
components
:
{
LazyContainer
,
TargetContent
,
Skeleton
,
Alert
},
setup
()
{
return
{};
},
});
</
script
>
<
style
lang=
"less"
scoped
>
.lazy-base-demo
{
&-wrap
{
display
:
flex
;
width
:
50%
;
height
:
2000px
;
margin
:
20px
auto
;
text-align
:
center
;
background
:
#fff
;
justify-content
:
center
;
flex-direction
:
column
;
align-items
:
center
;
}
h1
{
height
:
1300px
;
margin
:
20px
0
;
}
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论