Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jinfa-platform
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
陈智峰
jinfa-platform
Commits
8cf939c0
Commit
8cf939c0
authored
May 11, 2021
by
XieZhiXiong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 添加 AnchorPage 带锚点头部页面布局组件
parent
e9600160
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
224 additions
and
56 deletions
+224
-56
useClientRect.ts
src/hooks/useClientRect.ts
+64
-0
index.less
src/layouts/AnchorPage/index.less
+80
-34
index.tsx
src/layouts/AnchorPage/index.tsx
+80
-22
No files found.
src/hooks/useClientRect.ts
0 → 100644
View file @
8cf939c0
/*
* @Author: XieZhiXiong
* @Date: 2021-05-11 09:44:16
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-05-11 10:14:07
* @Description: 获取 DOM 节点的位置 或是 大小 hook
*/
import
{
useState
,
useCallback
}
from
'react'
;
interface
RectData
{
/**
* 元素高度
*/
height
:
number
,
/**
* 元素宽度
*/
width
:
number
,
/**
* 元素顶部距离视口的距离
*/
top
:
number
,
/**
* 元素右侧距离视口的距离
*/
right
:
number
,
/**
* 元素底部距离视口的距离
*/
bottom
:
number
,
/**
* 元素左侧距离视口的距离
*/
left
:
number
,
/**
* 元素距离左上角坐标 (0, 0)的 x 坐标值
*/
x
:
number
,
/**
* 元素距离左上角坐标 (0, 0)的 y 坐标值
*/
y
:
number
,
}
const
useClientRect
=
():
[
RectData
,
any
]
=>
{
const
[
rect
,
setRect
]
=
useState
({
height
:
0
,
width
:
0
,
top
:
0
,
right
:
0
,
bottom
:
0
,
left
:
0
,
x
:
0
,
y
:
0
,
});
const
ref
=
useCallback
(
node
=>
{
if
(
node
!==
null
)
{
setRect
(
node
.
getBoundingClientRect
());
}
},
[]);
return
[
rect
,
ref
];
}
export
default
useClientRect
;
src/
components/AnchorPageHeader
/index.less
→
src/
layouts/AnchorPage
/index.less
View file @
8cf939c0
@import '~antd/es/style/themes/default.less';
.anchor-page-header {
display: flex;
background: #FFFFFF;
&-left {
flex: 1;
overflow: hidden;
}
&-right {
padding-top: 14px;
flex-shrink: 0;
margin-left: 12px;
}
.anchor-page {
&-header {
background: #FFFFFF;
&-heading {
padding: 14px 0;
display: flex;
align-items: center;
&-title {
margin-bottom: 0;
color: rgba(0, 0, 0, 0.85);
font-weight: 600;
font-size: 18px;
line-height: 32px;
&-main {
padding: 0 16px;
display: flex;
}
&-left {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
&-right {
padding-top: 14px;
flex-shrink: 0;
margin-left: 12px;
}
&-heading {
padding: 14px 0 9px 0;
display: flex;
align-items: center;
&-title {
margin-bottom: 0;
color: rgba(0, 0, 0, 0.85);
font-weight: 600;
font-size: 18px;
line-height: 32px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
&-back {
margin-right: 12px;
font-size: 16px;
cursor: pointer;
&:hover {
color: @primary-color;
}
}
&-anchors {
display: flex;
align-items: center;
}
:global {
.ant-anchor {
&-link {
padding: 0 16px;
font-size: 14px;
font-weight: 400;
color: @text-color;
&-back {
margin-right: 12px;
font-size: 16px;
cursor: pointer;
&-title {
padding: 16px 0;
border-bottom: 2px solid transparent;
}
&-active,
&:hover {
font-weight: 500;
color: @text-color;
&:hover {
color: @primary-color;
.ant-anchor-link-title {
border-bottom: 2px solid @primary-color;
}
}
}
&-ink {
display: none;
}
}
}
}
&-content {
padding: 16px;
}
}
\ No newline at end of file
src/
components/AnchorPageHeader
/index.tsx
→
src/
layouts/AnchorPage
/index.tsx
View file @
8cf939c0
...
...
@@ -2,13 +2,14 @@
* @Author: XieZhiXiong
* @Date: 2021-05-10 11:36:58
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-05-1
0 15:05:20
* @LastEditTime: 2021-05-1
1 10:16:12
* @Description: 页面公用锚点头部
*/
import
React
from
'react'
;
import
{
Anchor
,
Button
}
from
'antd'
;
import
React
,
{
useState
}
from
'react'
;
import
{
Anchor
}
from
'antd'
;
import
{
ArrowLeftOutlined
}
from
'@ant-design/icons'
;
import
{
history
}
from
'umi'
;
import
useClientRect
from
'@/hooks/useClientRect'
;
import
styles
from
'./index.less'
;
export
interface
AnchorsItem
{
...
...
@@ -35,6 +36,12 @@ interface IProps {
* 锚点数据
*/
anchors
:
AnchorsItem
[],
/**
* 自定义样式
*/
customStyle
?:
React
.
CSSProperties
,
children
?:
React
.
ReactNode
,
}
const
AnchorPageHeader
:
React
.
FC
<
IProps
>
=
(
props
:
IProps
)
=>
{
...
...
@@ -42,39 +49,90 @@ const AnchorPageHeader: React.FC<IProps> = (props: IProps) => {
title
,
extra
,
anchors
,
customStyle
,
children
,
}
=
props
;
const
firstKey
=
anchors
.
length
?
`#
${
anchors
[
0
].
key
}
`
:
''
;
const
[
current
,
setCurrent
]
=
useState
(
firstKey
);
const
[
rect
,
measuredRef
]
=
useClientRect
();
const
handleBack
=
()
=>
{
history
.
goBack
();
};
const
handleAnchorChange
=
(
currentActiveLink
:
string
)
=>
{
if
(
currentActiveLink
)
{
setCurrent
(
''
);
return
;
}
if
(
!
currentActiveLink
)
{
setCurrent
(
firstKey
);
}
};
const
handleAnchorClick
=
(
e
:
React
.
MouseEvent
<
HTMLElement
>
)
=>
{
e
.
preventDefault
();
};
return
(
<
div
className=
{
styles
[
'anchor-page-header'
]
}
>
<
div
className=
{
styles
[
'anchor-page-header-left'
]
}
>
<
div
className=
{
styles
[
'anchor-page-header-heading'
]
}
>
<
ArrowLeftOutlined
className=
{
styles
[
'anchor-page-header-back'
]
}
onClick=
{
handleBack
}
/>
<
span
className=
{
styles
[
'anchor-page-header-heading-title'
]
}
>
{
title
}
</
span
>
</
div
>
<
div
className=
{
styles
[
'anchor-page-header-content'
]
}
>
123
</
div
>
<
div
className=
{
styles
[
'anchor-page'
]
}
style=
{
customStyle
}
>
<
div
className=
{
styles
[
'anchor-page-header'
]
}
style=
{
customStyle
}
ref=
{
measuredRef
}
>
<
Anchor
showInkInFixed=
{
false
}
targetOffset=
{
rect
.
height
}
onChange=
{
handleAnchorChange
}
onClick=
{
handleAnchorClick
}
>
<
div
className=
{
styles
[
'anchor-page-header-main'
]
}
>
<
div
className=
{
styles
[
'anchor-page-header-left'
]
}
>
<
div
className=
{
styles
[
'anchor-page-header-heading'
]
}
>
<
ArrowLeftOutlined
className=
{
styles
[
'anchor-page-header-back'
]
}
onClick=
{
handleBack
}
/>
<
span
className=
{
styles
[
'anchor-page-header-heading-title'
]
}
>
{
title
}
</
span
>
</
div
>
<
div
className=
{
styles
[
'anchor-page-header-content'
]
}
>
<
div
className=
{
styles
[
'anchor-page-header-anchors'
]
}
>
{
anchors
.
map
((
item
,
index
)
=>
(
<
Anchor
.
Link
className=
{
current
&&
index
===
0
?
'ant-anchor-link-active'
:
null
}
key=
{
item
.
key
}
href=
{
`#${item.key}`
}
title=
{
item
.
name
}
/>
))
}
</
div
>
</
div
>
</
div
>
{
extra
?
(
<
div
className=
{
styles
[
'anchor-page-header-right'
]
}
>
{
extra
}
</
div
>
)
:
null
}
</
div
>
</
Anchor
>
</
div
>
<
div
className=
{
styles
[
'anchor-page-content'
]
}
>
{
children
}
</
div
>
{
extra
?
(
<
div
className=
{
styles
[
'anchor-page-header-right'
]
}
>
{
extra
}
</
div
>
)
:
null
}
</
div
>
);
};
AnchorPageHeader
.
defaultProps
=
{
extra
:
null
,
customStyle
:
{},
children
:
null
,
};
export
default
AnchorPageHeader
;
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