生命周期函数
componentWillMount
在组件渲染之前执行
componentDidMount
在组件渲染之后执行
shouldComponentUpdate
返回true/false,true代表允许改变,false代表不允许改变
componentWillUpdate
数据在改变之前执行(state,props)
componentDidUpdate
数据修改完成(state,props)
componentWillReceiveProps
props发生改变执行
componentWillUnmount
组件卸载前执行
app.jsx
// 引入react库
import React from "react"
//引入组件
import Home from "./home"
import MyNav from "./MyNav"
import StateComponent from "./StateComponent"
import ComponentLife from "./ComponentLife"
// 用类的形式创建组件
class App extends React.Component{
constructor(){
super();
this.state ={
title:"文本1"
}
}
clickChange =()=>{
this.setState({
title:"文本2"
})
}
// 渲染函数
render(){
const nav1 = ["首页","视频","学习"];
const nav2 = ["WEB","JAVA","PHP"];
return(
<div>
{/* <h1>Hello React Component</h1>
<h3>学习react</h3>
<Home />
<MyNav nav={ nav1 } title="路径导航"/>
<MyNav nav={ nav2 } title="学习导航"/> */}
{/* <StateComponent /> */}
<ComponentLife title={ this.state.title}/>
<button onClick={ this.clickChange }>修改title</button>
</div>
)
}
}
// 导出组件
export default App
ComponentLife.jsx
import React from "react"
export default class ComponentLife extends React.Component{
constructor(props){
super(props);
this.state ={
count:10
}
}
componentWillMount (){
console.log("componentWillMount");
}
componentDidMount (){
console.log("componentDidMount");
}
shouldComponentUpdate (){
console.log("shouldComponentUpdate");
return true ;
}
componentWillUpdate (){
console.log("ComponentWillUpdate");
}
componentDidUpdate (){
console.log("ComponentDidUpdate");
}
componentWillReceiveProps (){
console.log("ComponentWillReceiveProps");
}
componentWillUnmount (){
console.log("ComponentWillUnmount");
}
changeHandler =()=>{
this.setState({
count:this.state.count+=1
})
}
render(){
const { count } =this.state;
return(
<div>
生命周期函数:{ count } -{ this.props.title }
<button onClick={ this.changeHandler }>修改</button>
</div>
)
}
}
当props发生改变时,执行了componentWillReceiveProps
子传父
可以通过props向父组件传值
app.jsx 这是父组件
// 引入react库
import React from "react"
//引入组件
import Home from "./home"
import MyNav from "./MyNav"
import StateComponent from "./StateComponent"
import ComponentLife from "./ComponentLife"
// 用类的形式创建组件
class App extends React.Component{
constructor(){
super();
this.state ={
title:"文本1"
}
}
clickChange =(data)=>{
this.setState({
title:data
})
}
// 渲染函数
render(){
const nav1 = ["首页","视频","学习"];
const nav2 = ["WEB","JAVA","PHP"];
return(
<div>
{/* <h1>Hello React Component</h1>
<h3>学习react</h3>
<Home />
<MyNav nav={ nav1 } title="路径导航"/>
<MyNav nav={ nav2 } title="学习导航"/> */}
{/* <StateComponent /> */}
< ComponentLife title={ this.state.title} clickChanges={ this.clickChange }/>
</div>
)
}
}
// 导出组件
export default App
ComponentLife.jsx 这是子组件
import React from "react"
export default class ComponentLife extends React.Component{
constructor(props){
super(props);
this.state ={
count:10
}
}
componentWillMount (){
console.log("componentWillMount");
}
componentDidMount (){
console.log("componentDidMount");
}
shouldComponentUpdate (){
console.log("shouldComponentUpdate");
return true ;
}
componentWillUpdate (){
console.log("ComponentWillUpdate");
}
componentDidUpdate (){
console.log("ComponentDidUpdate");
}
componentWillReceiveProps (){
console.log("ComponentWillReceiveProps");
}
componentWillUnmount (){
console.log("ComponentWillUnmount");
}
changeHandler =()=>{
this.setState({
count:this.state.count+=1
})
}
clickChange =()=>{
this.props.clickChanges('我是儿子的数据');
}
render(){
const { count } =this.state;
return(
<div>
生命周期函数:{ count } -{ this.props.title }
<button onClick={ this.changeHandler }>修改</button>
<button onClick={ this.clickChange }>修改title</button>
</div>
)
}
}
<button onClick={ this.clickChange }>修改title</button>
这段代码原来是父组件中的,如果写在子组件中,通过props定义一个clickChanges传到父组件中
子组件定义的props
clickChange =()=>{
this.props.clickChanges('我是儿子的数据');
}
父组件中< ComponentLife title={ this.state.title} clickChanges={ this.clickChange }/>
同时传送的数据可以发生改变,直接将title定义为data
clickChange =(data)=>{
this.setState({
title:data
})
}
setState的更新问题
setState会引起视图的重绘
setState在可控的情况下是异步,在非可控的情况下是同步
app.jsx
// 引入react库
import React from "react"
//引入组件
import Home from "./home"
import MyNav from "./MyNav"
import StateComponent from "./StateComponent"
import ComponentLife from "./ComponentLife"
import SetStateDemo from "./setStateDemo"
// 用类的形式创建组件
class App extends React.Component{
constructor(){
super();
this.state ={
title:"文本1"
}
}
clickChange =(data)=>{
this.setState({
title:data
})
}
// 渲染函数
render(){
const nav1 = ["首页","视频","学习"];
const nav2 = ["WEB","JAVA","PHP"];
return(
<div>
{/* <h1>Hello React Component</h1>
<h3>学习react</h3>
<Home />
<MyNav nav={ nav1 } title="路径导航"/>
<MyNav nav={ nav2 } title="学习导航"/> */}
{/* <StateComponent /> */}
{/* < ComponentLife title={ this.state.title} clickChanges={ this.clickChange }/> */}
<SetStateDemo />
</div>
)
}
}
// 导出组件
export default App
这是使用异步方法实现数据的更新
import React from "react"
export default class SetStateDemo extends React.Component{
constructor(){
super();
this.state ={
count:0
}
}
increment =()=>{
this.setState({
count:this.state.count+1
},()=>{
console.log(this.state.count);
})
}
// async increment(){
// await this.setStateAsync({count:this.state.count+1});
// console.log(this.state.count);
// }
// setStateAsync(state){//自己定义一个同步方法
// return new Promise((resolve)=>{
// this.setState(state,resolve);
// })
// }
render (){
return(
<div>
setState同步还是异步问题
<p> { this.state.count } </p>
<button onClick={ this.increment.bind(this) }> 修改 </button>
</div>
)
}
}
注释掉的代码是使用同步方法实现数据的更新,实现的效果是相同的,自己定义一个同步方法setStateAsync
async increment(){
await this.setStateAsync({count:this.state.count+1});
console.log(this.state.count);
}
setStateAsync(state){//自己定义一个同步方法
return new Promise((resolve)=>{
this.setState(state,resolve);
})
}
条件渲染
常用的应用场景有两个:一种是对视图条件进行切换,另一种是做缺省值
用户登录页面的切换就是第一种应用场景
还是在app.jsx中引入组件
import IfDemo from "./ifDemo"
并在return返回值中使用组件
<IfDemo />
ifDemo.jsx
import React from "react"
export default class IfDemo extends React.Component{
constructor(){
super();
this.state={
isLogin:false
}
}
ClickHandler =() =>{
this.setState({
isLogin:true
})
}
render(){
let showView =this.state.isLogin?
<div>iven</div> :
<div>请登录</div>
return(
<div>
条件渲染:{ showView}
<button onClick={ this.ClickHandler}>登录</button>
</div>
)
}
}
另一种做缺省值的场景,是数据在传递时可能会出现空的情况,这时需要对数据进行判断
ifDemo.jsx
import React from "react"
export default class IfDemo extends React.Component{
constructor(){
super();
this.state={
isLogin:false,
names:["iven","ime"]
}
}
ClickHandler =() =>{
this.setState({
isLogin:true
})
}
render(){
const { names } =this.state;
let showView =this.state.isLogin?
<div>iven</div> :
<div>请登录</div>
return(
<div>
条件渲染:{ showView}
<button onClick={ this.ClickHandler}>登录</button>
{
names.length >0?
<div>
{
names.map((element,index) =>{
return <p key={index}>{ element}</p>
})
}
</div>
:
<div>请等待数据正在读取....</div>
}
</div>
)
}
}
列表渲染
明确设置key的值会对数据有什么影响:
1.key是用来帮助react识别哪些内容被更改、添加或者删除。key需要写在用数组渲染出来的元素内部,并且需要赋予其一个稳定的值。如果key值发生了变更,react则会触发UI的重渲染。
2.在相邻的元素间,key值必须是唯一的,若出现了相同的key值,会抛出警告,告诉相邻组件间有重复的key值,且只会渲染第一个重复key值中的元素,因为react会认为后续拥有相同key值的都是同一个组件。
3.虽然我们在组件上定义了key值,但是在其子组件中,我们并没有办法拿到key值,因为key值仅仅是给react内部使用的。如果我们需要使用到key值,可通过其他方式传入,比如将key值赋值给id等。
同样的还是在app.jsx中引入组件
import KeyDemo from "./KeyDemo"
并在return返回值中使用组件
<KeyDemo />
KeyDemo.jsx
import React from "react"
export default class KeyDemo extends React.Component{
constructor(){
super();
this.state ={
userinfo:[
{
name:'iven',
age:20,
sex:'男',
jobs:['11','222','333']
},
{
name:'inco',
age:27,
sex:'男',
jobs:['19','999','323']
},
{
name:'ime',
age:24,
sex:'女',
jobs:['18','345','563']
}
]
}
}
clickHandler =() =>{
this.setState({
userinfo:this.state.userinfo.concat([{
name:"sakura",
age:30,
sex:"女",
jobs:['333','444','555']
}])
})
}
render(){
return(
<div>
<ul>
{
this.state.userinfo.map((element,index) =>{
return(
<li>
<span> { element.name } </span>
<span> { element.age } </span>
<span> { element.sex } </span>
<div>
{
element.jobs.map((childElement,childIndex) =>{
return <span key={ childIndex}> { childElement }</span>
})
}
</div>
</li>
)
})
}
</ul>
<button onClick={ this.clickHandler }>添加数据</button>
</div>
)
}
}