# react相关
# react 函数调用时this的指向
# 在constructor中给函数绑定this
import * as React from "react";
export default class EventTest extends React.Component{
constructor(props) {
super(props)
this.state = {
name:'kira'
}
//constructor只会执行一次bind绑定也只会发生一次
this.myClick = this.myClick.bind(this)
}
myClick = ()=>{
console.log('---',this.state.name)
}
render() {
return(
<div onClick={this.myClick}>
button
</div>
)
}
}
# 在jsx中给事件绑定this
问题,但是每次函数调用时候都会进行bind绑定,效率不高
render() {
return(
<div onClick={this.myClick.bind(this)}>
button
</div>
)
}
# 通过箭头函数绑定this
问题,但是每次函数调用时候都会进行bind绑定,效率不高
//箭头函数
myClick = ()=>{
console.log('---',this.state.name)
}
render() {
return(
<div onClick={this.myClick}>
button
</div>
)
}
# setState同步异步问题
# react的异步更新
myClick =()=>{
console.log('state',this.state.name)
this.setState({
state:'test'
})
//此时获取到的state仍然是kira
console.log('---this.state.name',this.state.name)
}
render() {
return(
<div onClick={this.myClick}>
button
</div>
)
}
# 在setTimeOut中更新state
//在setTimeOut中更新state获取的值是同步的
myClick =()=>{
setTimeout(()=>{
this.setState({
name:'test'
})
console.log('---this.state.name',this.state.name)
},0)
}
# 在事件的回调函数中setState
componentDidMount() {
document.body.addEventListener('click',()=>{
this.setState({
name:'test'
})
console.log('---this.state.name',this.state.name)
})
}
# react的event事件
- fn(参数1,参数2,event),event会在函数末尾追加一个event参数供咱们调用。
- react中的event和原生的event的不同,是自己封装的。
myClick =(event)=>{
//阻止默认行为(比如打开链接),但是会冒泡。
event.preventDefault();
//阻止冒泡
event.stopPropagation();
console.log('event', event.target)
console.log('currentTarget', event.currentTarget)
}
render() {
return(
<a href={this.state.url} onClick={this.myClick}>
button
</a>
)
}
# react的父子组件
- 关于state的状态数据提升,一般state数据都是存在父组件中,通过props传递给子组件,子组件完成动作(子组件一般只完成渲染和提交状态 ),在通知父组件更新数据。 -通过props传值 传方法 约定props的类型
//父组件
<Child list={this.state.list} onSubmit={this.onSubmit}/>
//子组件
export default class Child extends React.Component{
constructor(props) {
super(props);
}
render() {
const { list,onSubmit } = this.props;
return(
<div>
{
list.map(item=>{
return(
<li key={item.id} onClick={onSubmit}>{item.name}</li>
)
})
}
</div>
)
}
}
# 函数组件
输入props,渲染组件。
//函数组件
function Child(props){
const { list,onSubmit } = this.props;
return(
<div>
{
list.map(item=>{
return(
<li key={item.id}>{item.name}</li>
)
})
}
</div>
)
}
//class组件
export default class Child extends React.Component{
constructor(props) {
super(props);
}
render() {
const { list,onSubmit } = this.props;
return(
<div>
{
list.map(item=>{
return(
<li key={item.id}>{item.name}</li>
)
})
}
</div>
)
}
}
# 类组件 vs 函数组件
- 函数组件没有实例 没有生命周期 没有state和setState 只能接收props(接收props 返回jsx)
- class组件 大型组件难拆分,难测试。相同的业务分散个个方法中。
- 函数组件倡导 view = fn(props);更灵活 易拆分 更易测试。但没有生命周期 没有实例需要通过hooks增强其功能。
- 函数组件是一个纯函数 执行完即销毁 无法存储state。
//类组件
class List extend React.Component {
constructor(props){
super(props);
}
render (){
const {List } = this.props;
return <ul>{list.map((c)=>{return <li>c</li>})}</ul>
}
}
//函数组件
function List(props){
const {list} = props;
return <ul>{list.map((c)=>{return <li>c</li>})}</ul>
}
//纯函数使用hooks
import React,{useState} from "react"
export function ClickController(){
const [count,setCount] = useState(0);
return <div>
<div>点击次数{count}</div>
<button onClick={()=>{setCount(count + 1 )}}>点击</button>
</div>
}
# useEffect
- useEffect 通过[]、[a,b]模拟mount 和 update
- useEffect 无依赖或者依赖[a,b],组件更新时执行fn
- 下次执行useEffect之前,就会执行fn,无论更新或者卸载
export function ClickController(){
const [count,setCount] = useState(0);
useEffect(()=>{
console.log('参数[] 模拟componentDidMount')
console.log()
},[])
useEffect(()=>{
console.log('参数[count] 模拟update,count更新之后调用');
},[count])
//exprot function clickController(){
}
useEffect(()=>{
const timer = window.setInterval(()=>{
console.log(Date.now())
},1000)
//通过返回一个fn 模拟componentWillUnMount
return ()=>{
window.clearInterval(timer)
}
},[])
return <div>
<div>点击次数{count}</div>
<button onClick={()=>{setCount(count + 1 )}}>点击</button>
</div>
}
# shouldComponentUpdate
shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。
在react中只要父组件发生变化,无论子组件是否更新,都会默认被自动更新。为了避免性能浪费,shouldComponentUpdate主要通过浅比较state判断变化返回true/false控制子组件是否更新。
import React, {Component} from 'react'
class APP extends Component {
constructor(props) {
super(props)
this.state = {
count: 0,
name: 'XX'
}
}
// 是否进行更新的生命周期,它有两个参数,它允许我们自定义是否更新,默认返回true
// nextProps:更新后的props属性
// nextState: 更新后的state状态
shouldComponentUpdate(nextProps, nextState) {
// 现在设置只有count改变时,才触发重新渲染
if(nextState.count === this.state.count) {
return false;
}
return true;
}
render() {
const { count, name } = this.state
// 第二个为要放至的dom元素位置
return <div>
<p>count: {count}</p>
<p>name: {name}</p>
<button onClick={this.changeCount}>累加count</button>
<button onClick = {this.changeName}>不改变count,改变其它state状态</button>
</div>
}
changeCount = () => {
this.setState({count: this.state.count + 1})
}
changeName = () => {
this.setState({name: '小小'})
console.log(this.state.name)
}
}
export default App
PureComponent 是个性能优化的组件,会自动对 shouldComponentUpdate中的state进行浅比较,判断是否更新
import from 'react'
class App extends React.PureComponent{ {
constructor(props) {
super(props)
this.state = {
count: 0,
name: 'XX'
}
}
}
export default App
← 响应式Reactive webpack配置 →