Skip to content

Commit 898c4c8

Browse files
committed
docs: DemoIframe
1 parent c2c8923 commit 898c4c8

File tree

6 files changed

+141
-24
lines changed

6 files changed

+141
-24
lines changed

docs/components/DemoIframe.vue

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,105 @@
11
<template>
2-
<div>
3-
<iframe :src="fullUrl" />
2+
<div class="DemoIframe">
3+
<div>
4+
<strong>{{ lang === 'zh' ? '请看效果' : 'Preview' }}</strong>
5+
</div>
6+
<div class="iframeWrapper">
7+
<iframe v-if="iframe_id" :src="shouldLoad ? fullUrl : undefined" scrolling="no"
8+
:style="{ height: height + 'px' }" />
9+
</div>
410
</div>
511
</template>
612

713
<script>
14+
import { useData } from 'vitepress'
15+
816
export default {
917
props: {
1018
url: {},
1119
},
20+
setup(props) {
21+
const { isDark, lang } = useData()
22+
return {
23+
isDark,
24+
lang,
25+
}
26+
},
27+
data() {
28+
return {
29+
shouldLoad: false,
30+
loadedOnce: false,
31+
iframe_id: '',
32+
height: '',
33+
bg: '',
34+
color: '',
35+
}
36+
},
1237
computed: {
1338
fullUrl() {
14-
return `${import.meta.env.DEV ? 'http://localhost:3000' : ''}/he-tree-react#${this.url}`
39+
return `${import.meta.env.DEV ? 'http://localhost:3000' : ''}/he-tree-react#${this.url}?bg=${this.bg}&color=${this.color}&iframe_id=${this.iframe_id}`
40+
},
41+
},
42+
watch: {
43+
},
44+
methods: {
45+
resizeIframe(obj) {
46+
obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
1547
},
48+
checkShouldLoad() {
49+
if (this.loadedOnce) {
50+
return
51+
}
52+
const buffer = 200
53+
let rect = this.$el.getBoundingClientRect()
54+
const compare = y => (y > -buffer) && (y < window.innerHeight + buffer)
55+
this.shouldLoad = compare(rect.top) || compare(rect.bottom)
56+
if (this.shouldLoad) {
57+
this.loadedOnce = true
58+
}
59+
},
60+
},
61+
mounted() {
62+
this.$watch('isDark', async (val) => {
63+
await this.$nextTick()
64+
const t = getComputedStyle(document.body)
65+
this.bg = encodeURIComponent(t.backgroundColor)
66+
this.color = encodeURIComponent(t.color)
67+
}, { immediate: true })
68+
//
69+
this.iframe_id = Math.random().toString(36).substring(2, 15)
70+
//
71+
this._messageListener = (e) => {
72+
if (e.data?.type === "iframeHeight") {
73+
if (e.data.id === this.iframe_id) {
74+
this.height = e.data.height
75+
}
76+
}
77+
}
78+
window.addEventListener("message", this._messageListener, false);
79+
80+
window.addEventListener("scroll", this.checkShouldLoad);
81+
},
82+
beforeUnmount() {
83+
window.removeEventListener("message", this._messageListener, false);
84+
window.removeEventListener("scroll", this.checkShouldLoad);
1685
},
17-
methods: {},
1886
}
1987
</script>
2088
2189
<style scoped>
22-
iframe {
23-
width: 100%;
90+
.DemoIframe {
91+
margin: 16px 0;
92+
}
93+
94+
.DemoIframe .iframeWrapper {
95+
margin-top: 10px;
96+
padding: 10px;
97+
border: 1px solid var(--vp-c-divider, #ccc);
98+
border-radius: 8px;
99+
}
100+
101+
.DemoIframe iframe {
24102
border: 0;
25-
min-height: 200px;
103+
width: 100%;
26104
}
27105
</style>

docs/zh/v1/guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ export default function App() {
6767
## 基础使用-平面数据
6868

6969
<<< @/../src/pages/base_flat_data.tsx
70-
<DemoIframe url="/base_tree_data" />
70+
<DemoIframe url="/base_flat_data" />

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
<title>he-tree-react Demo</title>
7+
<title>he-tree-react</title>
88
</head>
99
<body>
1010
<div id="root"></div>

src/PageLayout.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,48 @@
1-
import React, { useState } from "react";
2-
import { useRoutes, Link, NavLink, Outlet } from "react-router-dom";
1+
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
2+
import { Link, NavLink, Outlet, useSearchParams } from "react-router-dom";
33
export default function PageLayout(props: {}) {
4+
const [searchParams, setSearchParams] = useSearchParams();
5+
// bg & color
6+
const prevBgColor = useRef<string[]>();
7+
const bgColor = useMemo(() => [
8+
searchParams.get('bg') || prevBgColor.current?.[0] || '#fff9e6',
9+
searchParams.get('color') || prevBgColor.current?.[1] || '#000'
10+
], [searchParams]);
11+
prevBgColor.current = bgColor;
12+
// iframe id
13+
const [iframeId, setiframeId] = useState(searchParams.get('iframe_id')!);
14+
415
const [menu, setmenu] = useState(() => [
516
{
6-
title: 'Home',
7-
path: '/',
17+
title: 'Base - Flat Data',
18+
path: '/base_flat_data',
819
},
920
{
10-
title: 'Base Tree with Tree Data',
21+
title: 'Base - Tree Data',
1122
path: '/base_tree_data',
1223
},
1324
{
14-
title: 'Base Tree with Flat Data',
15-
path: '/base_flat_data',
25+
title: 'Home',
26+
path: '/',
1627
},
1728
]);
1829

30+
useLayoutEffect(() => {
31+
const { ResizeObserver } = window
32+
const observer = ResizeObserver && new ResizeObserver(() => {
33+
window.parent.postMessage({ type: 'iframeHeight', height: document.body.offsetHeight, id: iframeId }, '*')
34+
})
35+
// observer is undefined in test environment
36+
observer?.observe(document.body)
37+
return () => {
38+
observer?.disconnect()
39+
}
40+
}, [])
41+
1942
return <div className="page-layout">
2043
<Outlet />
21-
<div className="main-menu fixed top-1 right-2 px-4 py-4 bg-gray-200 text-right max-sm:hidden">
44+
<div className="main-menu fixed top-1 right-2 px-4 py-4 bg-gray-100 max-md:hidden">
45+
<div className="text-xl font-bold mb-5 text-black">Menu</div>
2246
{menu.map((item, index) => <div key={index} className="menu-item py-1">
2347
<NavLink to={item.path}>{item.title}</NavLink>
2448
</div>
@@ -27,7 +51,16 @@ export default function PageLayout(props: {}) {
2751
<style>{`
2852
body{
2953
margin: 0;
30-
background-color: #fff9e6;
54+
background-color: ${bgColor[0]};
55+
color: ${bgColor[1]};
56+
}
57+
.main-menu{
58+
}
59+
.main-menu a{
60+
text-decoration: none;
61+
}
62+
.main-menu a:hover{
63+
text-decoration: underline;
3164
}
3265
`}</style>
3366
</div>

src/pages/base_flat_data.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { useHeTree, sortFlatData } from "he-tree-react";
33
import { useState } from 'react';
44

55
export default function BasePage() {
6-
const [data, setdata] = useState(() => sortFlatData(createFlatData()));
6+
const keys = { idKey: 'id', parentIdKey: 'parent_id' };
7+
const [data, setdata] = useState(() => sortFlatData(createFlatData(), keys));
78
const { renderHeTree } = useHeTree({
9+
...keys,
810
data,
911
dataType: 'flat',
10-
idKey: 'id',
11-
parentIdKey: 'parent_id',
1212
onChange: setdata,
1313
renderNode: ({ id, node, open, checked }) => <div>
1414
{node.name}
1515
</div>,
1616
})
17-
return <div>
17+
return <div style={{ width: '300px', border: '1px solid #ccc', padding: '10px' }}>
1818
{renderHeTree()}
1919
</div>
2020
}

src/pages/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11

22
import { createHashRouter, RouterProvider, Link } from "react-router-dom";
33
export default function Home() {
4-
return <h1>Home
5-
</h1>
4+
return <>
5+
<div className="fixed w-full h-full left-0 top-0 flex justify-center items-center">
6+
<div className="text-center">
7+
<h1>he-tree-react Demo</h1>
8+
<a href="https://github.com/phphe/he-tree-react">Github</a>
9+
</div>
10+
</div>
11+
</>
612
}

0 commit comments

Comments
 (0)