JavaScript的扩展语法与React开发基础
JSX定义:JSX是JavaScript的语法扩展,它允许我们在JavaScript代码中编写类似HTML的标记。JSX让React组件的编写更加直观和简洁。
// 使用React.createElement
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
// 使用JSX语法
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
重要概念:JSX不是必须的,但强烈推荐使用。它会被编译成普通的JavaScript函数调用,最终生成React元素。
规则:所有标签都必须正确闭合,包括自闭合标签。
// ✅ 正确
<div>内容</div>
<img src="image.jpg" />
<input type="text" />
// ❌ 错误
<div>内容 // 缺少闭合标签
<img src="image.jpg"> // 自闭合标签需要斜杠
规则:JSX表达式必须有一个根元素,或者使用Fragment。
// ✅ 正确 - 使用div包裹
return (
<div>
<h1>标题</h1>
<p>内容</p>
</div>
);
// ✅ 正确 - 使用Fragment
return (
<>
<h1>标题</h1>
<p>内容</p>
</>
);
// ❌ 错误 - 多个根元素
return (
<h1>标题</h1>
<p>内容</p>
);
注意:由于class是JavaScript的保留字,在JSX中使用className来设置CSS类。
// ✅ 正确
<div className="container">内容</div>
// ❌ 错误
<div class="container">内容</div>
核心特性:可以在JSX中使用花括号{}来嵌入任何有效的JavaScript表达式。
function Welcome() {
const name = "张三";
const age = 25;
const isStudent = true;
return (
<div>
<h1>欢迎, {name}!</h1>
<p>年龄: {age}</p>
<p>状态: {isStudent ? '学生' : '非学生'}</p>
<p>明年年龄: {age + 1}</p>
</div>
);
}
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
function UserCard() {
const user = {
firstName: '李',
lastName: '四'
};
return (
<div>
<h2>用户: {formatName(user)}</h2>
<p>时间: {new Date().toLocaleTimeString()}</p>
</div>
);
}
function LoginButton({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>退出登录</button>
) : (
<button>登录</button>
)}
</div>
);
}
function Notification({ message, showNotification }) {
return (
<div>
{showNotification && (
<div className="notification">
{message}
</div>
)}
</div>
);
}
function Greeting({ isMorning }) {
let greeting;
if (isMorning) {
greeting = <h1>早上好!</h1>;
} else {
greeting = <h1>晚上好!</h1>;
}
return <div>{greeting}</div>;
}
function TodoList() {
const todos = [
{ id: 1, text: '学习React', completed: false },
{ id: 2, text: '写代码', completed: true },
{ id: 3, text: '阅读文档', completed: false }
];
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text} - {todo.completed ? '已完成' : '未完成'}
</li>
))}
</ul>
);
}
重要提示:列表中的每个元素都需要一个唯一的key属性,这有助于React识别哪些项目发生了变化。
function StyledComponent() {
const boxStyle = {
backgroundColor: '#f0f0f0',
padding: '20px',
border: '1px solid #ccc',
borderRadius: '5px',
margin: '10px 0'
};
return (
<div style={boxStyle}>
<h2 style={{color: '#61DAFB', fontSize: '24px'}}>
带样式的组件
</h2>
<p style={{color: '#666', lineHeight: '1.6'}}>
这是一个带有内联样式的段落。
</p>
</div>
);
}
样式对象:内联样式需要使用驼峰命名法(如backgroundColor),而不是CSS的连字符写法(background-color)。
function InteractiveButton() {
const handleClick = () => {
alert('按钮被点击了!');
};
const handleMouseOver = (event) => {
event.target.style.backgroundColor = '#61DAFB';
};
const handleMouseOut = (event) => {
event.target.style.backgroundColor = '';
};
return (
<button
onClick={handleClick}
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
style={{
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
点击我试试!
</button>
);
}
任务:创建一个商品列表组件
要求:
// 参考答案
function ProductList() {
const products = [
{ id: 1, name: 'iPhone', price: 5999, stock: 10 },
{ id: 2, name: 'MacBook', price: 9999, stock: 5 },
{ id: 3, name: 'iPad', price: 3299, stock: 0 }
];
const handleClick = (product) => {
alert(`商品: ${product.name}\n价格: ¥${product.price}\n库存: ${product.stock}`);
};
return (
<div>
<h2>商品列表</h2>
{products.map(product => (
<div
key={product.id}
onClick={() => handleClick(product)}
style={{
border: '1px solid #ddd',
padding: '15px',
margin: '10px 0',
borderRadius: '5px',
cursor: 'pointer',
backgroundColor: product.stock === 0 ? '#ffebee' : '#f9f9f9',
color: product.stock === 0 ? '#f44336' : 'inherit'
}}
>
<h3>{product.name}</h3>
<p>价格: ¥{product.price}</p>
<p>库存: {product.stock}</p>
</div>
))}
</div>
);
}