demoModule.js:
/** 命名导出:供 import { ... } 使用 */
export const MODULE_TAG = 'demoModule.js'
export const SEED_NUMBERS = [1, 2, 3, 4, 5]
/** 默认导出:供 import xxx from '...' 使用 */
export default function pickEvens(nums) {
return nums.filter((n) => n % 2 === 0)
}
App.jsx:
import { useEffect, useState } from 'react'
import pickEvens, { MODULE_TAG, SEED_NUMBERS } from './demoModule.js'
import './App.css'
/** 箭头函数 + const:可复用的小函数 */
const doubleWithMap = (nums) => nums.map((n) => n * 2)
/** let:需要重新赋值的变量(循环变量、累加中间量) */
const sumWithLetLoop = (nums) => {
let total = 0
for (let i = 0; i < nums.length; i += 1) {
total += nums[i]
}
return total
}
/** let:循环里块级作用域 */
const labelsWithLetFor = () => {
const parts = []
for (let i = 0; i < 3; i += 1) {
parts.push(`项-${i}`)
}
return parts
}
export default function App() {
const [count, setCount] = useState(0)
/** 解构:对象 */
const user = { name: 'Ada', role: '前端', level: 3 }
const { name: displayName, role } = user
/** 解构:数组 */
const coordPair = [120, 80]
const [cx, cy] = coordPair
/** 展开:数组 / 对象 */
const extendedNums = [...SEED_NUMBERS, 6, 7]
const baseStyle = { borderRadius: '6px', padding: '4px 8px' }
const extraStyle = { background: '#eef2ff', color: '#3730a3' }
const tagStyle = { ...baseStyle, ...extraStyle }
/** 模板字符串 */
const headline = `当前计数为 ${count},双倍为 ${count * 2}`
const moduleLine = `从「${MODULE_TAG}」导入:默认函数挑出偶数 → [${pickEvens(
SEED_NUMBERS,
).join(', ')}]`
/** 数组:map / filter / reduce(可链式组合) */
const doubled = doubleWithMap(SEED_NUMBERS)
const evens = SEED_NUMBERS.filter((n) => n % 2 === 0)
const product = SEED_NUMBERS.reduce((acc, n) => acc * n, 1)
const letLoopSum = sumWithLetLoop(SEED_NUMBERS)
const letLabels = labelsWithLetFor()
useEffect(() => {
document.title = `ES6+ 小抄 | 计数 ${count}`
}, [count])
return (
<main className="app">
<header className="hero">
<h1>HTML / CSS / JS 与 ES6+ 在一页里对照看</h1>
<p className="hero-note">
本页用语义化标签(<code><main></code>、<code><section></code>
)组织内容;样式在 <code>App.css</code>。
</p>
</header>
<section className="card" aria-labelledby="sec-counter">
<h2 id="sec-counter">状态与箭头函数(React)</h2>
<p className="hint">
<code>const [count, setCount] = useState(0)</code> 用{' '}
<strong>const</strong> 声明状态;事件里用<strong>箭头函数</strong>调用{' '}
<code>setCount</code>。
</p>
<p className="mono">{headline}</p>
<div className="actions">
<button type="button" onClick={() => setCount((c) => c - 1)}>
−1
</button>
<button type="button" onClick={() => setCount((c) => c + 1)}>
+1
</button>
</div>
</section>
<section className="card" aria-labelledby="sec-destructure">
<h2 id="sec-destructure">解构赋值</h2>
<dl className="kv">
<dt>对象</dt>
<dd>
<code>{'{ name: displayName, role }'}</code> → {displayName} / {role}
</dd>
<dt>数组</dt>
<dd>
<code>[cx, cy]</code> → x: {cx}, y: {cy}
</dd>
</dl>
</section>
<section className="card" aria-labelledby="sec-spread">
<h2 id="sec-spread">展开运算符 …</h2>
<p className="hint">
<code>SEED_NUMBERS</code> 为 <code>[{SEED_NUMBERS.join(', ')}]</code>
</p>
<p>
数组:<code>[...SEED_NUMBERS, 6, 7]</code> → [
{extendedNums.join(', ')}]
</p>
<p>
对象合并:<code>{'{ ...baseStyle, ...extraStyle }'}</code> →{' '}
<span style={tagStyle}>示例标签样式</span>
</p>
</section>
<section className="card" aria-labelledby="sec-let">
<h2 id="sec-let">let / const</h2>
<ul className="list">
<li>
<strong>const</strong>:默认用来声明不变引用(本组件里大量常量、函数)。
</li>
<li>
<strong>let</strong>:需要重新赋值时用(如循环累加{' '}
<code>sumWithLetLoop</code> → {letLoopSum};或{' '}
<code>for (let i …)</code> → {letLabels.join(',')})。
</li>
</ul>
</section>
<section className="card" aria-labelledby="sec-array">
<h2 id="sec-array">数组:map / filter / reduce</h2>
<ul className="list mono">
<li>map(×2):[{doubled.join(', ')}]</li>
<li>filter(偶数):[{evens.join(', ')}]</li>
<li>reduce(乘积):{product}</li>
</ul>
</section>
<section className="card" aria-labelledby="sec-module">
<h2 id="sec-module">模块化 import / export</h2>
<p className="hint">
另见 <code>demoModule.js</code>:<code>export const …</code> 与{' '}
<code>export default …</code>。
</p>
<p className="mono">{moduleLine}</p>
</section>
</main>
)
}
App.css:
.app {
max-width: 40rem;
margin: 0 auto;
padding: 2rem 1.25rem 3rem;
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.55;
color: #1a1a1a;
}
.hero {
margin-bottom: 1.75rem;
}
.hero h1 {
font-size: 1.35rem;
font-weight: 650;
margin: 0 0 0.5rem;
line-height: 1.35;
}
.hero-note {
margin: 0;
color: #555;
font-size: 0.9rem;
}
.card {
border: 1px solid #e5e7eb;
border-radius: 10px;
padding: 1rem 1.15rem 1.15rem;
margin-bottom: 1rem;
background: #fff;
box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
}
.card h2 {
font-size: 1.05rem;
font-weight: 600;
margin: 0 0 0.65rem;
}
.hint {
color: #555;
font-size: 0.88rem;
margin: 0 0 0.75rem;
}
.hint code,
.card code {
font-size: 0.85em;
background: #f3f4f6;
padding: 0.08em 0.35em;
border-radius: 4px;
}
.mono {
font-family: ui-monospace, 'Cascadia Code', monospace;
font-size: 0.9rem;
margin: 0 0 0.75rem;
word-break: break-word;
}
.actions {
display: flex;
gap: 0.65rem;
}
.actions button {
padding: 0.45rem 0.95rem;
font-size: 0.95rem;
cursor: pointer;
border: 1px solid #ccc;
border-radius: 6px;
background: #fff;
}
.actions button:hover {
background: #f9fafb;
}
.kv {
margin: 0;
}
.kv dt {
font-weight: 600;
font-size: 0.85rem;
color: #444;
margin-top: 0.5rem;
}
.kv dt:first-child {
margin-top: 0;
}
.kv dd {
margin: 0.2rem 0 0;
}
.list {
margin: 0;
padding-left: 1.2rem;
}
.list li {
margin-bottom: 0.35rem;
}
.list.mono li {
font-family: ui-monospace, 'Cascadia Code', monospace;
font-size: 0.88rem;
}
相关知识点总结:
HTML / CSS / JavaScript 基础
ES6+ 核心语法(重中之重)
箭头函数
解构赋值
展开运算符 ...
模板字符串
let / const
数组方法:map / filter / reduce
模块化 import / export