目录
- JSX
- 环境配置
- 基本语法规则
- 在 JSX 中嵌入 JavaScript 表达式
- 在 JavaScript 表达式中嵌入 JSX
- JSX 中的节点属性
- 声明子节点
- JSX 自动阻止注入攻击
- 在 JSX 中使用注释
- JSX 原理
- 列表循环
- DOM Elements
- 列表渲染
- 语法高亮
- 条件渲染
- 示例1:
- 示例2:
- 示例3(行内判断):
- 示例4(if-else):
- 示例5(阻止组件渲染):
JSX
HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法。它允许 HTML 与 JavaScript 的混写。
- Introducing JSX
- JSX In Depth
- React Without JSX
环境配置
- 非模块化环境
babel-standalone
- 模块化环境
babel-preset-react
- Babel REPL 赋值查看编译结果
基本语法规则
-
必须只能有一个根节点
-
遇到 HTML 标签 (以
<
开头) 就用 HTML 规则解析- 单标签不能省略结束标签。
-
遇到代码块(以
{
开头),就用 JavaScript 规则解析 -
JSX 允许直接在模板中插入一个 JavaScript 变量
- 如果这个变量是一个数组,则会展开这个数组的所有成员添加到模板中
-
单标签必须结束
/>
基本语法:
const element = <h1>Hello, world!</h1>;
在 JSX 中嵌入 JavaScript 表达式
- 语法
- 如果 JSX 写到了多行中,则建议包装括号避免自动分号的陷阱
function formatName(user) {return user.firstName + ' ' + user.lastName;
}const user = {firstName: 'Harper',lastName: 'Perez'
};const element = (<h1>Hello, {formatName(user)}!</h1>
);ReactDOM.render(element,document.getElementById('root')
);
在 JavaScript 表达式中嵌入 JSX
function getGreeting(user) {if (user) {return <h1>Hello, {formatName(user)}!</h1>;}return <h1>Hello, Stranger.</h1>;
}
JSX 中的节点属性
- 动态绑定属性值
class
使用className
tabindex
使用tabIndex
for
使用htmlFor
普通的属性:
const element = <div tabIndex="0"></div>;
在属性中使用表达式:
const element = <img src={user.avatarUrl}></img>;
声明子节点
如果标签是空的,可以使用 />
立即关闭它。
const element = <img src={user.avatarUrl} />;
JSX 子节点可以包含子节点:
const element = (<div><h1>Hello!</h1><h2>Good to see you here.</h2></div>
);
JSX 自动阻止注入攻击
const element = <div>{'<h1>this is safe</h1>'}</div>
在 JSX 中使用注释
写法一:
{// 注释// ...
}
写法二(单行推荐):
{/* 单行注释 */}
写法三(多行推荐):
{/** 多行注释*/
}
JSX 原理
Babel 会把 JSX 编译为 React.createElement()
函数。
- 每个 React 元素都是一个真实的 JavaScript 对象
下面两种方式是等价的:
const element = (<h1 className="greeting">Hello, world!</h1>
);
const element = React.createElement('h1',{className: 'greeting'},'Hello, world!'
);
// Note: this structure is simplified
const element = {type: 'h1',props: {className: 'greeting',children: 'Hello, world'}
};
列表循环
JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
var arr = [<h1>Hello world!</h1>,<h2>React is awesome</h2>,
];
ReactDOM.render(<div>{arr}</div>,document.getElementById('example')
);
综上所述,我们可以这样:
var names = ['Alice', 'Emily', 'Kate'];ReactDOM.render(<div>{names.map(function (name) {return <div>Hello, {name}!</div>})}</div>,document.getElementById('example')
);
DOM Elements
参考文档:https://reactjs.org/docs/dom-elements.html
列表渲染
参考文档:https://reactjs.org/docs/lists-and-keys.html
语法高亮
http://babeljs.io/docs/editors
条件渲染
参考文档:https://reactjs.org/docs/conditional-rendering.html
示例1:
function UserGreeting(props) {return <h1>Welcome back!</h1>;
}function GuestGreeting(props) {return <h1>Please sign up.</h1>;
}function Greeting(props) {const isLoggedIn = props.isLoggedIn;if (isLoggedIn) {return <UserGreeting />;}return <GuestGreeting />;
}ReactDOM.render(// Try changing to isLoggedIn={true}:<Greeting isLoggedIn={false} />,document.getElementById('root')
);
示例2:
function LoginButton(props) {return (<button onClick={props.onClick}>Login</button>);
}function LogoutButton(props) {return (<button onClick={props.onClick}>Logout</button>);
}class LoginControl extends React.Component {constructor(props) {super(props);this.handleLoginClick = this.handleLoginClick.bind(this);this.handleLogoutClick = this.handleLogoutClick.bind(this);this.state = {isLoggedIn: false};}handleLoginClick() {this.setState({isLoggedIn: true});}handleLogoutClick() {this.setState({isLoggedIn: false});}render() {const isLoggedIn = this.state.isLoggedIn;let button = null;if (isLoggedIn) {button = <LogoutButton onClick={this.handleLogoutClick} />;} else {button = <LoginButton onClick={this.handleLoginClick} />;}return (<div><Greeting isLoggedIn={isLoggedIn} />{button}</div>);}
}ReactDOM.render(<LoginControl />,document.getElementById('root')
);
示例3(行内判断):
function Mailbox(props) {const unreadMessages = props.unreadMessages;return (<div><h1>Hello!</h1>{unreadMessages.length > 0 &&<h2>You have {unreadMessages.length} unread messages.</h2>}</div>);
}const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(<Mailbox unreadMessages={messages} />,document.getElementById('root')
);
示例4(if-else):
render() {const isLoggedIn = this.state.isLoggedIn;return (<div>The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.</div>);
}
render() {const isLoggedIn = this.state.isLoggedIn;return (<div>{isLoggedIn ? (<LogoutButton onClick={this.handleLogoutClick} />) : (<LoginButton onClick={this.handleLoginClick} />)}</div>);
}
示例5(阻止组件渲染):
function WarningBanner(props) {if (!props.warn) {return null;}return (<div className="warning">Warning!</div>);
}class Page extends React.Component {constructor(props) {super(props);this.state = {showWarning: true}this.handleToggleClick = this.handleToggleClick.bind(this);}handleToggleClick() {this.setState(prevState => ({showWarning: !prevState.showWarning}));}render() {return (<div><WarningBanner warn={this.state.showWarning} /><button onClick={this.handleToggleClick}>{this.state.showWarning ? 'Hide' : 'Show'}</button></div>);}
}ReactDOM.render(<Page />,document.getElementById('root')
);