React 18 鏂扮壒鎬ц瑙?/title> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/github.min.css">\n <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/javascript.min.js"></script> <style> /* 鍩虹鏍峰紡鍙橀噺瀹氫箟 */ :root { --primary-color: #4361ee; --secondary-color: #3a0ca3; --accent-color: #f72585; --text-color: #333333; --background-color: #ffffff; --card-background: #f8f9fa; --border-color: #e9ecef; --code-background: #f6f8fa; --shadow: 0 2px 8px rgba(0, 0, 0, 0.08); --radius: 8px; --transition: all 0.2s ease; } * { margin: 0; padding: 0; box-sizing: border-box; } html { scroll-behavior: smooth; } body { font-family: 'Noto Sans SC', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--background-color); color: var(--text-color); line-height: 1.6; font-size: 16px; } /* 涓诲鍣?*/ .container { max-width: 800px; margin: 0 auto; padding: 2rem 1.5rem; } /* 鏍囬鏍峰紡 */ h1 { color: var(--primary-color); font-size: 2rem; font-weight: 700; margin-bottom: 1.5rem; text-align: center; padding-bottom: 1rem; border-bottom: 2px solid var(--border-color); } h2 { color: var(--secondary-color); font-size: 1.5rem; font-weight: 600; margin: 2rem 0 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--border-color); } h3 { color: var(--text-color); font-size: 1.2rem; font-weight: 500; margin: 1.5rem 0 0.8rem; } /* 娈佃惤鍜屾枃鏈?*/ p { margin: 1rem 0; text-align: justify; } /* 鍒楄〃鏍峰紡 */ ul, ol { margin: 1rem 0; padding-left: 2rem; } li { margin: 0.5rem 0; } /* 浠g爜鏍峰紡 */ pre { background-color: var(--code-background); border-radius: var(--radius); padding: 1rem; overflow-x: auto; margin: 1.5rem 0; box-shadow: var(--shadow); } code { font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 0.9rem; color: var(--secondary-color); } pre code { color: var(--text-color); } /* 鍗$墖鏍峰紡 */ .card { background-color: var(--card-background); border-radius: var(--radius); padding: 1.5rem; margin: 1.5rem 0; box-shadow: var(--shadow); transition: var(--transition); } .card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); transform: translateY(-2px); } /* 鎻愮ず妗嗘牱寮?*/ .tip { background-color: rgba(67, 97, 238, 0.1); border-left: 4px solid var(--primary-color); padding: 1rem; margin: 1.5rem 0; border-radius: 0 var(--radius) var(--radius) 0; } /* 浠g爜楂樹寒 */ .hljs { background: var(--code-background) !important; } /* 鍝嶅簲寮忚璁?*/ @media (max-width: 768px) { .container { padding: 1.5rem 1rem; } h1 { font-size: 1.8rem; } h2 { font-size: 1.3rem; } h3 { font-size: 1.1rem; } } /* 澶撮儴瀵艰埅 */ header { background-color: var(--background-color); border-bottom: 1px solid var(--border-color); padding: 1rem 0; margin-bottom: 2rem; box-shadow: var(--shadow); } .header-container { max-width: 800px; margin: 0 auto; padding: 0 1.5rem; display: flex; justify-content: space-between; align-items: center; } .header-title { font-size: 1.2rem; font-weight: 700; color: var(--primary-color); } .back-link { color: var(--text-color); text-decoration: none; font-size: 0.9rem; transition: var(--transition); padding: 0.5rem 1rem; border-radius: var(--radius); border: 1px solid var(--border-color); } .back-link:hover { background-color: var(--primary-color); color: white; border-color: var(--primary-color); } /* 鍝嶅簲寮忓ご閮ㄨ璁?*/ @media (max-width: 768px) { .header-container { padding: 0 1rem; } .header-title { font-size: 1.1rem; } .back-link { padding: 0.4rem 0.8rem; font-size: 0.85rem; } } </style> </head> <body> <!-- 澶撮儴瀵艰埅 --> <header> <div class="header-container"> <div class="header-title">React鏁欑▼</div> <a href="../article.html" class="back-link">杩斿洖鏂囩珷鍒楄〃</a> </div> </header> <div class="container"> <h1>React 18 鏂扮壒鎬ц瑙?/h1> <p>React 18 鏄?React 搴撶殑閲嶅ぇ鐗堟湰鏇存柊锛屽甫鏉ヤ簡璁稿鏂扮壒鎬у拰鎬ц兘鏀硅繘銆傛湰鏂囧皢璇︾粏浠嬬粛 React 18 鐨勪富瑕佹柊鐗规€э紝甯姪寮€鍙戣€呮洿濂藉湴鐞嗚В鍜屽簲鐢ㄨ繖浜涚壒鎬с€?/p> <h2>1. Concurrent Features锛堝苟鍙戠壒鎬э級</h2> <h3>1.1 Automatic Batching锛堣嚜鍔ㄦ壒澶勭悊锛?/h3> <p>React 18 寮曞叆浜嗚嚜鍔ㄦ壒澶勭悊鍔熻兘锛屾棤璁虹姸鎬佹洿鏂板彂鐢熷湪鍝噷锛岄兘浼氳鎵瑰鐞嗭紝浠庤€屽噺灏戞覆鏌撴鏁帮紝鎻愰珮鎬ц兘銆?/p> <pre><code class="javascript">// React 17 涓紝鍙湁鍦ㄤ簨浠跺鐞嗗嚱鏁颁腑鐨勭姸鎬佹洿鏂颁細琚壒澶勭悊 // React 18 涓紝鎵€鏈夌姸鎬佹洿鏂伴兘浼氳鎵瑰鐞? function App() { const [count, setCount] = useState(0); const [isLoading, setIsLoading] = useState(false); function handleClick() { // React 17 鍜?18 閮戒細鎵瑰鐞嗚繖浜涙洿鏂? setCount(c => c + 1); setIsLoading(true); } function handleFetch() { // React 17 涓紝杩欎簺鏇存柊涓嶄細琚壒澶勭悊 // React 18 涓紝杩欎簺鏇存柊浼氳鎵瑰鐞? fetch('https://api.example.com') .then(() => { setCount(c => c + 1); setIsLoading(false); }); } return ( <div> <button onClick={handleClick}>Increment</button> <button onClick={handleFetch}>Fetch Data</button> <p>Count: {count}</p> <p>Loading: {isLoading ? 'Yes' : 'No'}</p> </div> ); }</code></pre> <h3>1.2 startTransition锛堝紑濮嬭繃娓★級</h3> <p>startTransition 鍏佽寮€鍙戣€呭皢鏌愪簺鏇存柊鏍囪涓洪潪绱ф€ユ洿鏂帮紝React 浼氫紭鍏堝鐞嗙揣鎬ユ洿鏂帮紙濡傜敤鎴疯緭鍏ワ級锛岀劧鍚庡啀澶勭悊杩欎簺杩囨浮鏇存柊銆?/p> <pre><code class="javascript">import { startTransition, useState } from 'react'; function App() { const [input, setInput] = useState(''); const [results, setResults] = useState([]); function handleInputChange(e) { setInput(e.target.value); // 灏嗘悳绱㈢粨鏋滄洿鏂版爣璁颁负杩囨浮鏇存柊 startTransition(() => { // 妯℃嫙鎼滅储鎿嶄綔 const newResults = searchItems(e.target.value); setResults(newResults); }); } return ( <div> <input type="text" value={input} onChange={handleInputChange} /> <ul> {results.map(result => ( <li key={result.id}>{result.name}</li> ))} </ul> </div> ); }</code></pre> <h3>1.3 useDeferredValue锛堜娇鐢ㄥ欢杩熷€硷級</h3> <p>useDeferredValue 鍏佽寮€鍙戣€呰幏鍙栦竴涓欢杩熺増鏈殑鐘舵€佸€硷紝React 浼氬湪娓叉煋绱ф€ユ洿鏂板悗鍐嶆洿鏂拌繖涓欢杩熷€笺€?/p> <pre><code class="javascript">import { useDeferredValue, useState } from 'react'; function App() { const [input, setInput] = useState(''); const deferredInput = useDeferredValue(input); return ( <div> <input type="text" value={input} onChange={(e) => setInput(e.target.value)} /> <SearchResults query={deferredInput} /> </div> ); } function SearchResults({ query }) { // 杩欎釜缁勪欢浼氬湪 input 绋冲畾鍚庡啀閲嶆柊娓叉煋 const results = searchItems(query); return ( <ul> {results.map(result => ( <li key={result.id}>{result.name}</li> ))} </ul> ); }</code></pre> <h2>2. Suspense Improvements锛圫uspense 鏀硅繘锛?/h2> <h3>2.1 Suspense for Data Fetching锛堟暟鎹幏鍙栫殑 Suspense锛?/h3> <p>React 18 鏀硅繘浜?Suspense 鍔熻兘锛屼娇鍏跺彲浠ユ洿濂藉湴鐢ㄤ簬鏁版嵁鑾峰彇鍦烘櫙銆?/p> <pre><code class="javascript">import { Suspense, useState } from 'react'; import { fetchData } from './api'; function DataComponent() { const data = fetchData(); // 杩欐槸涓€涓?Suspense-enabled 鏁版嵁鑾峰彇鍑芥暟 return <div>{data}</div>; } function App() { return ( <Suspense fallback={<div>Loading...</div>}> <DataComponent /> </Suspense> ); }</code></pre> <h3>2.2 Suspense with SSR锛堟湇鍔$娓叉煋鐨?Suspense锛?/h3> <p>React 18 鏀寔鍦ㄦ湇鍔$娓叉煋涓娇鐢?Suspense锛屽疄鐜版祦寮忔覆鏌撱€?/p> <h2>3. New Root API锛堟柊鐨勬牴 API锛?/h2> <p>React 18 寮曞叆浜嗘柊鐨勬牴 API锛屼娇鐢?createRoot 鏇夸唬浜?ReactDOM.render銆?/p> <pre><code class="javascript">// React 17 import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render(<App />, document.getElementById('root')); // React 18 import ReactDOM from 'react-dom/client'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />);</code></pre> <h2>4. Transitions锛堣繃娓★級</h2> <p>杩囨浮鏄?React 18 涓紩鍏ョ殑涓€涓柊姒傚康锛岀敤浜庡尯鍒嗙揣鎬ユ洿鏂板拰闈炵揣鎬ユ洿鏂般€?/p> <div class="tip"> <strong>鎻愮ず锛?/strong> 浣跨敤 startTransition 鎴?useTransition 鍙互灏嗛潪绱ф€ユ洿鏂版爣璁颁负杩囨浮鏇存柊锛孯eact 浼氫紭鍏堝鐞嗙揣鎬ユ洿鏂帮紝浠庤€屾彁楂樼敤鎴蜂綋楠屻€? </div> <h2>5. Other Improvements锛堝叾浠栨敼杩涳級</h2> <ul> <li><strong>useId锛?/strong> 鐢熸垚鍞竴 ID锛岄€傜敤浜庢湇鍔$娓叉煋鍜屽鎴风娓叉煋鐨勪竴鑷存€с€?/li> <li><strong>useSyncExternalStore锛?/strong> 鐢ㄤ簬璁㈤槄澶栭儴鏁版嵁婧愶紝纭繚鍦ㄥ苟鍙戞ā寮忎笅鐨勪竴鑷存€с€?/li> <li><strong>useInsertionEffect锛?/strong> 鐢ㄤ簬 CSS-in-JS 搴擄紝鍦?DOM 绐佸彉涔嬪墠鎻掑叆鏍峰紡銆?/li> </ul> <h2>6. 杩佺Щ鍒?React 18</h2> <p>杩佺Щ鍒?React 18 闇€瑕佷互涓嬫楠わ細</p> <ol> <li>鏇存柊 React 鍜?ReactDOM 鍒?18 鐗堟湰</li> <li>灏?ReactDOM.render 鏇挎崲涓?ReactDOM.createRoot</li> <li>鏍规嵁闇€瑕佷娇鐢ㄦ柊鐨勫苟鍙戠壒鎬?/li> </ol> <div class="card"> <h3>鎬荤粨</h3> <p>React 18 甯︽潵浜嗚澶氭柊鐗规€у拰鎬ц兘鏀硅繘锛岀壒鍒槸骞跺彂鐗规€э紝浣垮緱 React 搴旂敤鍙互鏇村ソ鍦板鐞嗗鏉傜殑鏇存柊鍦烘櫙锛屾彁楂樼敤鎴蜂綋楠屻€傚紑鍙戣€呭簲璇ラ€愭閲囩敤杩欎簺鏂扮壒鎬э紝浠ュ厖鍒嗗彂鎸?React 18 鐨勪紭鍔裤€?/p> </div> </div> <script> // 鍒濆鍖栦唬鐮侀珮浜? document.addEventListener('DOMContentLoaded', (event) => { document.querySelectorAll('pre code').forEach((block) => { hljs.highlightElement(block); }); }); </script> <footer> <div class="footer-content"> <p>© 2026 骞冲钩鐨勫皬鐮寸珯 鐗堟潈鎵€鏈?/p> <div class="footer-links"> <span>鐢?<a href="https://ppkjgzs.top" class="footer-link" target="_blank">骞冲钩鐨勫皬鐮寸珯</a> 鍒朵綔</span> <span class="divider">|</span> <span>浣跨敤 <span class="tech">HTML5</span>, <span class="tech">CSS3</span> 鍜?<span class="tech">Font Awesome</span> 鏋勫缓</span> <span class="divider">|</span> <a href="https://beian.miit.gov.cn/" target="_blank" class="footer-link">娴橧CP澶?025194709鍙?2</a> <span class="divider">|</span> <a href="https://beian.mps.gov.cn/#/query/webSearch?code=13020202000680" rel="noreferrer" target="_blank" class="footer-link">鍐€鍏綉瀹夊13020202000680鍙?/a> </div> </div> </footer> <style> /* 椤佃剼鏍峰紡 */ footer { background-color: #ffffff; color: var(--text-color); padding: 2rem 1rem; text-align: center; margin-top: 3rem; font-size: 0.9rem; border-top: 1px solid var(--border-color); } .footer-content { max-width: 800px; margin: 0 auto; text-align: center; } .footer-content p { text-align: center; margin-bottom: 1rem; } .footer-links { margin-top: 1rem; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 1rem; font-size: 0.85rem; text-align: center; } .footer-links span { text-align: center; } .footer-link { color: var(--primary-color); text-decoration: none; } .footer-link:hover { text-decoration: underline; } .divider { color: var(--border-color); } .tech { color: var(--primary-color); font-weight: 500; } /* 椤佃剼鍝嶅簲寮忎紭鍖?*/ @media (max-width: 768px) { footer { padding: 1.5rem 1rem; font-size: 0.85rem; } .footer-links { gap: 0.8rem; font-size: 0.8rem; } } </style> </body> </html>