一:React面向组件编程
1:定义组件
react定义组件的两种方式:函数式组件,类式组件
a.函数式组件
注意:
函数首字母要大写
一定要有返回值
执行了 ReactDOM.render(<Dome/>,...)之后发生了什么事
第一步:react解析组件标签,找到Dome组件
第二步:发现组件是函数式组件,随后调用该函数,将返回的虚拟DOM转为真实的DOM,然后渲染到页面
注意:此函数里的this指向不是window,而是undefined。因为babel编译开启了严格模式
b.类式组件
执行了 ReactDOM.render(<Dome/>,...)之后发生了什么事
第一步:react解析组件标签,找到Dome组件
第二步:发现组件是类式组件,随后new出个该类的实例,并通过实例调用原型上的render方法
第三步:将render返回的虚拟DOM转为真实DOM,渲染到页面中
注意:
render放在那里,放在该类的原型对象上
render方法中的this是什么,是这个类的实例对象,即组件实例对象
2:组件实例的三大属性
什么是简单组件,什么是复杂组件。
看组件有无状态(state),有状态的是复杂组件,无状态的是简单组件
函数式组件适用于简单组件,
类式组件适用于复杂组件
1).三大属性之一状态state
this是实例对象里面包含着state
如何往state里赋值呢?
赋完值如何获取值?
案例:注意:非常重要一定要明白
class Dome extends React.Component{
constructor(props){
super(props)
//状态初始化
this.state={
isHot:true,
}
//解决add中this的指向问题
this.eve = this.add.bind(this)
}
// 方法add放在什么地方,放在该类的原型对象上
// 因为add是作为onClick的回调函数,所以add里的this指向的不是该类的实例对象,
// 所以this,state获取不到该类的状态
// 类中的方法默认开启了局部的严格模式,所以类中的方法this没有指向,即undefined
add(){
//因为通过构造函数里的bind()方法改变了this的指向,所以该方法中的this指向了该类的实例
const isHot=this.state.isHot
// 注意!!状态不可以直接更改
// 即直接更改:this.state.isHot=!isHot
// 用setState更改
this.setState({
isHot:!isHot
})
}
render(){
const {isHot}=this.state
return <h1 onClick={this.eve}>今天天气很{isHot?'炎热':'凉爽'}</h1>
}
}
ReactDOM.render(<Dome/>,document.querySelector('#text'))
注意点一:函数的事件绑定
推荐使用传统方式onClick,绑定函数用 { },注意函数不要加括号直接调用,这个函数调的不是该类的原型对象上的方法,调的是该类构造函数里的一个属性,将该类的原型对象上的方法在通过bind赋值给该属性,
注意点二:为什么要通过bind赋值呢?
答:注意类中this指向问题,类的构造函数(constructor)里的this指向的是该类的实例对象,
而类中的其他方法开启了局部严格模式,所以类中的其他的方法在没有被调用时就没有指向,即undefined,如果该方法被调用了,则该方法中的this就指向该方法的调用者
注意点三:不能直接修改状态(state)里的值
直接修改状态里的值是不会被React认可的,所以要解药React的内置API,setState()
this.setState({
属性:值
})
简化写法
class Dome extends React.Component{
//初始化状态
state = {
ishot:true
}
// 自定义方法用赋值语句写,用箭头函数
add = () => {
const isHot=this.state.isHot
this.setState({
isHot:!isHot
})
}
render(){
const {isHot}=this.state
return <h1 onClick={this.add}>今天天气很{isHot?'炎热':'凉爽'}</h1>
}
}
state总结
1)state是组件对象最重要的属性之一,值是对象,可以包含多个键值对组合
2)state是组件的状态机,通过跟新组件里的state来更新对应的页面显示(重新渲染)
3)组件里的rende方法中的this是实例对象
4)组件里的自定义方法中this的值为undefined,如何解决
a.强制指定this,通过bind方法
b.箭头函数
5)state数据不能直接更改
2).三大属性之一props
props用于接收组件外的值
基本用法
限制props规则
注意:peops是只读的不能修改
不能直接修改,但可以在渲染的时候进行运算
如果要传递的数据特别多怎么办?
用展开运算符 。。。
拓展知识:展开运算符。。。
注意:展开运算符不能展开对象
在React要想展开对象怎么展
额外加上{}
相当于克隆对象
仅仅用于标签传值
还可以在复制的过程中改值
props简写
上面代码的peops规则写在类的外面,如果想写在里面怎么写
Person.propTypes就相当于给这个Person类添加了一个propTypes属性,注意是给这个类添加属性而不是这个类的实例对象添加属性
对props进行限制,先引入 prop-types
import PropTypes from 'prop-types';
构造器与props
构造器是否接收props,是否传递super,取决于是否在构造器中通过this使用props
函数式组件使用props
3).三大属性之一ref
给组件内标签一个唯一标识,类似于Dom的id
可以通过ref获取Dom元素
ref的调用方式
第一种:字符串类型(这个方式已经过时了,可能在react以后的版本被优化掉)
第二种:回调函数方式
箭头函数里的a就是该DOM节点,直接传到该类自身上,而不是refs中
内联函数式
注意写成内联函数,重新渲染的时候里面的回调函数会执行俩次
class绑定函数式
这个方式可以避免调两次问题
第三种:官方API 方式React.createRef()
React.createRef调用后可以返回一个容器这个容器可以存储被ref所标识的节点
注意:React.createRef类似于专人专用,每次只存一个
3:事件处理
1):通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件,而不是使用原生DOM事件
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
2):通过event.target得到发生事件的DOM元素对象
注意可以通过绑定事件函数,获取当前元素
4:收集表单数据
要理解两个概念,受控组件,非受控组件
1)什么是非受控组件
即现用现取
2)什么是受控组件
即非现用现取
5:高阶函数和函数柯里化
高阶函数:如果一个函数符合下面两个条件中的任何一个,那该函数就是一个高阶函数
1):若函数A,接收的参数是一个函数,则A就是一个高阶函数
2):若函数A,调用的返回值是一个函数,则A就是一个高阶函数
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
案例
简化:使用非柯里化
二:组件的生命周期
即生命周期回调函数,生命周期钩子函数,生命周期函数,生命周期钩子
简单的小示例
1:旧版本的生命周期
constructor:构造器函数,组件挂载时第一个执行
componentWillMount:组件挂载前
componentDidlMount:组件挂载后
componentWillUnmount:组件销毁前
shouldComponentUpdate:控制状态是否可以更新
返回值为false时状态禁止更新,后续不会在执行接下来的生命周期钩子
返回值为true时状态允许更新,后续继续执行接下来的生命周期钩子
this.state()普通跟新流程:shouldComponentUpdate =》componentWillUpdate =》render=》componentDidUpdate
this.forceUpdate强制更新流程:componentWillUpdate =》render=》componentDidUpdate
强制更新会跳过:shouldComponentUpdate
注意:此时shouldComponentUpdate返回值为false,但是forceUpdate依然触发了componentWillUpdate
componentWillReceiveProps():子组件将要接收父组件新的props
注意:组件第一次初始化传进去的props次生命周期不执行,是接收新的props才会执行改函数
父组件
子组件
总结:组件生命周期主要分为三个阶段
1)初始化阶段:由ReactDOM.render()触发,初次渲染
1.constructor()
2.componentWillMount()
3.render()
4.componentDidMount()常用
一般在这个钩子中进行一些初始化操作,列:开启定时器,网络请求,订阅信息
2)更新阶段:由组件内部的this.setState或父组件render触发
1.shouldComponentUpdate()
2.componentWillUpdate()
3.render()常用
4.componentDidUpdate()
3)卸载阶段:由React.unmountComponentAtNode()触发
1.componentWillUnmount()常用
一般在这个钩子中进行一些收尾操作:列关闭定时器,取消订阅
2:新版本的生命周期
getDerivedStateFromProps:
从props那里得到一个衍生的状态,当state的值取决于prpos
时可以使 用该函数。
getSnapshotBeforeUpdate:在更新之前获取快照(快照就是值),传给componentDidUpdate(props,state,value)第三个参数
新生命周期总结:
1)初始化阶段:ReactDOM.render()触发
1.constructor()
2.getDerivedStateFromProps()注意:要定义成静态的
3.render()
4.componentDidMount()
2)更新阶段:由组件内部this.setState()或父组件的render()触发
1.getDerivedStateFromProps()
2.shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate()
5.componentDidUpdate()
3)卸载阶段:由React.unmountComponentAtNode()触发
1.componentWillUnmount()常用
3:生命周期总结
最常用的几个钩子
1)render:初始化渲染或更新渲染调用
2)componentDidMount:组件挂载后。开启监听,发起ajax请求
3)componentWillUnmount:组件销毁时调用