React 1-6
the official React documentation: https://reactjs.org/
Here's the finished source code: https://codepen.io/anon/pen/MELQaQ
2.14 Arrow Function:
const print = (name) =>{
console.log(name);
}
only one argument: 只有一个参数可以省略括号
const print = name =>{
console.log(name);
}
no arg:
const print = () =>{}
const multiply = number => number * 2
console.log(multiply(2));
3. Export Import
Classes, Properties and Method
class Person extends Human { constructor(){ super(); this.name='max'; } printMyName() { console.log(this.name); } }
等于
class Person extends Human{ name='max'; print = () => console.log(this.name); }
3.39 Props &State
3.43 manipulating state
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value' }; switchNameHandler = () => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState({ persons: [ { name: 'Maximilian', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] }); }; render() { return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button onClick={this.switchNameHandler}>Switch Name</button> <Person name={this.state.persons[0].name} age={this.state.persons[0].age} /> <Person name={this.state.persons[1].name} age={this.state.persons[1].age} > My Hobbies: Racing </Person> <Person name={this.state.persons[2].name} age={this.state.persons[2].age} /> </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
person.js
import React from 'react'; const person = ( props ) => { return ( <div> <p>I'm {props.name} and I am {props.age} years old!</p> <p>{props.children}</p> </div> ) }; export default person;
class-based
因为用()=>这种语法 给一个property一个function 所以this可以用 否则不可以
{this.switchNameHandler}不加括号,加了是瞬间渲染的,不加是调用时作为reference
click={this.switchNameHandler.bind(this, 'Max!')} bind 后面是一个参数列表传进function
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value' } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ { name: newName, age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event) => { this.setState( { persons: [ { name: 'Max', age: 28 }, { name: event.target.value, age: 29 }, { name: 'Stephanie', age: 26 } ] } ) } render () { return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button onClick={() => this.switchNameHandler('Maximilian!!')}>Switch Name</button> <Person name={this.state.persons[0].name} age={this.state.persons[0].age} /> <Person name={this.state.persons[1].name} age={this.state.persons[1].age} click={this.switchNameHandler.bind(this, 'Max!')} changed={this.nameChangedHandler} >My Hobbies: Racing</Person> <Person name={this.state.persons[2].name} age={this.state.persons[2].age} /> </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
import React from 'react'; const person = ( props ) => { return ( <div> <p onClick={props.click}>I'm {props.name} and I am {props.age} years old!</p> <p>{props.children}</p> <input type="text" onChange={props.changed} value={props.name} /> </div> ) }; export default person;
two way binding
3.48 Adding Styling
需要import css into js file
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ { name: newName, age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event) => { this.setState( { persons: [ { name: 'Max', age: 28 }, { name: event.target.value, age: 29 }, { name: 'Stephanie', age: 26 } ] } ) } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } render() { const style = { backgroundColor: 'white', font: 'inherit', border: '1px solid blue', padding: '8px', cursor:'pointer' }; return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> { this.state.showPersons ? <div > <Person name={this.state.persons[0].name} age={this.state.persons[0].age} /> <Person name={this.state.persons[1].name} age={this.state.persons[1].age} click={this.switchNameHandler.bind(this, 'Max!')} changed={this.nameChangedHandler} >My Hobbies: Racing</Person> <Person name={this.state.persons[2].name} age={this.state.persons[2].age} /> </div> :null } </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
more elelgant way 判断
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ { name: newName, age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event) => { this.setState( { persons: [ { name: 'Max', age: 28 }, { name: event.target.value, age: 29 }, { name: 'Stephanie', age: 26 } ] } ) } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } render() { const style = { backgroundColor: 'white', font: 'inherit', border: '1px solid blue', padding: '8px', cursor:'pointer' }; let persons = null; if(this.state.showPersons){ persons = ( <div> <Person name={this.state.persons[0].name} age={this.state.persons[0].age} /> <Person name={this.state.persons[1].name} age={this.state.persons[1].age} click={this.switchNameHandler.bind(this, 'Max!')} changed={this.nameChangedHandler} >My Hobbies: Racing</Person> <Person name={this.state.persons[2].name} age={this.state.persons[2].age} /> </div> ); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> { persons} </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
3.56 Outputting lists (turn into jsx object)
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ { name: newName, age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event) => { this.setState( { persons: [ { name: 'Max', age: 28 }, { name: event.target.value, age: 29 }, { name: 'Stephanie', age: 26 } ] } ) } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } render() { const style = { backgroundColor: 'white', font: 'inherit', border: '1px solid blue', padding: '8px', cursor:'pointer' }; let persons = null; if(this.state.showPersons){ persons = ( <div> {this.state.persons.map(person => { return <Person name={person.name} age={person.age} />//jsx object })} </div> ); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> {persons} </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
delete list
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ { name: 'Max', age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ { name: newName, age: 28 }, { name: 'Manu', age: 29 }, { name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event) => { this.setState( { persons: [ { name: 'Max', age: 28 }, { name: event.target.value, age: 29 }, { name: 'Stephanie', age: 26 } ] } ) } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } deletePersonHandler = (personIndex) => { const persons = this.state.persons; persons.splice(personIndex, 1);//删除数组中的元素,在index的地方删除一个元素 this.setState({ persons: persons }); } render() { const style = { backgroundColor: 'white', font: 'inherit', border: '1px solid blue', padding: '8px', cursor:'pointer' }; let persons = null; if(this.state.showPersons){ persons = ( <div> {this.state.persons.map((person,index) => { return <Person click={() => this.deletePersonHandler(index)}//function带参数 必须那么写 name={person.name} age={person.age} />//jsx object })} </div> ); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> {persons} </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
map(a,b) a是元素,b是索引
会报warning,改进:
deletePersonHandler = (personIndex) => { const persons = this.state.persons; persons.splice(personIndex, 1);//删除数组中的元素,在index的地方删除一个元素 this.setState({ persons: persons });
因为object 和array 是 reference type
persons有着上面persons的索引
然后下面修改的是索引。
好的步骤是先复制一个 然后再修改 而不是直接修改索引
const persons = this.state.persons.slice(); slice()复制array 然后赋给persons
3.60 Flexible List
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; class App extends Component { state = { persons: [ {id:'1', name: 'Max', age: 28 }, {id:'2', name: 'Manu', age: 29 }, {id:'3', name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ {name: newName, age: 28 }, {name: 'Manu', age: 29 }, {name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event, id) => { const personIndex = this.state.persons.findIndex(p => { return p.id === id;//这个看不懂 }); const person = { ...this.state.persons[personIndex] }; person.name = event.target.value; const persons = [...this.state.persons]; persons[personIndex] = person; this.setState({ persons: persons }); } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } deletePersonHandler = (personIndex) => { const persons = this.state.persons.slice(); //const persons = [...this.state.persons]; persons.splice(personIndex, 1); this.setState({ persons: persons });///bhb } render() { const style = { backgroundColor: 'white', font: 'inherit', border: '1px solid blue', padding: '8px', cursor:'pointer' }; let persons = null; if(this.state.showPersons){ persons = ( <div> {this.state.persons.map((person,index) => { return <Person click={() => this.deletePersonHandler(index)} name={person.name} age={person.age} key={person.id}//key 是保留字吗 changed={(event)=>this.nameChangedHandler(event,person.id)} />//jsx object??? })} </div> ); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> {persons} </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
5.67 Styling Class Dynamic
//let classes = [ 'red','bold'].join(' '); let classes = []; if (this.state.persons.length <= 2) { classes.push('red');//push red 给这个array } if (this.state.persons.length <= 1) { classes.push('bold'); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p className={classes.join(' ')}>This is really working!</p> <button style={style} onClick={this.togglePersonsHandler}>Switch Name</button> {persons} </div> );
5.70 Styled Components
import React from 'react'; /*import './Person.css';*/ /*import Radium from 'radium';*/ import styled from 'styled-components'; const StyledDiv = styled.div` width:60%; margin:16px; border:1px solid #eee; box-shadow: 0 2px 3px #ccc; padding: 16px; text-align: center; `;// 这已经是一个三方库形成的react component了 所以不需要用function括住它 const person = ( props ) => { return ( /*<div className="Person">*/ <StyledDiv> <p onClick={props.click}>I'm {props.name} and I am {props.age} years old!</p> <p>{props.children}</p> <input type="text" onChange={props.changed} value={props.name} /> </StyledDiv> ) }; export default person;
同时要改动代码成为css,因为不再用jsx进行渲染
import React, { Component } from 'react'; import './App.css'; import Person from './Person/Person'; import styled from 'styled-components'; const StyledButton = styled.button` background-color: ${props => props.alt ? 'red' : 'green'}; color: white; font: inherit; border: 1px solid blue; padding: 8px; cursor: pointer; &:hover { background-color: ${props => props.alt?'blue':'salmon'}; color: black; } `; class App extends Component { state = { persons: [ {id:'1', name: 'Max', age: 28 }, {id:'2', name: 'Manu', age: 29 }, {id:'3', name: 'Stephanie', age: 26 } ], otherState: 'some other value', showPersons: false } switchNameHandler = (newName) => { // console.log('Was clicked!'); // DON'T DO THIS: this.state.persons[0].name = 'Maximilian'; this.setState( { persons: [ {name: newName, age: 28 }, {name: 'Manu', age: 29 }, {name: 'Stephanie', age: 27 } ] } ) } nameChangedHandler = (event, id) => { const personIndex = this.state.persons.findIndex(p => { return p.id === id;//这个看不懂 }); const person = { ...this.state.persons[personIndex] }; person.name = event.target.value; const persons = [...this.state.persons]; persons[personIndex] = person; this.setState({ persons: persons }); } togglePersonsHandler = () => { const doesShow = this.state.showPersons; this.setState({showPersons: !doesShow}); } deletePersonHandler = (personIndex) => { const persons = this.state.persons.slice(); //const persons = [...this.state.persons]; persons.splice(personIndex, 1); this.setState({ persons: persons });///bhb } render() { let persons = null; if(this.state.showPersons){ persons = ( <div> {this.state.persons.map((person,index) => { return <Person click={() => this.deletePersonHandler(index)} name={person.name} age={person.age} key={person.id}//key 是保留字吗 changed={(event)=>this.nameChangedHandler(event,person.id)} />//jsx object??? })} </div> ); /*style.backgroundColor = 'red';*/ /* style[':hover']= { backgroundColor: 'salmon', color: 'black' }*/ } //let classes = [ 'red','bold'].join(' '); let classes = []; if (this.state.persons.length <= 2) { classes.push('red');//push red 给这个array } if (this.state.persons.length <= 1) { classes.push('bold'); } return ( <div className="App"> <h1>Hi, I'm a React App</h1> <p className={classes.join(' ')}>This is really working!</p> <StyledButton alt={this.state.showPersons} onClick={this.togglePersonsHandler}>Switch Name</StyledButton> {persons} </div> ); // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?')); } } export default App;
6.81 Debugging
import React, { Component } from 'react'; class ErrorBoundary extends Component { state = { hasError: false, errorMessage:'' } componentDidCatch = (error, info) => { this.setState({ hasError: true, errorMessage: error }); } render() { if (this.state.hasError) { return <h1>{this.state.errorMessage}</h1>; } else { return this.props.children;//这是执行它的子类吗 } } } export default ErrorBoundary;
{this.state.persons.map((person,index) => { return <ErrorBoundary key={person.id}><Person click={() => this.deletePersonHandler(index)} name={person.name} age={person.age} //key 是保留字吗 changed={(event)=>this.nameChangedHandler(event,person.id)} /></ErrorBoundary>//jsx object??? })}