深入JSX
本质上来讲,JSX是为React.createElement方法提供的语法糖
<MyButton color="blue" shadowSize={2}> Click Me </MyButton>
编译为
React.createElement( MyButton, {color: 'blue', shadowSize: 2}, 'Click Me' )
点表示法用于JSX类型
const MyComponents = { DatePicker: function DatePicker(props) { return <div>Imagine a {props.color} datepicker here.</div>; } } function BlueDatePicker() { return <MyComponents.DatePicker color="blue" />; }
JSX的属性
使用JavaScript表达式作为属性
<MyComponent foo={1 + 2 + 3 + 4} />
字符串常量
<MyComponent message="hello world" /> <MyComponent message={'hello world'} />
属性默认为True
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
展开属性,建议不要使用可能传递不必要的属性给组件
function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />; }
JSX中的子代
字符串子面量
<MyComponent>Hello world!</MyComponent>
JavaScript表达式
function Item(props) { return <li>{props.message}</li>; } function TodoList() { const todos = ['finish doc', 'submit pr', 'nag dan to review']; return ( <ul> {todos.map((message) => <Item key={message} message={message} />)} </ul> ); }
布尔,Undefined,Null会被忽略
<div> {showHeader && <Header />} <Content /> </div>
Refs & DOM
创建Refs
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; } }
访问Refs
const node = this.myRef.current;
为DOM元素添加Ref
class CustomTextInput extends React.Component { constructor(props) { super(props); // 创建 ref 存储 textInput DOM 元素 this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); } focusTextInput() { // 直接使用原生 API 使 text 输入框获得焦点 // 注意:通过 "current" 取得 DOM 节点 this.textInput.current.focus(); } render() { // 告诉 React 我们想把 <input> ref 关联到构造器里创建的 `textInput` 上 return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
ref的更新会发生在componentDidMount和componentDidUpdate
为类添加Ref
class AutoFocusTextInput extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } componentDidMount() { this.textInput.current.focusTextInput(); } render() { return ( <CustomTextInput ref={this.textInput} /> ); } }
回调Refs
class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; this.setTextInputRef = element => { this.textInput = element; }; this.focusTextInput = () => { // 直接使用原生 API 使 text 输入框获得焦点 if (this.textInput) this.textInput.focus(); }; } componentDidMount() { // 渲染后文本框自动获得焦点 this.focusTextInput(); } render() { // 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 React // 实例上(比如 this.textInput) return ( <div> <input type="text" ref={this.setTextInputRef} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
非受控组件
使用ref从DOM 获取表单值
class NameForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { alert('A name was submitted: ' + this.input.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={(input) => this.input = input} /> </label> <input type="submit" value="Submit" /> </form> ); } }
默认值
render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input defaultValue="Bob" type="text" ref={(input) => this.input = input} /> </label> <input type="submit" value="Submit" /> </form> ); }
文件输入标签
class FileInput extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { event.preventDefault(); alert( `Selected file - ${this.fileInput.files[0].name}` ); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Upload file: <input type="file" ref={input => { this.fileInput = input; }} /> </label> <br /> <button type="submit">Submit</button> </form> ); } } ReactDOM.render( <FileInput />, document.getElementById('root') );