react扩展及新特性

setState更新状态的2种写法

(1). setState(stateChange, [callback])------对象式的setState
            1.stateChange为状态改变对象(该对象可以体现出状态的更改)
            2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用
					
(2). setState(updater, [callback])------函数式的setState
           1.updater为返回stateChange对象的函数。
           2.updater可以接收到state和props。
           4.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。
总结:
1.对象式的setState是函数式的setState的简写方式(语法糖)
2.使用原则:
		(1).如果新状态不依赖于原状态 ===> 使用对象方式
		(2).如果新状态依赖于原状态 ===> 使用函数方式
		(3).如果需要在setState()执行后获取最新的状态数据, 
			要在第二个callback函数中读取
			
代码示例:
import React, { Component } from 'react'

export default class Demo extends Component {
	state = {count:0}
	add = ()=>{
		/* //1.获取原来的count值
		const {count} = this.state
		//2.更新状态
		this.setState({count:count+1},()=>{
			console.log(this.state.count);
		})
		//函数式的setState
		this.setState((state)=>{
            return {count:state.count+1}
        })
	}
	render() {
		return (
			<div>
				<h1>当前求和为:{this.state.count}</h1>
				<button onClick={this.add}>点我+1</button>
			</div>
		)
	}
}

路由懒加载(路由组件的lazyLoad)

//1.需要引入lazy,Suspense。
//2.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包
//3.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义loading界面
import React, { Component,lazy,Suspense} from 'react'
import {NavLink,Route} from 'react-router-dom'

// import Home from './Home'
// import About from './About'

import Loading from './Loading'
const Home = lazy(()=> import('./Home') )
const About = lazy(()=> import('./About'))

export default class Demo extends Component {
	render() {
		return (
			<div>
				<div className="row">
					<div className="col-xs-2 col-xs-offset-2">
						<div className="list-group">
							{/* 在React中靠路由链接实现切换组件--编写路由链接 */}
							<NavLink className="list-group-item" to="/about">About</NavLink>
							<NavLink className="list-group-item" to="/home">Home</NavLink>
						</div>
					</div>
					<div className="col-xs-6">
						<div className="panel">
							<div className="panel-body">
								<Suspense fallback={<Loading/>}>
									{/* 注册路由  需要Suspense 包裹*/}
									<Route path="/about" component={About}/>
									<Route path="/home" component={Home}/>
								</Suspense>
							</div>
						</div>
					</div>
				</div>
			</div>
		)
	}
}

Hooks

useState

import React ,{useState}from "react";

function Child1 () {
    const [count,setCount] =useState(0)
    let clickHandle=()=>{
        // 写法一:
        setCount(count+1)
        // 写法二:
        // setCount((count)=>{
        //     return count+1
        // })
    }
    return (
        <div>
            <div>{count}</div>
            <button onClick={clickHandle}>点我加1</button>
        </div>
    )
}


export default Child1

useEffect(模拟生命周期)

componentDidMount vs useEffect

类组件中,我们这样编写componentDidMount:

class Example extends React.Component {
  componentDidMount() {
    console.log('Did mount!');
  }
  render() {
    return null;
  }
}

在函数组件中,我们可以使用useEffect这样编写

import React ,{useEffect}from "react";
function Example() {
  // 注意不要省略第二个参数 [],这个参数保证函数只在挂载的时候进行,而不会在更新的时候执行。
  // 假如第二个参数为[num],会在初始化和num值改变时执行
  useEffect(() => console.log('mounted'), []);  
  return null;
}
componentDidUpdate vs useEffect

类组件中,我们这样编写componentDidUpdate:

componentDidUpdate() {
  console.log('mounted or updated');
}

而在函数组件中,我们使用useEffect起到同样的效果:

useEffect(() => console.log('mounted or updated'));  // 不需要指定第二个参数

值得一提的是,现在官方推荐的编程规范就是不区分 update 阶段和 mount 阶段,两个阶段视为一致。

componentWillUnmount vs useEffect

类组件中,我们这样编写componentWillUnmount:

componentWillUnmount() {
  console.log('will unmount');  
}

而在函数组件中,我们使用useEffect起到同样的效果:

useEffect(() => {
  return () => {
    console.log('will unmount');  // 直接使用return返回一个函数,这个函数在unmount时执行。
  }
}, []);

你也可以使用useEffect 组合componentDidMount 和 componentDidUnmount。

useEffect(()=>{
	console.log("mounted")return () => {
		console.log("unmounted");
	}
}, [Started])  // 前后两次执行的Started相等时,useEffect代码生效,否则跳过。

useRef

import React,{useRef} from 'react'
import ReactDOM from 'react-dom'

//类式组件
/* class Demo extends React.Component {
	myRef = React.createRef()
	show = ()=>{
		alert(this.myRef.current.value)
	}
	render() {
		return (
			<div>
				<input type="text" ref={this.myRef}/>
				<button onClick={this.show}>点击提示数据</button>
			</div>
		)
	}
} */
//函数组件:
function Demo(){
	const myRef = useRef()
	//提示输入的回调
	function show(){
		alert(myRef.current.value)
	}
	return (
		<div>
			<input type="text" ref={myRef}/>
			<button onClick={show}>点我提示数据</button>
		</div>
	)
}

export default Demo

Fragment (标签碎片,可以不用必须有一个真实的DOM根标签了,真正渲染时不存在此标签)

<Fragment><Fragment>
<></>

Context 一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信

使用

1) 创建Context容器对象:
	const XxxContext = React.createContext()  
	
2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
	<xxxContext.Provider value={数据}>
		子组件
    </xxxContext.Provider>
    
3) 后代组件读取数据:

//第一种方式:仅适用于类组件 
  static contextType = xxxContext  // 声明接收context
  this.context // 读取context中的value数据
  
//第二种方式: 函数组件与类组件都可以
  <xxxContext.Consumer>
    {
      value => ( // value就是context中的value数据
        要显示的内容
      )
    }
  </xxxContext.Consumer>

代码示例:

import React, { Component } from 'react'
import './index.css'

//创建Context对象
const MyContext = React.createContext()
const {Provider,Consumer} = MyContext
export default class A extends Component {

	state = {username:'tom',age:18}

	render() {
		const {username,age} = this.state
		return (
			<div className="parent">
				<h3>我是A组件</h3>
				<h4>我的用户名是:{username}</h4>
				<Provider value={{username,age}}>
					<B/>
				</Provider>
			</div>
		)
	}
}

class B extends Component {
	render() {
		return (
			<div className="child">
				<h3>我是B组件</h3>
				<C/>
			</div>
		)
	}
}

/* class C extends Component {
	//声明接收context
	static contextType = MyContext
	render() {
		const {username,age} = this.context
		return (
			<div className="grand">
				<h3>我是C组件</h3>
				<h4>我从A组件接收到的用户名:{username},年龄是{age}</h4>
			</div>
		)
	}
} */

function C(){
	return (
		<div className="grand">
			<h3>我是C组件</h3>
			<h4>我从A组件接收到的用户名:
			<Consumer>
				{value => `${value.username},年龄是${value.age}`}
			</Consumer>
			</h4>
		</div>
	)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值