React-3-类式组件

组件

 对具有一定独立功能的数据和方法的封装,对外暴露接口,有利于代码功能的复用

1.组件的定义和渲染
函数组件
function assembly(){
	return <div>组件</div>
}
const assembly = <Assembly/>;
ReactDOM.render(
  assembly,
  document.getElementById('root')
);

 1.组件类必须继承 React.Component
 2.组件类必须有render方法
 3.render方法的return后定义组件的内容
 4.组件的名称必须大写
 5.导出

类式组件
import React,{Component} from 'react';

class App extends Component{    
    render(){
        return ...
    }
}
export default App;

或者

import React from 'react'

export default class App extends React.Component{
    render(){
        return 
    }
}

 在主入口js文件中,导入

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
3.props和state

props是父组件传递过来的参数
state是组件自身的状态
this.setState()
  参数1:一个函数或一个对象,修改的内容
  参数2:回调函数,更新成功后执行
  异步方法:react通常会集齐一批需要更新的组件,然后一次性更新来保证渲染的性能
  该方法的赋值属于浅合并(Objecr.assign()方法),只会进行指定属性的修改,并不是覆盖
 原数据

App.js文件
	import React,{Component} from 'react';
	import FriendList from './FriendList';
	
	export default class App extends Component{
	    render(){
	        return (
	            <div>
	            	//1.父组件传递参数,自定义属性名
	                <FriendList name="组件传参" />
	            </div>
	        )
	    }
	}
FriendList.js文件
	import React,{Component} from 'react';
	
	export default class Friend extends Component{
		//state的定义
		//	1.constructor构造函数中定义
		constructor(props){
			super(props);
			this.state={
				date:new Date()
			}
		}
		//	2.作为原型定义
		state=()=>{
			date:new Date()
		}
	    tick(){
	    	//state只读,无法直接修改
	        this.setState({
	          date: new Date()
	        });
	    }
	    render(){
	    	//2.props接收使用this.props
	    	let {name} = this.props
	    	//state接收使用this.state
	    	let {date} = this.state
	        return (
	            <div className="friend-list">
	                {date.toLocaleString()}
	                //标签内this为undefined,需要使用箭头函数改变this
	                <button onClick={()=>this.tick()}>点击更新时间</button>
	                {name}
	            </div>
	        )
	    }
	}
4.复合组件

 创建多个组件来合成一个组件,根据组件的功能或内容划分

function Name(props) {
    return <h1>名字:{props.name}</h1>;
}
function Age(props) {
    return <h1>年龄:{props.age}</h1>;
}
function Sex(props) {
    return <h1>性别:{props.sex}</h1>;
}
function App() {
    return (
    <div>
        <Name name="马拉卡" />
        <Age age=123 />
        <Sex sex="男" />
    </div>
    );
}
ReactDOM.render(
     <App />,
    document.getElementById('root')
);
5.组件的生命周期函数

 生命周期就是指某个事物从开始到结束的各个阶段,当在 React.js 中指的是组件从创建到销毁的过程
 React.js 在这个过程中的不同阶段调用的函数,通过这些函数,我们可以更加精确的对组件进行控制
 可分为三个阶段:挂载,更新,卸载

5-1挂载(mounting)

5-1-1 constructor
 类的构造函数,组件初始化函数,这个阶段会初始化state,处理事件绑定的this

5-1-2 static getDerivedStateFromProps(props,state)
 该方法会在render方法之前调用,代表数据将要开始挂载
 初始挂载及后续更新都会调用
 它需要返回一个对象更新state,返回null不更新内容
 ps:componentWillMount()方法16.3版本之前使用,不能与本方法同时使用

5-1-3render()方法
 组件中唯一必须实现的方法

5-1-4componentDidMount()方法
 组件挂载完成后调用

import React,{Component} from 'react';
	
export default class Friend extends Component{
	constructor(props){
		super(props);
		this.state={date:new Date()}
		console.log(1)
	}
	static getDerivedStateFromProps(){
		console.log(2,'将要挂载');
		return state;
	}
	componentDidMount(){
		console.log(4,'挂载完成')
	}
	render(){
		console.log(3,'数据渲染')
		return (
			<div></div>
		)
	}
}
5-2 数据更新

5-2-0 componentWillReceiveProps(nextProps)

 16.3版本之前使用,之后的版本使用加UNSAFE前缀
 父组件引起的子组件更新,16.3版本之前使用

5-2-1static getDerivedStateFromProps(props, state)

render方法之前调用,初始挂载及后续更新都会调用
 该方法不能与componentWillUpdate,componentWillReceiveProps同时出现,会报错

5-2-2shouldComponentUpdate(nextProps, nextState)

 当 props 或 state 发生变化时,该方法会在渲染执行之前被调用,首次渲染不调用
 返回值决定是否重新渲染
  true:重新渲染dom,下面的生命周期继续执行
  false:不渲染dom,更新结束

5-2-3 componentWillUpdate()

 16.3版本之前使用,之后的版本使用加UNSAFE前缀
 即将更新组件,接收到新的props或state但没有渲染时调用
 初始化时,不会调用,该方法中不能调用this.setState()

5-2-4render()

5-2-5getSnapshotBeforeUpdate(prevProps, prevState)
 该方法在 render() 之后,但是在输出到 DOM 之前执行
 该方法不能与componentWillUpdate,componentWillReceiveProps同时出现,会报错

5-2-6componentDidUpdate()
 更新完成后立即被调用

import React,{Component} from 'react'

export default class Child extends Component{
    state = {
        age:10
    }
    UNSAFE_componentWillReceiveProps(nextProps){
        console.log(0,"父组件引起的更新")
    }
    //组件的state或props改变
    shouldComponentUpdate(nextProps,nextState){
        console.log(1,'state或props改变');
        return true;
    }
    //即将更新组件,接收到新的props或state但没有渲染时调用
    UNSAFE_componentWillUpdate(nextProps,nextState){
        console.log(2,'组件即将更新')
    }
    componentDidUpdate(){
        console.log(4,'挂载完成')
    }
    changeAge=()=>{
        let {age} = this.state;
        this.setState({
            age:age+=1
        });
    }
    render(){
        let {age} = this.state;
        let {name,changeName} = this.props;
        console.log(3,"渲染");
        return (
            <div>
                <p>名字:{name}</p>
                <p>年龄:{age}</p>
                <button onClick={changeName}>升级</button>
                <button onClick={
                    ()=>this.changeAge()
                }>长一岁</button>
            </div>
        )
    }
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述

import React,{Component} from 'react'

export default class Child extends Component{
    state = {
        age:10
    }
    static getDerivedStateFromProps(props, state){
        console.log(0)
        return state
    }
    //组件的state或props改变
    shouldComponentUpdate(nextProps,nextState){
        console.log(1,'state或props改变');
        return true;
    }

    getSnapshotBeforeUpdate(){
        console.log(3.5,"render方法之后");
        return 11;
    }
    changeAge=()=>{
        let {age} = this.state;
        this.setState({
            age:age+=1
        });
    }
    componentDidUpdate(){
        console.log(4,'挂载完成')
    }
    render(){
        let {age} = this.state;
        let {name,changeName} = this.props;
        console.log(3,"渲染");
        return (
            <div>
                <p>名字:{name}</p>
                <p>年龄:{age}</p>
                <button onClick={changeName}>升级</button>
                <button onClick={
                    ()=>this.changeAge()
                }>长一岁</button>
            </div>
        )
    }
}

在这里插入图片描述

5-3卸载阶段

5-3-1componentWillUnmount()
 该方法会在组件卸载及销毁之前直接调用

app.js
import React,{Component} from 'react';
import Child from './child'

export default class App extends Component{
    state = {
        name:"baby",
        isShow:true
    }
    changeName=()=>{
        this.setState({
            name:"bigBaby"
        })
    }
    render(){
        let {name,isShow} = this.state
        return (
            <div>
                {isShow?<Child name = {name} changeName = {this.changeName}/>:''}
                <button onClick={()=>{
                    this.setState({
                        isShow:false
                    })
                }}>卸载</button>
            </div> 
        )
    }
}
class.js
import React,{Component} from 'react'

export default class Child extends Component{
    state = {
        age:10
    }
    toScroll(){
        console.log(111)
    }
    //渲染前调用
    componentWillMount(){
        console.log(1)
        window.addEventListener("resize",this.toScroll)
    }
    //在组件从 DOM 中移除之前调用
    componentWillUnmount(){
        console.log("组件即将卸载")
        window.removeEventListener("resize",this.toScroll)
    }
    changeAge=()=>{
        let {age} = this.state;
        this.setState({
            age:age+=1
        });
    }
    render(){
        let {age} = this.state;
        let {name,changeName} = this.props;
        console.log(3,"渲染");
        return (
            <div>
                <p>名字:{name}</p>
                <p>年龄:{age}</p>
                <button onClick={changeName}>升级</button>
                <button onClick={
                    ()=>this.changeAge()
                }>长一岁</button>
            </div>
        )
    }
}
5-4 错误处理

5-4-1static getDerivedStateFromError(error)
 后代组件抛出错误后被调用,渲染阶段被调用,

import React,{Component} from 'react'

export default class Child extends Component{
	constructor(props) {
		super(props);
    	this.state = { hasError: false };
	}
    static getDerivedStateFromError(error) {    
    	// 错误作为参数参数方法中
    	//返回一个对象更新state
    	return { hasError: true };  
    }
    render(){
        if (this.state.hasError) {      
            // 你可以渲染任何自定义的降级  UI      
            return <h1>Something went wrong.</h1>;    
        }
    	return this.props.children; 
    }
}

5-4-2componentDidCatch(error,info)
 此生命周期在后代组件抛出错误后被调用,提交阶段被调用
 参数1:抛出的错误
 参数2:带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息

6.组件传参
6-1子组件修改父组件数据

 可通过父组件给子组件传一个函数,子组件调用,来达成子组件修改父组件的参数

6-2 跨组件通信context

 新建一个js文件

context.js文件
import {createContext} from 'react'

let context = createContext();

let {Consumer,Provider} = context;

export default context
export {Consumer,Provider}

 传参

import React,{Component} from 'react';
import FriendList from './FriendList';
import {Provider} from './context'


export default class App extends Component{
    render(){
        return (
        	//Provider 是一个标签,包裹本页面的所有标签
        	//value 要传递的数据
            <Provider value={{
                info:'别浪'
            }}>
                <div>
                    <FriendList/>
                </div>
            </Provider>   
        )
    }
}

 接收参数

import React,{Component} from 'react'
import {Consumer} from './context'

export default class Dl extends Component{


    render(){
        return (
            <div>
                 <Consumer>
                     {(value)=>value.info}
                 </Consumer>
            </div>
        )
    }
}
7.受控组件

 受控组件:类似于Vue的双向数据绑定,数据视图互相影响
 非受控组件:类似于单项数据流,只可以数据改变视图

8.PureComponent

PureComponent提供了一个具有浅比较的 shouldComponentUpdate 方法,其他和 Component 完全一致

import React,{Component,PureComponent} from "react";

class App extends PureComponent(Component) {
		//Component使用
		//使用setState()进行操作时
		//可以es6的赋值写法,属性名值相同时,可以简写
		this.setState({arr})
		//PureComponent使用
		//浅比较:更新前后对比,不一样才会更新
		//使用setState()操作时,es6的方法无法生效
		this.setState({
			arr:[...arr]
		})
}
export default App;
9.refs

 旧版:
  绑定:<div ref='自定义'></div>
  使用:this.refs.自定义名称
 新版:
  设置:render方法外自定义名字=createRef()
  绑定:<div ref={this.自定义名字}></div>
  使用:this.自定义名字.current

import React,{Component,PureComponent, createRef} from "react";
class App extends PureComponent {
  //新版设置
  box = createRef();
  componentDidMount(){
    //旧版使用
    console.log(this.refs.box)
    //新版使用
    console.log(this.box.current)
  }
  render(){
    return (
      <div
      //旧版绑定
        ref='box'
      //新版绑定
        ref = {this.box}
      >
      </div>
    )
  }
}
export default App;
10.children

 组件标签对之间的内容会被当做一个特殊的属性 props.children 传入组件内容

import React,{Component,PureComponent} from "react";

class Child extends PureComponent{
  render(){
    let {children}=this.props
    return (
      <div>
      {children}
      </div>
    )
  }
}
class App extends PureComponent {
  render(){
    let {show,man} = this.state
    return (
      <div>
        	<Child>
				<h1>好累</h1>
	          	<p>真的好累</p>
	          	{'要死啦'}
	          	{[1,2,3]}
        	</Child> 
      </div>
    )
  }
}
export default App;

在这里插入图片描述

11.dangerouslySetInnerHTML

 直接设置标签的innerHTML

import React,{Component,PureComponent} from "react";

let message = `<div>憨批</div>`;
class App extends PureComponent {

  render(){

    return (
      //接收一个对象
      //接收后端发送 校检过的数据
      <div dangerouslySetInnerHTML={{
        __html:message
      }}>
      </div>
    )
  }
}
export default App;

在这里插入图片描述

12.key的问题

 在 React,组件每次更新时,会生成一个 虚拟DOM,和原有的虚拟DOM进行对比
 如果是批量生成的一组元素,那React就会根据key值去做对比
 一个列表中的每一项 key 是唯一的
 如果列表中发生顺序等操作变化,key 一定要用数据的id

import React,{Component,PureComponent} from "react";

class App extends PureComponent {

    state={
      data:[
        {id:0,content:'第1条数据'},
        {id:1,content:'第2条数据'},
        {id:2,content:'第3条数据'},
        {id:3,content:'第4条数据'},
        {id:4,content:'第5条数据'},
      ]
    }
  render(){
    let {data} = this.state
    return (
      <div>
        {
          data.map((item,index)=>{
            return (
            <div key={item.id}>
              {item.content}
              
              <a onClick={()=>{
                data = data.filter(itemData=>itemData.id!==item.id)
                this.setState({
                  data:[...data]
                })
              }}>删除</a>
              
            </div>)
          })
        }
      </div>
    )
  }
}
export default App;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值