初学注意的问题:
- 在JSX中只能有一个根标签
- index.css 是全局的样式
- APP.css 是组件的样式
- state用来改变值得状态
- 使用方法时在方法名后面加上()时方法会自动调用
- react中的this就是指向当前的类
=============================================
组件通信(属性传值)
组件:App.js
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
class App extends Component {
render() {
return (
<div className="App">
<h1>Hello</h1>
<Person name="山川川1号" count="10"/>
<Person name="山川川2号" count="20"/>
<Person name="山川川3号" count="30">山川川在学习React!</Person>
</div>
)
}
}
export default App;
组件:Person.js
import React from 'react';
const person = ( props ) => {
// props 是这里的形参也可以是其他名字,但一般经常使用props 更好的知道我们接收的是一个属性
return (
<div>
<p>大家好,我是{props.name};我已经有{props.count}个作品</p>
{/* 拿到props 下面的子元素 */}
<p>{props.children}</p>
</div>
)
}
export default person;
{/* 传递参数有两种方法 ,建议使用bind*/}
<button onClick={() => this.switchNameHandler("米修")}>更改状态值</button>
<button onClick={this.switchNameHandler.bind(this,"missyou")}>更改状态值</button>
state状态的使用
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state不能在Person.js组件使用,因为 state 只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{name:"川川4",count:40},
{name:"川川5",count:50},
{name:"川川6",count:60},
],
otherState:"anything"
}
// 定义方法
switchNameHandle = () => {
// 在ES6 函数中this就是指向当前的类
// 更改状态时需要用到 setState()方法
// 在这里只是更改persons里面的值
this.setState({
persons:[
{name:"山川川1",count:10},
{name:"山川川2",count:20},
{name:"山川川3",count:30},
],
})
}
render() {
return (
<div className="App">
<h1>Hello</h1>
{/*
这里的this.switchNameHandle 加上括号后会自动执行函数,正常不会加括号;
如果传对应的参数时会加上括号
*/}
// 点击事件,执行switchNameHandle方法
<button onClick={this.switchNameHandle}>更改状态值</button>
<Person
name={this.state.persons[0].name}
count={this.state.persons[0].count}/>
<Person
name={this.state.persons[1].name}
count={this.state.persons[1].count}/>
<Person
name={this.state.persons[2].name}
count={this.state.persons[2].count}>山川川在学习React!</Person>
</div>
)
}
}
export default App;
属性传值(传事件)
- 给事件传递参数
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{name:"川川4",count:40},
{name:"川川5",count:50},
{name:"川川6",count:60},
],
otherState:"anything"
}
// 定义方法
switchNameHandler = (newName) => {
// 在ES6 函数中this就是指向当前的类
// 更改状态时需要用到 setState()方法
// 在这里只是更改persons里面的值
this.setState({
persons:[
{name:newName,count:10},
{name:"山川川2",count:20},
{name:"山川川3",count:30},
],
})
}
render() {
return (
<div className="App">
<h1>Hello</h1>
{/*
这里的this.switchNameHandle 加上括号后会自动执行函数,正常不会加括号;
如果传对应的参数时会加上括号
*/}
{/* 传参 */}
{/* 1.使用ES6 箭头函数的方法 */}
{/* <button onClick={() => this.switchNameHandler("米修")}>更改状态值</button> */}
{/* 2. 使用bind方法 一般传参使用bind*/}
{/* bind(当前指向对象this,对应的名字) */}
<button onClick={this.switchNameHandler.bind(this,"山川川,哈哈哈")}>更改状态值</button>
</div>
)
}
}
export default App;
- 如何使用属性传值传递一个函数
组件:App.js
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{name:"川川4",count:40},
{name:"川川5",count:50},
{name:"川川6",count:60},
],
otherState:"anything"
}
// 定义方法
switchNameHandler = (newName) => {
// 在ES6 函数中this就是指向当前的类
// 更改状态时需要用到 setState()方法
// 在这里只是更改persons里面的值
this.setState({
persons:[
{name:newName,count:10},
{name:"山川川2",count:20},
{name:"山川川3",count:30},
],
})
}
render() {
return (
<div className="App">
<h1>Hello</h1>
{/* 使用属性传递函数 */}
<Person
myclick={this.switchNameHandler.bind(this,"山川川,真帅")}
name={this.state.persons[1].name}
count={this.state.persons[1].count}/>
</div>
)
}
}
export default App;
组件:Person.js
import React from 'react';
const person = ( props ) => {
// props 是这里的形参也可以是其他名字,但一般经常使用props 更好的知道我们接收的是一个属性
return (
<div>
{/* 这里接收myclick属性,所以点击这句会执行App.js中switchNameHandler方法 */}
<p onClick={props.myclick}>大家好,我是{props.name};我已经有{props.count}个作品</p>
</div>
)
}
export default person;
双向数据绑定
App.js
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{name:"川川4",count:40},
{name:"川川5",count:50},
{name:"川川6",count:60},
],
otherState:"anything"
}
// 定义方法
nameChangeHandle = (event) => {
this.setState({
persons:[
{name:event.target.value,count:10},
{name:"山川川2",count:20},
{name:"山川川3",count:30},
],
})
}
render() {
return (
<div className="App">
<h1>Hello</h1>
{/* 双向数据绑定 */}
<Person
changed={this.nameChangeHandle}
name={this.state.persons[0].name}
count={this.state.persons[0].count}/>
</div>
)
}
}
export default App;
Person.js
import React from 'react';
const person = ( props ) => {
// props 是这里的形参也可以是其他名字,但一般经常使用props 更好的知道我们接收的是一个属性
return (
<div>
{/* 双向数据绑定 , 这里需要使用defaultValue否则会报错*/}
<input type="text" onChange={props.changed} defaultValue={props.name}/>
</div>
)
}
export default person;
组件样式
1.直接引入样式
import './Person.css';
2.行间样式
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
render() {
// 定义样式
const style = {
backgroundColor: 'white',
font: 'inherit',
border: '1px solid blue',
padding: '8px',
cursor: 'pointer',
};
return (
<div className="App">
<h1>Hello</h1>
{/* 使用样式 */}
<button style={style} onClick={this.switchNameHandler.bind(this,"山川川,哈哈哈")}>更改状态值</button>
</div>
)
}
}
export default App;
使用分支if
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{name:"川川4",count:40},
{name:"川川5",count:50},
{name:"川川6",count:60},
],
otherState:"anything",
showPersons:false, // 定义一个状态
}
togglePersonHandle = () => {
const doesShow = this.state.showPersons;
this.setState({showPersons:!doesShow})
}
render() {
// 在render()里面定义
let persons = null;
if (this.state.showPersons){
persons = (
<div>
<Person
changed={this.nameChangeHandle}
name={this.state.persons[0].name}
count={this.state.persons[0].count}/>
{/* 使用属性传递一个函数 */}
<Person
myclick={this.switchNameHandler.bind(this,"山川川,真帅")}
name={this.state.persons[1].name}
count={this.state.persons[1].count}/>
<Person
name={this.state.persons[2].name}
count={this.state.persons[2].count}>山川川在学习React!</Person>
</div>
)
}
return (
<div className="App">
<h1>Hello</h1>
<button style={style} onClick={this.togglePersonHandle}>内容切换</button>
{/* 这里只return 重要的东西,代码定义到外部 ,在这里使用persons*/}
{persons}
</div>
)
}
}
export default App;
使用循环并实现删除和修改
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{id:1,name:"川川4",count:40},
{id:2,name:"川川5",count:50},
{id:3,name:"川川6",count:60},
],
otherState:"anything",
showPersons:false,
}
// 定义方法
switchNameHandler = (newName) => {
// 在ES6 函数中this就是指向当前的类
// 更改状态时需要用到 setState()方法
// 在这里只是更改persons里面的值
this.setState({
persons:[
{id:1,name:newName,count:10},
{id:2,name:"山川川2",count:20},
{id:3,name:"山川川3",count:30},
],
})
}
// 修改
nameChangeHandle = (event,id) => {
/*
拿到id就可以查找到更改哪一个对象的值
*/
// 1.找到index
const personIndex = this.state.persons.findIndex(p => {
return p.id === id;
})
// 2.在整个数组找到当前对象
const person = {
...this.state.persons[personIndex]
}
// 3.给当前对象的name进行赋值
person.name = event.target.value;
// 4.找到原型的数组
const persons = [...this.state.persons];
// 5.找到原型数组单独的,把修改的赋给它
persons[personIndex] = person;
this.setState({
persons:persons
})
}
togglePersonHandle = () => {
const doesShow = this.state.showPersons;
this.setState({showPersons:!doesShow})
}
deletePersonHandler = (personIndex) => {
// const persons = this.state.persons;
const persons = [...this.state.persons]
persons.splice(personIndex,1);
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
changed={(event) => this.nameChangeHandle(event,person.id)}
myclick={() => this.deletePersonHandler(index)}
key={person.id}
name={person.name}
count={person.count}/>
})
}
</div>
)
}
return (
<div className="App">
<h1>Hello</h1>
<button style={style} onClick={this.togglePersonHandle}>内容切换</button>
{persons}
</div>
)
}
}
export default App;
动态修改样式和添加类名
import React ,{Component}from 'react';
import './App.css';
import Person from './Person/Person';
/*
state 不能在Person.js组件使用,因为state只能在类中使用而且类也要继承于component;
Person.js只是一个函数
*/
class App extends Component {
/*
state: 用于改变组件内容状态的值(动态)
props: 用于组件通信进行传值
*/
// state状态
state = {
persons:[
{id:1,name:"川川4",count:40},
{id:2,name:"川川5",count:50},
{id:3,name:"川川6",count:60},
],
otherState:"anything",
showPersons:false,
}
// 定义方法
switchNameHandler = (newName) => {
// 在ES6 函数中this就是指向当前的类
// 更改状态时需要用到 setState()方法
// 在这里只是更改persons里面的值
this.setState({
persons:[
{id:1,name:newName,count:10},
{id:2,name:"山川川2",count:20},
{id:3,name:"山川川3",count:30},
],
})
}
nameChangeHandle = (event,id) => {
/*
拿到id就可以查找到更改哪一个对象的值
*/
// 1.找到index
const personIndex = this.state.persons.findIndex(p => {
return p.id === id;
})
// 2.在整个数组找到当前对象
const person = {
...this.state.persons[personIndex]
}
// 3.给当前对象的name进行赋值
person.name = event.target.value;
// 4.找到原型的数组
const persons = [...this.state.persons];
// 5.找到原型数组单独的,把修改的赋给它
persons[personIndex] = person;
this.setState({
persons:persons
})
}
togglePersonHandle = () => {
const doesShow = this.state.showPersons;
this.setState({showPersons:!doesShow})
}
deletePersonHandler = (personIndex) => {
// const persons = this.state.persons;
const persons = [...this.state.persons]
persons.splice(personIndex,1);
this.setState({
persons:persons
})
}
render() {
// 定义样式
const style = {
backgroundColor: 'green',
color: '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
changed={(event) => this.nameChangeHandle(event,person.id)}
myclick={() => this.deletePersonHandler(index)}
key={person.id}
name={person.name}
count={person.count}/>
})
}
</div>
)
// ==========================当showPersons 为true 按钮的颜色会变红=========
// 当showPersons 为true 按钮的颜色会变红
style.backgroundColor = 'red';
}
// ==================动态添加类名=================================
// const classes = ["red","bold"].join(" ") // class ="red bold"
// 动态添加类名
const classes = [];
if(this.state.persons.length <= 2){
classes.push("red");
}
if(this.state.persons.length <= 1){
classes.push("bold");
}
return (
<div className="App">
<h1>Hello</h1>
<p className={classes.join(" ")}>React,APP</p>
<button style={style} onClick={this.togglePersonHandle}>内容切换</button>
{persons}
</div>
)
}
}
export default App;
this.state 和 this.props
总结:由于this.props和this.state都用于描述组件的特性,可能会产生混淆;简单的区分方法:
this.props表示那些本组件无法改变的特性,而this.state是会随着用户互动而产生变化的特性。
有状态组件和无状态组件的区别
- 有状态组件
1、可以拥有状态
2、拥有生命周期
3、可以通过this来接受状态和属性this.state.AA this.props.AA
4、只有在需要管理状态,或者需要使用生命周期时在用
class AA extends component{ }
- 无状态组件
1、不可以拥有状态
2、不拥有生命周期
3、可以通过属性实现数据传递props.BB
const BB = (props) => { }
React生命周期钩子函数(有状态)
constructor()
调用父级
super(props)
设置状态state
componentWillReceiveProps()
componentWillUpadate
componentDidCatch
componentWillUnmount()
componentWillMount()
修改状态
shouldComponentUpdate
componentDidUpdate
-
componentDidMount()
组件更新完毕
不要更新状态 -
render()
创建虚拟DOM
更新DOM
constructor()
=>componentWillMount()
=> render()
=>componentDidMount()
生命周期钩子函数(更新)
componentWillReceiveProps(nextProps)
组件发生改变时触发
shouldComponentUpdate(nxPro,nxSta)
控件组件是否重新渲染
componentWillUpadate(nxPro,nxSta)
进入重新渲染流程
render()
更新与当前相关的子组件
componentDidUpdate(prevProps,prevState)
组件渲染完毕
========================================================================
后期继续更新整理