Skip to content

Commit ce82af1

Browse files
committed
offline preact works
1 parent cee9722 commit ce82af1

File tree

6 files changed

+408
-0
lines changed

6 files changed

+408
-0
lines changed

examples/preact_offline/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# 忽略JS库文件
2+
*.min.js
3+
4+
# 可能的缓存/临时文件
5+
__pycache__/
6+
*.py[cod]
7+
*$py.class
8+
.DS_Store
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@echo off
2+
setlocal enabledelayedexpansion
3+
4+
:: 确定脚本所在目录
5+
set "SCRIPT_DIR=%~dp0"
6+
7+
echo 开始下载Preact相关库文件...
8+
9+
:: 定义库和URL (使用正确的浏览器版本)
10+
set "LIBS[1]=preact.min.js:https://cdn.jsdelivr.net/npm/[email protected]/dist/preact.min.js"
11+
set "LIBS[2]=hooks.min.js:https://cdn.jsdelivr.net/npm/[email protected]/hooks/dist/hooks.umd.min.js"
12+
set "LIBS[3]=htm.min.js:https://cdn.jsdelivr.net/npm/[email protected]/dist/htm.min.js"
13+
14+
:: 下载文件
15+
for /L %%i in (1,1,3) do (
16+
for /F "tokens=1,2 delims=:" %%a in ("!LIBS[%%i]!") do (
17+
set "LIB_NAME=%%a"
18+
set "URL=%%b"
19+
20+
echo 下载 !LIB_NAME!!URL!
21+
22+
:: 使用PowerShell下载文件
23+
powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '!URL!' -OutFile '%SCRIPT_DIR%\!LIB_NAME!' }"
24+
25+
:: 检查文件是否下载成功
26+
if not exist "%SCRIPT_DIR%\!LIB_NAME!" (
27+
echo 错误: 下载 !LIB_NAME! 失败
28+
exit /b 1
29+
)
30+
31+
echo !LIB_NAME! 下载完成
32+
)
33+
)
34+
35+
echo 所有库文件已成功下载到 %SCRIPT_DIR%
36+
echo 现在可以运行 'python preact_offline_example.py' 启动应用
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
# 确保脚本在任何错误时退出
4+
set -e
5+
6+
# 定义目录
7+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
8+
9+
# 定义库和URL (使用正确的浏览器版本)
10+
LIBS=(
11+
"preact.min.js:https://cdn.jsdelivr.net/npm/[email protected]/dist/preact.min.js"
12+
"hooks.min.js:https://cdn.jsdelivr.net/npm/[email protected]/hooks/dist/hooks.umd.min.js"
13+
"htm.min.js:https://cdn.jsdelivr.net/npm/[email protected]/dist/htm.min.js"
14+
)
15+
16+
echo "开始下载Preact相关库文件..."
17+
18+
# 使用curl或wget下载文件
19+
for lib in "${LIBS[@]}"; do
20+
# 分割库名和URL
21+
LIB_NAME="${lib%%:*}"
22+
URL="${lib#*:}"
23+
24+
echo "下载 $LIB_NAME$URL"
25+
26+
# 尝试使用curl,如果不可用则尝试wget
27+
if command -v curl > /dev/null; then
28+
curl -L -o "$SCRIPT_DIR/$LIB_NAME" "$URL"
29+
elif command -v wget > /dev/null; then
30+
wget -O "$SCRIPT_DIR/$LIB_NAME" "$URL"
31+
else
32+
echo "错误: 需要curl或wget来下载文件"
33+
exit 1
34+
fi
35+
36+
# 检查文件是否下载成功
37+
if [ ! -s "$SCRIPT_DIR/$LIB_NAME" ]; then
38+
echo "错误: 下载 $LIB_NAME 失败"
39+
exit 1
40+
fi
41+
42+
echo "$LIB_NAME 下载完成"
43+
done
44+
45+
echo "所有库文件已成功下载到 $SCRIPT_DIR"
46+
echo "现在可以运行 'python preact_offline_example.py' 启动应用"
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<!DOCTYPE html>
2+
<html lang="zh">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>离线Preact示例</title>
7+
<style>
8+
body {
9+
font-family: system-ui, sans-serif;
10+
max-width: 500px;
11+
margin: 0 auto;
12+
padding: 2rem;
13+
text-align: center;
14+
}
15+
button {
16+
margin: 0 0.5rem;
17+
padding: 0.5rem 1rem;
18+
font-size: 1rem;
19+
cursor: pointer;
20+
}
21+
.counter {
22+
font-size: 2rem;
23+
margin: 2rem 0;
24+
}
25+
.loading {
26+
opacity: 0.5;
27+
}
28+
.error {
29+
color: red;
30+
margin: 1rem 0;
31+
}
32+
</style>
33+
<!-- 使用浏览器版本的库文件 -->
34+
<script src="./preact.min.js"></script>
35+
<script src="./hooks.min.js"></script>
36+
<script src="./htm.min.js"></script>
37+
</head>
38+
<body>
39+
<div id="app"></div>
40+
41+
<script>
42+
// 调试:显示全局变量
43+
console.log("全局对象检查:", {
44+
preact: typeof preact !== 'undefined',
45+
h: typeof h !== 'undefined',
46+
preactHooks: typeof preactHooks !== 'undefined',
47+
htm: typeof htm !== 'undefined'
48+
});
49+
50+
// 从全局变量中安全获取函数,避免重新声明
51+
// 注意:不再使用解构赋值,避免变量声明冲突
52+
const myRender = preact.render;
53+
const myH = preact.h;
54+
const myUseState = preactHooks.useState;
55+
const myUseEffect = preactHooks.useEffect;
56+
const myHtml = htm.bind(myH); // 使用myH而不是h
57+
58+
function Counter() {
59+
const [count, setCount] = myUseState(null);
60+
const [loading, setLoading] = myUseState(true);
61+
const [updating, setUpdating] = myUseState(false);
62+
const [error, setError] = myUseState(null);
63+
64+
// 从Python获取计数
65+
const fetchCount = async () => {
66+
try {
67+
setLoading(true);
68+
setError(null);
69+
const result = await getCount();
70+
setCount(result);
71+
} catch (err) {
72+
setError('获取计数失败: ' + (err.message || err));
73+
console.error('获取计数错误:', err);
74+
} finally {
75+
setLoading(false);
76+
}
77+
};
78+
79+
// 初始加载
80+
myUseEffect(() => {
81+
fetchCount();
82+
}, []);
83+
84+
// 增加计数
85+
const handleIncrement = async () => {
86+
try {
87+
setUpdating(true);
88+
setError(null);
89+
const newCount = await increment();
90+
setCount(newCount);
91+
} catch (err) {
92+
setError('增加计数失败: ' + (err.message || err));
93+
console.error('增加计数错误:', err);
94+
} finally {
95+
setUpdating(false);
96+
}
97+
};
98+
99+
// 减少计数
100+
const handleDecrement = async () => {
101+
try {
102+
setUpdating(true);
103+
setError(null);
104+
const newCount = await decrement();
105+
setCount(newCount);
106+
} catch (err) {
107+
setError('减少计数失败: ' + (err.message || err));
108+
console.error('减少计数错误:', err);
109+
} finally {
110+
setUpdating(false);
111+
}
112+
};
113+
114+
// 显示加载状态
115+
if (loading) {
116+
return myHtml`<div>加载中...</div>`;
117+
}
118+
119+
return myHtml`
120+
<div class=${updating ? 'loading' : ''}>
121+
<h1>Preact计数器示例</h1>
122+
<p>通过Python后端管理状态(完全离线)</p>
123+
124+
<div class="counter">${count !== null ? count : '...'}</div>
125+
126+
${error && myHtml`<div class="error">${error}</div>`}
127+
128+
<div>
129+
<button
130+
onClick=${handleDecrement}
131+
disabled=${updating}
132+
>
133+
减少
134+
</button>
135+
<button
136+
onClick=${handleIncrement}
137+
disabled=${updating}
138+
>
139+
增加
140+
</button>
141+
</div>
142+
</div>
143+
`;
144+
}
145+
146+
// 渲染应用
147+
myRender(myHtml`<${Counter} />`, document.getElementById('app'));
148+
</script>
149+
</body>
150+
</html>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from webview.webview import Webview, Size, SizeHint
2+
import os
3+
import sys
4+
5+
# 创建Webview实例
6+
webview = Webview(debug=True)
7+
webview.title = "离线Preact示例"
8+
webview.size = Size(800, 600, SizeHint.NONE)
9+
10+
# 初始计数器值
11+
count = 0
12+
13+
# Python函数: 获取当前计数
14+
def get_count():
15+
return count
16+
17+
# Python函数: 增加计数
18+
def increment():
19+
global count
20+
count += 1
21+
return count
22+
23+
# Python函数: 减少计数
24+
def decrement():
25+
global count
26+
count -= 1
27+
return count
28+
29+
# 绑定Python函数
30+
webview.bind("getCount", get_count)
31+
webview.bind("increment", increment)
32+
webview.bind("decrement", decrement)
33+
34+
# 获取HTML文件的绝对路径
35+
current_dir = os.path.dirname(os.path.abspath(__file__))
36+
html_path = os.path.join(current_dir, 'preact_offline_example.html')
37+
38+
# 检查HTML文件是否存在
39+
if not os.path.exists(html_path):
40+
print(f"错误: HTML文件不存在: {html_path}")
41+
sys.exit(1)
42+
43+
# 检查JS库是否已下载
44+
required_libs = ['preact.min.js', 'hooks.min.js', 'htm.min.js']
45+
missing_libs = [lib for lib in required_libs if not os.path.exists(os.path.join(current_dir, lib))]
46+
47+
if missing_libs:
48+
# 提示用户运行下载脚本
49+
script_name = 'download_libs.bat' if sys.platform == 'win32' else 'download_libs.sh'
50+
print(f"错误: 缺少必要的JavaScript库文件: {', '.join(missing_libs)}")
51+
print(f"请运行 {os.path.join(current_dir, script_name)} 下载所需库文件")
52+
sys.exit(1)
53+
54+
# 使用file://协议加载HTML
55+
webview.navigate(f"file://{html_path}")
56+
webview.run()

0 commit comments

Comments
 (0)