React学习笔记
1.React—Hello World
-
在DOM容器中添加容器,存放react内容
-
<div id="app"></div>
-
-
引入React
-
<script src="./node_modules/babel-standalone/babel.min.js"></script> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
-
-
创建React组件
-
<script type="text/babel"> ReactDOM.render( <h1>Hello,world!</h1>, document.getElementById('app') ); </script>
-
2.React—jsx
-
jsx就是在React组建中可以写什么样的代码
-
jsx有如下几种
-
变量
const name = 'Josh Perez'; const element = <h1>Hello, {name}</h1>;//遇到{}用JavaScript解析
-
对象(不直观)
const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!');
-
函数
const user = {firstName: 'Harper'}; function formatName(user) { return user.firstName;} const element = (<h1>Hello, {formatName(user)}!</h1>);
-
jsx中可以使用判断语句
-
if语句
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; 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') );
-
&&
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') );
-
三目运算符
render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in. </div> ); }
-
list,在使用map的时候通常设置key
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}> {number}</li> );
-
-
jsx中为标签添加属性值(class变成className)
const element = <div tabIndex="0"></div>; const element = <img src={user.avatarUrl}></img>;
-
3.React—component_props_state
-
组件可以作为标签存在的,必须以大写字母开头
-
在使用方法时,props作为方法的参数,自动封装传递给该方法的参数
-
为props设置默认值,通过
defaultProps
class Greeting extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } // 为属性指定默认值: Greeting.defaultProps = { name: 'Stranger' }; // 渲染 "Hello, Stranger": ReactDOM.render( <Greeting />, document.getElementById('example') );
-
-
state是类特有的私有属性,state的值发生变化时会重新加载组件
-
不能直接修改state的状态,修改的时候应该用setState(),state初始化的地方是构造函数。
this.state.comment = 'Hello';//错误 this.setState({comment: 'Hello'});//正确
-
-
函数式组件
function Welcome(props) {//props代表属性 return <h1>Hello, {props.name}</h1>; }
-
类组件(类中有方法和变量)
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
-
组件应用***组件都是以大写字母开头***
-
函数式组件
function Welcome(props) { return <h1>Hello, {props.name}</h1>; } const element = <Welcome name="Sara" />; ReactDOM.render( element, document.getElementById('root') );
-
类组件
-
将函数式组件改为类组件,类组件需要继承React.Component类,实现render方法,在render方法中this.props代替props
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } }
-
将类组件中props修改为state
-
替换props为state
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
-
添加构造方法,病初始化this.state
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } ... ...
-
一处Clock组件中的date属性
ReactDOM.render( <Clock />, document.getElementById('root') );
-
-
-
4.React—生命周期
componentDidMount()
组件输出到DOM后运行此方法,该方法放在类中componentWillUnmount()
组件即将消失前执行函数,同样放在类中
5.事件处理
-
React与传统的DOM不同之处
-
写法不同
<button onclick="activateLasers()"> Activate Lasers</button>//传统 <button onClick={activateLasers}>Activate Lasers</button>//react
-
React不能通过return false阻止行为
<a href="#" onclick="console.log('hello'); return false"> Click me</a>//传统 //react的写法 function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('The link was clicked.'); } return ( <a href="#" onClick={handleClick}>Click me</a>); }
-
事件处理完整例子
class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // 这个绑定是必要的,使`this`在回调中起作用 this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(state => ({isToggleOn: !state.isToggleOn})); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } ReactDOM.render( <Toggle />,document.getElementById('root'));
-
6.表单
-
<input>
,被控制,通过***state***,在操作表单中,如何难道目标标签的值class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
-
多个
<input>
标签,通过给每一个标签添加name属性class Reservation extends React.Component { constructor(props) { super(props); this.state = { isGoing: true, numberOfGuests: 2 }; this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } render() { return ( <form> <label> Is going: <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> </label> <br /> <label> Number of guests: <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> </label> </form> ); } }
-
<textarea>
,使用value复制class EssayForm extends React.Component { constructor(props) { super(props); this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Essay: <textarea value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
-
<select>
标签,同样使用value代表选中class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } }
7.组合
-
使用
props.children
来占位,进行元素传递function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ); } function WelcomeDialog() { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); }
-
使用自定义属性,进行元素传递
function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }
-
通过属性来传递元素
function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } function WelcomeDialog() { return ( <Dialog title="Welcome" message="Thank you for visiting our spacecraft!" /> ); }
8.深入JSX
-
React引用组件时,组件必须在这个作用域中,如果不在则手动引入
import React from 'react'; import CustomButton from './CustomButton'; function WarningButton() { // return React.createElement(CustomButton, {color: 'red'}, null); return <CustomButton color="red" />; }
-
通过.来组件
import React from 'react'; const MyComponents = { DatePicker: function DatePicker(props) { return <div>Imagine a {props.color} datepicker here.</div>; } } function BlueDatePicker() { return <MyComponents.DatePicker color="blue" />; }
-
在JSX中传递props
function App1() { return <Greeting firstName="Ben" lastName="Hector" />; } function App2() { const props = {firstName: 'Ben', lastName: 'Hector'}; return <Greeting {...props} />; }