Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
京东前端
nutui
提交
caa64662
N
nutui
项目概览
京东前端
/
nutui
通知
37
Star
4
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
nutui
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
caa64662
编写于
2月 08, 2021
作者:
Y
yangxiaolu3
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: pullrefresh 纵向
上级
ca1e7172
变更
9
显示空白变更内容
内联
并排
Showing
9 changed file
with
506 addition
and
0 deletion
+506
-0
src/config.js
src/config.js
+10
-0
src/packages/pullrefresh/demo.vue
src/packages/pullrefresh/demo.vue
+61
-0
src/packages/pullrefresh/doc.md
src/packages/pullrefresh/doc.md
+34
-0
src/packages/pullrefresh/index.css
src/packages/pullrefresh/index.css
+43
-0
src/packages/pullrefresh/index.min.css
src/packages/pullrefresh/index.min.css
+1
-0
src/packages/pullrefresh/index.scss
src/packages/pullrefresh/index.scss
+43
-0
src/packages/pullrefresh/index.vue
src/packages/pullrefresh/index.vue
+231
-0
src/packages/pullrefresh/use-touch.ts
src/packages/pullrefresh/use-touch.ts
+69
-0
src/packages/pullrefresh/util.ts
src/packages/pullrefresh/util.ts
+14
-0
未找到文件。
src/config.js
浏览文件 @
caa64662
...
...
@@ -313,6 +313,16 @@ module.exports = {
sort
:
15
,
show
:
true
,
author
:
'
yangxiaolu
'
},
{
version
:
'
3.0.0
'
,
name
:
'
PullRefresh
'
,
type
:
'
component
'
,
cName
:
'
下拉刷新
'
,
desc
:
'
下拉刷新
'
,
sort
:
16
,
show
:
true
,
author
:
'
yangxiaolu3
'
}
]
},
...
...
src/packages/pullrefresh/demo.vue
0 → 100644
浏览文件 @
caa64662
<
template
>
<div
class=
"demo"
>
<nut-pullrefresh
@
refresh=
"refresh"
:useWindow=
"false"
containerId=
"pull"
>
<div
class=
"content"
id=
"pull"
>
<div
class=
"main"
>
<div
class=
"text-data"
>
我是测试数据1
</div>
<div
class=
"text-data"
>
我是测试数据2
</div>
<div
class=
"text-data"
>
我是测试数据3
</div>
<div
class=
"text-data"
>
我是测试数据4
</div>
<div
class=
"text-data"
>
我是测试数据5
</div>
<div
class=
"text-data"
>
我是测试数据6
</div>
<div
class=
"text-data"
>
我是测试数据7
</div>
<div
class=
"text-data"
>
我是测试数据8
</div>
<div
class=
"text-data"
>
我是测试数据9
</div>
<div
class=
"text-data"
>
我是测试数据10
</div>
<div
class=
"text-data"
>
我是测试数据11
</div>
<div
class=
"text-data"
>
我是测试数据12
</div>
<div
class=
"text-data"
>
我是测试数据13
</div>
<div
class=
"text-data"
>
我是测试数据14
</div>
<div
class=
"text-data"
>
我是测试数据15
</div>
<div
class=
"text-data"
>
我是测试数据16
</div>
<div
class=
"text-data"
>
我是测试数据17
</div>
<div
class=
"text-data"
>
我是测试数据18
</div>
<div
class=
"text-data"
>
我是测试数据19
</div>
<div
class=
"text-data"
>
我是测试数据20
</div>
<div
class=
"text-data"
>
我是测试数据21
</div>
<div
class=
"text-data"
>
我是测试数据22
</div>
<div
class=
"text-data"
>
我是测试数据23
</div>
<div
class=
"text-data"
>
我是测试数据24
</div>
</div>
</div>
</nut-pullrefresh>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
createComponent
}
from
'
@/utils/create
'
;
const
{
createDemo
}
=
createComponent
(
'
pullrefresh
'
);
export
default
createDemo
({
props
:
{},
setup
()
{
const
refresh
=
done
=>
{
setTimeout
(()
=>
{
done
();
},
1000
);
};
return
{
refresh
};
}
});
</
script
>
<
style
lang=
"scss"
scoped
>
.content
{
height
:
100%
;
overflow
:
auto
;
.main
{
padding
:
10px
0
;
background
:
#f00
;
}
}
</
style
>
src/packages/pullrefresh/doc.md
0 → 100644
浏览文件 @
caa64662
# pullrefresh组件
### 介绍
基于 xxxxxxx
### 安装
## 代码演示
### 基础用法1
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 '20px' '2em' '2rem' | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | 'nutui-iconfont' |
| tag | HTML 标签 | String | 'i' |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
\ No newline at end of file
src/packages/pullrefresh/index.css
0 → 100644
浏览文件 @
caa64662
view
{
display
:
block
;
}
.nut-pullrefresh
{
position
:
relative
;
height
:
100%
;
}
.nut-pullrefresh
.pullrefresh-top
{
position
:
absolute
;
left
:
0
;
width
:
100%
;
height
:
50px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
-100%
);
transform
:
translateY
(
-100%
);
}
.nut-pullrefresh
.pullrefresh-content
{
height
:
100%
;
overflow
:
auto
;
background
:
#fff
;
}
.nut-pullrefresh
.pullrefresh-bottom
{
position
:
absolute
;
left
:
0
;
bottom
:
0
;
width
:
100%
;
height
:
0px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
100%
);
transform
:
translateY
(
100%
);
}
src/packages/pullrefresh/index.min.css
0 → 100644
浏览文件 @
caa64662
view
{
display
:
block
}
.nut-pullrefresh
{
position
:
relative
;
height
:
100%
}
.nut-pullrefresh
.pullrefresh-top
{
position
:
absolute
;
left
:
0
;
width
:
100%
;
height
:
50px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
-100%
);
transform
:
translateY
(
-100%
)}
.nut-pullrefresh
.pullrefresh-content
{
height
:
100%
;
overflow
:
auto
;
background
:
#fff
}
.nut-pullrefresh
.pullrefresh-bottom
{
position
:
absolute
;
left
:
0
;
bottom
:
0
;
width
:
100%
;
height
:
0px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
100%
);
transform
:
translateY
(
100%
)}
src/packages/pullrefresh/index.scss
0 → 100644
浏览文件 @
caa64662
view
{
display
:
block
;
}
.nut-pullrefresh
{
position
:
relative
;
height
:
100%
;
.pullrefresh-top
{
position
:
absolute
;
left
:
0
;
width
:
100%
;
height
:
50px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
-100%
);
transform
:
translateY
(
-100%
);
}
.pullrefresh-content
{
height
:
100%
;
overflow
:
auto
;
background
:
#fff
;
}
.pullrefresh-bottom
{
position
:
absolute
;
left
:
0
;
bottom
:
0
;
width
:
100%
;
height
:
0px
;
overflow
:
hidden
;
color
:
#969799
;
font-size
:
14px
;
line-height
:
50px
;
text-align
:
center
;
-webkit-transform
:
translateY
(
100%
);
transform
:
translateY
(
100%
);
}
}
src/packages/pullrefresh/index.vue
0 → 100644
浏览文件 @
caa64662
<
template
>
<view
class=
"nut-pullrefresh"
ref=
"scroller"
:style=
"getStyle"
@
touchstart=
"touchStart"
@
touchmove=
"touchMove"
@
touchend=
"touchEnd"
>
<view
class=
"pullrefresh-top"
>
<template
v-if=
"status == 'loading' && reachTop && distance > 0"
>
加载中...
</
template
>
<
template
v-if=
"status == 'pulling' && reachTop && distance > 0"
>
下拉刷新...
</
template
>
<
template
v-if=
"status == 'loosing' && reachTop && distance > 0"
>
释放刷新...
</
template
>
</view>
<view
class=
"pullrefresh-content"
ref=
"pull"
>
<slot></slot>
</view>
<view
class=
"pullrefresh-bottom"
:style=
"getBottomStyle"
>
<
template
v-if=
"status == 'loading' && reachBottom && distance < 0"
>
加载中...
</
template
>
<
template
v-if=
"status == 'pulling' && reachBottom && distance < 0"
>
下拉刷新...
</
template
>
<
template
v-if=
"status == 'loosing' && reachBottom && distance < 0"
>
释放刷新...
</
template
>
</view>
</view>
</template>
<
script
lang=
"ts"
>
import
{
ref
,
toRefs
,
reactive
,
onMounted
,
computed
,
CSSProperties
}
from
'
vue
'
;
import
{
createComponent
}
from
'
@/utils/create
'
;
import
{
useTouch
}
from
'
./use-touch
'
;
import
{
preventDefault
}
from
'
./util
'
;
const
{
componentName
,
create
}
=
createComponent
(
'
pullrefresh
'
);
export
default
create
({
props
:
{
useWindow
:
{
type
:
Boolean
,
default
:
true
},
containerId
:
{
type
:
String
,
default
:
''
}
},
components
:
{},
emits
:
[
'
refresh
'
],
setup
(
props
,
{
emit
})
{
console
.
log
(
'
componentName
'
,
componentName
);
const
{
containerId
,
useWindow
}
=
toRefs
(
props
);
const
reachTop
=
ref
(
false
);
const
reachBottom
=
ref
(
false
);
const
state
=
reactive
({
status
:
'
normal
'
,
distance
:
0
,
duration
:
0
});
let
scrollEl
:
HTMLElement
=
document
.
documentElement
||
document
.
body
;
const
scroller
=
ref
<
null
|
HTMLElement
>
(
null
);
const
touch
=
useTouch
();
const
getStyle
=
computed
(()
=>
{
let
style
:
CSSProperties
=
{};
if
(
(
reachTop
.
value
&&
touch
.
deltaY
.
value
>
0
&&
touch
.
isVertical
())
||
(
reachBottom
.
value
&&
touch
.
deltaY
.
value
<
0
&&
touch
.
isVertical
())
)
{
style
=
{
transitionDuration
:
`
${
state
.
duration
}
ms`
,
transform
:
state
.
distance
?
`translate3d(0,
${
state
.
distance
}
px, 0)`
:
`translate3d(0,0,0)`
};
}
return
style
;
});
const
getBottomStyle
=
computed
(()
=>
{
let
style
:
CSSProperties
=
{};
if
(
reachBottom
.
value
&&
touch
.
deltaY
.
value
<
0
&&
touch
.
isVertical
())
{
const
dis
=
Math
.
abs
(
state
.
distance
)
<
50
?
-
state
.
distance
:
50
;
style
=
{
height
:
dis
+
'
px
'
};
}
return
style
;
});
const
setStatus
=
(
distance
:
number
,
isLoading
?:
boolean
)
=>
{
state
.
distance
=
distance
;
if
(
isLoading
)
{
state
.
status
=
'
loading
'
;
}
else
if
(
distance
===
0
)
{
state
.
status
=
'
normal
'
;
}
else
if
(
Math
.
abs
(
distance
)
<
50
)
{
state
.
status
=
'
pulling
'
;
}
else
{
state
.
status
=
'
loosing
'
;
}
};
/** 获取监听自定义滚动节点 */
const
getParentElement
=
el
=>
{
if
(
containerId
.
value
!=
''
)
{
return
document
.
querySelector
(
`#
${
containerId
.
value
}
`
);
}
return
el
&&
el
.
parentNode
;
};
/** 生命周期 首次加载 */
onMounted
(()
=>
{
const
parentElement
=
getParentElement
(
scroller
);
let
scrollElCopy
=
document
.
documentElement
||
document
.
body
;
if
(
useWindow
.
value
===
false
)
{
scrollElCopy
=
parentElement
;
}
scrollEl
=
scrollElCopy
;
});
const
ease
=
(
distance
:
number
)
=>
{
const
headHeight
=
50
;
if
(
distance
>
headHeight
)
{
if
(
distance
<
headHeight
*
2
)
{
distance
=
headHeight
+
(
distance
-
headHeight
)
/
2
;
}
else
{
distance
=
headHeight
*
1.5
+
(
distance
-
headHeight
*
2
)
/
4
;
}
}
return
Math
.
round
(
distance
);
};
const
refreshDone
=
()
=>
{
setStatus
(
0
);
};
const
touchStart
=
event
=>
{
/** 判断滚动条是否在顶部 */
const
top
=
'
scrollTop
'
in
scrollEl
?
scrollEl
.
scrollTop
:
0
;
reachTop
.
value
=
Math
.
max
(
top
,
0
)
==
0
?
true
:
false
;
if
(
reachTop
.
value
)
{
state
.
duration
=
0
;
touch
.
start
(
event
);
}
const
{
scrollHeight
,
clientHeight
,
scrollTop
}
=
scrollEl
;
/** 判断滚动条是否在底部*/
reachBottom
.
value
=
clientHeight
+
scrollTop
==
scrollHeight
?
true
:
false
;
if
(
reachBottom
.
value
)
{
state
.
duration
=
0
;
touch
.
start
(
event
);
}
};
const
touchMove
=
event
=>
{
const
{
deltaY
}
=
touch
;
touch
.
move
(
event
);
if
(
reachTop
.
value
&&
deltaY
.
value
>=
0
&&
touch
.
isVertical
())
{
preventDefault
(
event
);
setStatus
(
ease
(
deltaY
.
value
));
}
if
(
reachBottom
.
value
&&
deltaY
.
value
<
0
&&
touch
.
isVertical
())
{
preventDefault
(
event
);
setStatus
(
ease
(
deltaY
.
value
));
}
};
const
touchEnd
=
()
=>
{
if
(
reachTop
.
value
&&
touch
.
deltaY
.
value
>
0
)
{
if
(
state
.
status
===
'
loosing
'
)
{
setStatus
(
50
,
true
);
emit
(
'
refresh
'
,
refreshDone
);
}
else
{
setStatus
(
0
);
}
}
if
(
reachBottom
.
value
&&
touch
.
deltaY
.
value
<
0
)
{
if
(
state
.
status
===
'
loosing
'
)
{
setStatus
(
-
50
,
true
);
emit
(
'
refresh
'
,
refreshDone
);
}
else
{
setStatus
(
0
);
}
}
};
return
{
scroller
,
touchStart
,
touchMove
,
touchEnd
,
getStyle
,
reachBottom
,
reachTop
,
getBottomStyle
,
...
toRefs
(
state
)
};
}
});
</
script
>
<
style
lang=
"scss"
>
@import
'index.scss'
;
</
style
>
src/packages/pullrefresh/use-touch.ts
0 → 100644
浏览文件 @
caa64662
import
{
ref
}
from
'
vue
'
;
const
MIN_DISTANCE
=
10
;
type
Direction
=
''
|
'
vertical
'
|
'
horizontal
'
;
function
getDirection
(
x
:
number
,
y
:
number
)
{
if
(
x
>
y
&&
x
>
MIN_DISTANCE
)
{
return
'
horizontal
'
;
}
if
(
y
>
x
&&
y
>
MIN_DISTANCE
)
{
return
'
vertical
'
;
}
return
''
;
}
export
function
useTouch
()
{
const
startX
=
ref
(
0
);
const
startY
=
ref
(
0
);
const
deltaX
=
ref
(
0
);
const
deltaY
=
ref
(
0
);
const
offsetX
=
ref
(
0
);
const
offsetY
=
ref
(
0
);
const
direction
=
ref
<
Direction
>
(
''
);
const
isVertical
=
()
=>
direction
.
value
===
'
vertical
'
;
const
isHorizontal
=
()
=>
direction
.
value
===
'
horizontal
'
;
const
reset
=
()
=>
{
deltaX
.
value
=
0
;
deltaY
.
value
=
0
;
offsetX
.
value
=
0
;
offsetY
.
value
=
0
;
direction
.
value
=
''
;
};
const
start
=
((
event
:
TouchEvent
)
=>
{
reset
();
startX
.
value
=
event
.
touches
[
0
].
clientX
;
startY
.
value
=
event
.
touches
[
0
].
clientY
;
})
as
EventListener
;
const
move
=
((
event
:
TouchEvent
)
=>
{
const
touch
=
event
.
touches
[
0
];
deltaX
.
value
=
touch
.
clientX
-
startX
.
value
;
deltaY
.
value
=
touch
.
clientY
-
startY
.
value
;
offsetX
.
value
=
Math
.
abs
(
deltaX
.
value
);
offsetY
.
value
=
Math
.
abs
(
deltaY
.
value
);
if
(
!
direction
.
value
)
{
direction
.
value
=
getDirection
(
offsetX
.
value
,
offsetY
.
value
);
}
})
as
EventListener
;
return
{
move
,
start
,
reset
,
startX
,
startY
,
deltaX
,
deltaY
,
offsetX
,
offsetY
,
direction
,
isVertical
,
isHorizontal
};
}
src/packages/pullrefresh/util.ts
0 → 100644
浏览文件 @
caa64662
export
function
preventDefault
(
event
:
Event
,
isStopPropagation
?:
boolean
)
{
/* istanbul ignore else */
if
(
typeof
event
.
cancelable
!==
'
boolean
'
||
event
.
cancelable
)
{
event
.
preventDefault
();
}
if
(
isStopPropagation
)
event
.
stopPropagation
();
}
export
function
trigger
(
target
:
Element
,
type
:
string
)
{
const
inputEvent
=
document
.
createEvent
(
'
HTMLEvents
'
);
inputEvent
.
initEvent
(
type
,
true
,
true
);
target
.
dispatchEvent
(
inputEvent
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录