跳转至

类组件

原理#

组件就是封装了html、css、js 及其其他多媒体资源的集合,做到自给自足,按数据而动

类组件,被react发现后,new出来一个实例对象,这个实力对象中挂载了React提供的一些属性和你自定义的一些挂载到原型链上的方法,
并且在render()方法中,返回类似html的标签,这便是虚拟dom了
类组件的核心是通过继承React.Component,得到组件的能力

需要提前复习的是,this永远指向调用它的那个实例
render里的this指向类的实例对象
render()中用到的数据this.state,恰好是这个类组件实例的构造器constructor()中放入实例中的,后边你会看到它也可以以自定义类属性的形式放到类的实例上,(这里区别与函数组件,函数组件上是没有this的)
所以可以在render()中,通过解构赋值的方式拿到具体的某个值,
render是被React调用的,自定义的函数被事件绑定了,但是不是React调用的

class Weather extends React.Component{
  constructor(props){
   super(props)
   this.state= {isHot:false}
  }
  render(){ const {isHot} = this.state return <h1>今天天气很{isHot'炎热':'凉爽'}</h1> }
}

this的指向问题#

我们预期的是将方法全部放到类里边,这样this就是类组件实例的,在实例中调用其内部的方法,得用this.functionName这种方式类中方法中的this
构造器中的this一定是当前类的实例对象
render是被new的实例对象调用,
类中方法中的this
由于自定义函数是作为onClick的回调,所以不是通过实例调用的,是直接调用,
类中所有自定义的方法,它自局部开好了严格模式
所以自定义函数中的this指向undefined
解决方式
this.changeWeather=this.changWeather.bind(this)

constuctor#

构造器是否接受props,是否传递props,取决于:是否希望在构造器中通过this访问props,(类实例中props,不是实参props)
类组件中的构造器能不写就不写,如果写的话,必须传递prop,并且调用super(props)

组件实例上三个重要属性#

  • state,状态,组件实例对象身上的数据
  • props,本组件之外传递过来的数据
  • refs
  • context

state#

state之所以是state,是因为他只能通过setState传递,并且这个更新是一个合并操作,不是更新操作,只是修改部分键值对,其他的键值对会原样奉还

🤚state函数的最佳实践
类组件属性 箭头函数的this
类中自定义的属性,可以直接传递到类的实例当中
类中通过箭头函数定义的方法,其箭头函数内部this指向和外部的一致,在这里就是类的实例
这样就规避了反复通过bind(),一次一次的将原型链中的自定义方法绑定到类实例上的反复操作

class MyComponets extends React.component{
  constuctor{

   }

  state={age:12,name:'kobe',isHOt:true}

  render(){
   const {isHot} = this.state
   return <h1 onClick={changeWeather}>今天天气很{isHot'炎热':'凉爽'}</h1>
  }

  const changeWeather=()=>{
    this.state.isHot=!this.state.isHot
  }

}

props#

通过在jsx的html标签中,传递属性
可以通过修改属性值,渲染出多个不同的组件
props是只读的,不能对其进行修改

🤚基础操作

class Person extends React.Componet{
  render(){
  const {name,age} = this.props
  return (
     <ul> 
        <li>姓名{this.props.name}
        <li>年龄{age}
     <ul>
  )
  }
ReactDom.render(<Person name="kobe" age="12">,document.getElementById('app'))
ReactDom.render(<Person name="tmac" age="18">,document.getElementById('app'))

🤚批量传递

批量传递props,是可以用jsx语法中的对象展开...object,
这里区别于es6
这里区别于ES6的三点展开,那个只能展开数组,jsx中的 就是展开此对象,
当在组件属性中传递Number类型是,要用{},括起来,转化为js,因为只有js中才存在类型,jsx中的html属性传递的是字符串的键值对

class Person extends React.Componet{
  render(){
  const {name,age} = this.props
  return (
     <ul> 
        <li>姓名{this.props.name}
        <li>年龄{age}
     <ul>
  )
  }
 ReactDom.render(<Person name="kobe",age={19}>,document.getElementById('app'))
 const p={name:'kobe',age:12} 
 ReactDom.render(<Person {...p}>,document.getElementById('app'))

🤚对props进行限制
1. 对传递的标签属性进行类型限制
2. 必要性限制
3. 指定默认值
在React中通过在类组件中添加组件。propTypes,添加规则

<script type="text/javascript" src="../js/prop-types.js"></script>

<script type="text/babel">
class Person extends React.Component{
  //....
}

//限制类型和必要性
Person.propTypes={
 name:React.ProTypes.string,  //React<=15
 name:ProTypes.string.isRequired,  //React>=16,引入单独的`prop-types.js`
 age:ProTypes.number,
 sex:ProTypes.string.isRequired,//限制sex必传且为字符串
 speak:Protypes.func, //方法也可以规范之
}
//指定默认值
Person.defaultProps={
  sex:'男',
  age18
}
</script>

将一个属性加到类本身上,和将一个属性加到类的实例上方式是不一样的类自身加属性

class Car{
  constuctor(name,price){
    this.name=name
    this.price=price
  }
  wheel=4 //在类中直接写赋值语句,是给car的实例对象添加一个属性
  static test =100 //在其前边添加 static 是给这个类本身,而不是加给类的实例
}

🤚 props最佳实践完整版本

class Person extends React.Component{
  static propTypes={
     name:React.ProTypes.string,  //React<=15
     name:ProTypes.string.isRequired,  //React>=16,引入单独的`prop-types.js`
     age:ProTypes.number,
     sex:ProTypes.string.isRequired,//限制sex必传且为字符串
     speak:Protypes.func, //方法也可以规范之
  }
  static defaultProps={
     sex:'男',
     age:18
  }
  render(){
    // .... 
  }
}

ref#

一句话,ref是用来在react中拿到最后渲染传来的真实dom节点的,拿到之后可以对齐做一些dom操作

🤚String类型的ref
多见于verson 16.8之前
jsx的html标签中,打入ref=''标签
React将会收集jsx中所有的ref,放入类实例对象中的this.refs
this.refs中通过解构赋值的形式拿到当前dom节点

class Person extends React.Component{
    const {test}=this.refs
    render(){
        <div>
            <h1 ref="test"></h1>
        </div>
    }
}

🤚回调函数方式的ref
通过在ref标签上写匿名函数的方式,拿到当前Dom当前节点

class Person extends React.Component{
    render(){
        <div>
            //通过箭头函数的方式,将当前节点挂载到当前类实例自身上
            <input ref={currentNode=>{this.input1=currentNode}}></input>
        </div>
    }
}

事件绑定#

原生dom事件绑定 React中的事件绑定

原生事件绑定#

//第一种方法
const btn1=doncument.getElementById('btn1')
   btn1.addEventListener('click',()=>{
   alert('按钮1被点击了')
})

//第二种方法
const btn2=doncument.getElementById('btn2')
    btn2.onclick=()=>{
    alert('按钮2被点击了')
}

React事件绑定#

React中的事件绑定,因为React把事件指向了类组件之外的一个函数,作为回调,这个函数是拿不到类组件中的this的,所有有一个本办法是,在constuctor中将that=this,将this缓存到一个全局变量中,
再在事件函数中调用that.state
类组件中的render方法返回的类似html结构的JSX中,将html的标签的属性都额外定义了一边,以React自身解析之用,例如onclick>onClick,class>className,这里简单复习,原生的两种绑定点击时间的方法

//第三种,在React中,请用一下方式
//html中一些原生标签属性,在jsx中都有其替代品,例如这里的onclick==>onClick
//注意这里的函数名不要加(),执行它
let that;
class Demo extends React.Componet{
  render(){
  const {isHot} = this.state
  return <h1 onClick={changeWeather}>今天天气很{isHot'炎热':'凉爽'}</h1>
  }

function changeWeather(){
  that.state.isHot=!that.state.isHot;
}

生命周期#

经典钩子#

React16
1. 初始化阶段,由ReactDOM.render()触发---初次渲染
1. contructor()
2. componentWillMount()
3. render()
4. componetDidMount()
a. 常用,页面加载完毕后,做一些初始化的事
b. 开启定时器,发送网络请求,订阅消息
1. 更新阶段:由组件内部this.setState()父组件重新render触发
0. componentWillReceviceProps,在首次不触发,二次更新state,会触发这个钩子
1. shouldComponentUpdate() (阀门),其中返会的布尔值,生命是否往下流动
2. componetWillUpdate(), 注意通过foreceUpdate()可触发强制更新,绕过阀门
3. render()
4. componentDidUpdate()
3. 卸载阶段:由ReactDOM。unMountComponentAtNode()触发
1. componentWillUnmount()
a. 常用,一般在此钩子中,做一些收尾阶段的事
b. 关闭定时器,取消消息
Pasted image 20230717085313.png
Pasted image 20230718091536.png

增强钩子#

新版本的React17
生命周期钩子有所改变
1. componetWillMount()改名为UNSAFE_componentWillMount(),并且不被推荐使用
2. componentWillReceviceProps改名为UNSAFE_componentWillReceviceProps(),并且不被推荐使用
3. componentWillUpdate改名为UNSAFE_componentWillUpdate()
4. 最重要的三个钩子render componentDidMount(出生) componentWillUnmount(将死),在React17,没有改变

Pasted image 20230717154659.png

对比#

Pasted image 20230717165143.png
挂载阶段
getDerivedStateFromProps====>componentWillMount
更新阶段
getDerivedStateFromProps====>componentWillReceviceProps'getDerivedStateFromProps横跨了挂载和更新,从props`得到一个派生的状态.它还是一个static 静态方法,给类自身添加的函数,

新旧生命周期相比,废弃了三个钩子,提出了两个新钩子,getDerivedStateFromPropsgetSnaphotBeforeUpdate,且一般使用不到,是给开发者用的,相当于简化了日常的使用