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 >
0 commit comments