当前位置: 首页 > news >正文

React学习(二)

文章目录

  • 1. React性能优化SCU
  • 2. 获取DOM方式refs
    • 2.1 获取原生DOM的三种方式
    • 2.2 获取组件实例
  • 3. 受控和非受控组件
    • 3.1 受控组件(推荐🌟)
      • 3.1.1 input
      • 3.1.2 checkbox (单选/多选)
      • 3.1.3 select
    • 3.2 非受控组件
  • 4. 高阶组件 hoc
    • 4.1 高阶组件写法定义
    • 4.2 应用场景
  • 5. 简要知识🧀
    • 5.1 Portals
    • 5.2 Fragment
    • 5.3 StrictMode(了解)
  • 6. 过渡动画
    • 6.1 react-transition-group
    • 6.2 CSSTransition
    • 6.3 SwitchTransition
    • 6.4 TransitionGroup

1. React性能优化SCU

先来了解一下React渲染流程和更新流程;

  • React的渲染流程:
    在这里插入图片描述
  • React的更新流程:
    在这里插入图片描述
    在这里插入图片描述
  • keys的优化:
    在这里插入图片描述
  • render的调用
    我们知道,当stateprops数据更新之后都会触发render(),但是其实有时候子组件没有使用到这些数据也会被迫更新,这就很浪费性能了。

所以React给我们提供一个生命周期函数shouldComponentUpdate,返回false的时候该组件就不会被更新,详细情况如下:
在这里插入图片描述
在这里插入图片描述
但是每次通过判断新旧数据是否一致来决定render()是否执行,这是在是太麻烦了,所以React又给我们提供了PureComponent来解决这种困扰。

怎么使用呢?
之前我们创建类组件总是继承自React.component,现在我们可以换成继承自PureComponent

import { Component,PureComponent } from 'react'
export class SetStateTest extends Component {
}// 改为
export class SetStateTest extends PureComponent {
}

在函数式组件中怎么解决这个问题呢? ----使用memo!!!

import ThemeContext from "./context/theme-context";
// 函数式组件const AppFunc = memo(function AppFunc() {// 返回值与类组件返回值一致return (...)
})export default AppFunc

这就是对React的性能优化(部分内容)了。


  • 使用PureComponent需要注意的地方:

在这里插入图片描述

2. 获取DOM方式refs

2.1 获取原生DOM的三种方式

一般我们不去获取原生DOM,但是这三种方式我们需要掌握。

  1. 第一种:传入一个createRef()定义的对象;
  2. 第二种:传入一个回调函数;
  3. 第三种:undefinenull
import { PureComponent, createRef } from 'react';export class HelloWorld extends PureComponent {render() {return (<div>HelloWorld</div>)}
}export class RefBind extends PureComponent {constructor(props) {super(props)this.titleRef = createRef()this.titleEl = null;}getDOMRef() {console.log('ref对象2', this.titleRef.current);console.log('ref对象3', this.titleEl);}render() {return (<div><h1>使用ref获取DOM</h1><h2 ref={this.titleRef}>ref对象1</h2><h2 ref={el => this.titleEl = el}>ref对象2</h2><button onClick={() => this.getDOMRef()}>获取ref对象</button></div>)}
}export default RefBind

注:React18+之后的字符串形式的ref已被弃用。

2.2 获取组件实例

学习了获取原生DOM的方法,那么同样的,我们也可以使用ref获取到组件实例

  1. 获取类组件实例
    获取类组件实例与获取原生DOM方法一样,这里的ref可以获取到整个组件实例
import { PureComponent, createRef, forwardRef } from 'react';export class HelloWorld extends PureComponent {test() {console.log('hw组件实例', this);}render() {return (<div>HelloWorld</div>)}
}export class RefBind extends PureComponent {constructor(props) {super(props)this.hwRef = createRef()}getDOMRef() {console.log('hw组件实例', this.hwRef.current.test());}render() {return (<div><h1>使用ref获取DOM</h1><HelloWorld ref={this.hwRef} /><button onClick={e => this.getDOMRef()}>获取HelloWorld组件实例</button></div>)}
}export default RefBind
  1. 获取函数式组件实例
    因为函数式组件没有实例,这里ref使用React.forwardRef()进行绑定,且只能获取到组件中的某个DOM
import { PureComponent, createRef, forwardRef } from 'react';const HelloWorldFunc = forwardRef(function (props, ref) {return (<div ref={ref}>HelloWorld</div>)
})export class RefBind extends PureComponent {constructor(props) {super(props)this.hwfRef = createRef()}getDOMRef() {console.log('hwf组件实例', this.hwfRef.current);}render() {return (<div><HelloWorldFunc ref={this.hwfRef} /><button onClick={e => this.getDOMRef()}>获取HelloWorld组件实例</button></div>)}
}export default RefBind

3. 受控和非受控组件

什么是受控组价?什么是非受控组件呢?

import { Component } from 'react'export class Control extends Component {constructor(props) {super(props)this.state = {name: 'cr'}}changeInput(e) {console.log(e.target.value)this.setState({name: e.target.value})}render() {const { name } = this.statereturn (<div><h1>受控组价和非受控组件</h1><h2>受控组件  name:{name}</h2><input type="text" value={name} onChange={e => this.changeInput(e)} /><h2>非受控组件</h2><input type="text" /></div>)}
}export default Control

这个案例中第一个input的value受我们的控制,第二个input自己维护自己的状态,不受我们控制,简单来说就是受控组件和非受控组件了。

3.1 受控组件(推荐🌟)

3.1.1 input

value值由我们自己控制时input就变成了受控组件。

import { Component } from 'react'export class Control extends Component {constructor(props) {super(props)this.state = {username: '',password: ''}}changeInput(e) {this.setState({[e.target.name]: e.target.value})}render() {const { username, password } = this.statereturn (<div><form action="#" onAbort={e => e.preventDefault()}><label htmlFor="username">用户名:<input type="text" name="username" id="username" value={username} onChange={e => this.changeInput(e)} /></label><br /><label htmlFor="password">密码:<input type="password" name="password" id="password" value={password} onChange={e => this.changeInput(e)} /></label></form ></div>)}
}

3.1.2 checkbox (单选/多选)

checkbox我们一般使用它的isChecked属性判断是否被选中;

import { Component } from 'react'export class Control extends Component {constructor(props) {super(props)this.state = {isAgree: false,hobbies: [{ id: "nail", value: '美甲💅', isChecked: false },{ id: "ktv", value: '唱K🎤', isChecked: false },{ id: "sleep", value: '睡觉💤', isChecked: false }]}}handleSubmit(e) {// 阻止默认事件发生e.preventDefault()console.log('同意协议', this.state.isAgree)console.log('爱好', this.state.hobbies.filter(hobby => hobby.isChecked).map(hobby => hobby.value))}// 单选changeAgree(e) {this.setState({isAgree: e.target.checked})}// 多选changeHobby(e, index) {const hobbies = [...this.state.hobbies]hobbies[index].isChecked = !hobbies[index].isCheckedthis.setState({hobbies})}render() {const { username, password, isAgree, hobbies } = this.statereturn (<div><form action="#" onSubmit={e => this.handleSubmit(e)}><label htmlFor="agree"><input type="checkbox" name="agree" id="agree" checked={isAgree} onChange={e => this.changeAgree(e)} />同意协议</label><div>爱好:{hobbies.map((hobby, index) => (<label htmlFor="nail" key={hobby.id}><input type="checkbox" name="hobby" id={hobby.id} onChange={e => this.changeHobby(e, index)} />{hobby.value}</label>))}</div><button>提交</button></form ></div>)}
}export default Control

3.1.3 select

select我们一般使用e.target.selectedOptions取获取多选选中的元素;

  • e.target.selectedOptions是伪数组;
  • 可以通过Array.from转化为数组再进行数据处理;
    在这里插入图片描述
    在这里插入图片描述

React推荐大多数情况下使用受控组件来管理表单数据:

  • 一个受控组件中,数据是由React组件来管理的;
  • 另一种是使用非受控组件,数据由原生DOM来管理;

如果要使用非受控组件,可以使用ref绑定DOM进行数据的获取和处理。

3.2 非受控组件

在这里插入图片描述

4. 高阶组件 hoc

学习过js高级的可能都了解高阶函数
在这里插入图片描述

同样的,高阶组件和高阶函数有异曲同工之处:

在这里插入图片描述

在这里插入图片描述

4.1 高阶组件写法定义

import { PureComponent } from "react"function enhancedComponent(OriginComponent) {class NewComponent extends PureComponent {constructor(props) {super(props)this.state = {userInfo: {name: "陈der",age: 18}}}render() {// this.props   ---  传递原本组件的props// this.state.userInfo  ---  高阶组件中定义的用户信息return (<OriginComponent {...this.props} {...this.state.userInfo} />)}}return NewComponent
}export default enhancedComponent

4.2 应用场景

  1. 高阶组件➕context
    我们知道使用context时会用到context.Provider或者context.Consumer,若是每次都写,那么将会产生大量重复的代码,所以我们可以使用高阶组件进行封装。下面是ThemeContext➕高阶组件的一个应用示例:
import ThemeContext from "../../context/theme-context"function withTheme(OriginComponent) {return (props) => {return (<ThemeContext.Consumer>{theme => <OriginComponent {...props} {...theme} />}</ThemeContext.Consumer>)}
}export default withTheme
  1. 登录鉴权

一般情况下,有些页面需要在登录状态下才能查看,这就需要在渲染前加判断是否展示相关页面,这时候我们就可以使用高阶组件,若登录则返回相关页面,若未登录就返回首页或其他状态提示页面。

function loginAuth(OriginComponent) {return props => {const token = localStorage.getItem('token')if (token) {return <OriginComponent {...props} />} else {return (<div><p>请先登录</p></div >)}}
}export default loginAuth
  1. 监听生命周期的执行
    在这里插入图片描述
    总结下来,高阶组件的作用就是拦截即将要渲染的组件,对数据状态等做加以判断再进行条件渲染。

回看之前学习的ref的转发,我们使用forwardRef接收转发传入的ref;
还有memo包裹函数式组件,替代类组件的PureComponent
这些都是高阶组件的用法

之后学习了Hooks可能HOC就不太需要了,但是初学还是需要了解一下。

5. 简要知识🧀

5.1 Portals

index.html中添加<div id="modal"></div>

import { PureComponent } from 'react';
import { createPortal } from 'react-dom';export class Modal extends PureComponent {render() {return (<div>{createPortal(this.props.children, document.querySelector("#modal"))}</div>)}
}export default Modal

5.2 Fragment

Fragment可作为render的根元素,在浏览器中不会像下图右侧情况出现div根元素。

在这里插入图片描述
key时可省略Fragment,有key时必须写完整用法。

// 完整写法<Fragment key={'Cart'}><h1>Cart</h1></Fragment>
// 简写<><h1>Cart</h1></>

5.3 StrictMode(了解)

我们知道在严格模式下js的代码检查会严格一些,React也为我们提供了StrictMode组件来代替use strict,主要能检测到的错误有以下几种情况:
在这里插入图片描述
了解即可,在代码书写规范的情况下也不一定需要。

6. 过渡动画

6.1 react-transition-group

在这里插入图片描述

 <button onClick={() => this.setState({ isShow: !isShow })}>切换</button><CSSTransitionnodeRef={nodeRef}in={isShow}classNames="fade"timeout={1000}unmountOnExit={true}appear={true}onEnter={el => console.log('进入')}onEntering={el => console.log('进入中')}onEntered={el => console.log('进入完成')}><h1 ref={nodeRef}>sugdfvsdbhvjs</h1></CSSTransition>
.fade-appear, .fade-enter{opacity: 0;
}.fade-appear, .fade-enter-active{opacity: 1;transition: opacity 1000ms;
}.fade-exit{opacity: 1;
}
.fade-exit-active{opacity: 0;transition: opacity 1000ms;
}

6.2 CSSTransition

CSSTransition常见属性:

  • in:触发进入或者退出状态
    • 如果添加了unmountOnExit=true,那么该组件会在执行退出动画结束后被移除掉:
    • 当in为true时,触发进入状态,会添加-enter、.enter-.acitve的class开始执行动画,当动画执行结束后,会移除两个class,并旦添加-enter-done的class;
    • 当in为falsel时,触发退出状态,会添加-exit.-exit-active的class开始执行动画,当动画执行结束后,会移除两个class,并且添加-enter-done的class;
  • classNames:动画class的名称
    • 决定了在编写css时,对应的class名称:比如card-enter、card-enter-active、card-enter-done;
  • timeout:过渡动画的时间
  • appear:
    • 是否在初次进入添加动画(需要和in同时为true)
  • unmountOnExit:退出后卸载组件
  • 其他属性可以参考官网来学习:
    https://reactcommunity.org/react-transition-group/css-transition/
  • CSSTransition对应的钩子函数:主要为了检测动画的执行过程,来完成一些JavaScript的操作
    • onEnter:在进入动画之前被触发,
    • onEntering:在应用进入动画时被触发;
    • onEntered:在应用进入动画结束后被触发;

6.3 SwitchTransition

在这里插入图片描述

<SwitchTransition mode='out-in'><CSSTransitionkey={isShow ? 'login' : 'exit'} // 通过key来区分不同的元素nodeRef={nodeRef}in={isShow}classNames="login"timeout={1000}unmountOnExit={true}><button ref={nodeRef} onClick={() => this.setState({ isShow: !isShow })}>{isShow ? 'login' : 'exit'}</button></CSSTransition></SwitchTransition>
.login-enter{transform: translateX(-100px);opacity: 0;
}.login-enter-active{transition: all 1000ms ease;opacity: 1;transform: translateX(0);
}.login-exit{transform: translateX(0);opacity: 1;
}
.login-exit-active{transition: all 1000ms ease;opacity: 0;transform: translateX(100px);
}

6.4 TransitionGroup

在这里插入图片描述

http://www.dtcms.com/a/416490.html

相关文章:

  • 京东网站建设思维导图网站中的幻灯片ie6显示 ie7如何兼容
  • 什么网站做海宁的房产好网站维护费一年多少钱
  • 房产中介网站开发做韩国护的网站
  • 建网站软件网站后台怎么修改代码
  • 信息门户网站建设电商型网站
  • 专业做w7系统的网站上海设立企业网站
  • C4D储卡器底部塑料壳建模之外部解析
  • 建设电商平台网站企业 wordpress 主题
  • 汕头网站设计浩森宇特wordpress插件收录
  • 甘肃建设厅网站二级建造师报名时间维拓设计在北京排名
  • 网上怎么自己做网站商城网站开发价格
  • 梧州seo排名成都网站优化最低价
  • 手工做女宝宝衣服的网站百度竞价项目
  • 国外客户推广网站wordpress添加价格
  • 行知智网站建设基于云平台网站群建设
  • R2U:通过过程监督优化文档改写,弥合 RAG 系统中检索相关性与生成效用差距
  • 515.在每个树行中找最大值(二叉树算法题)
  • 云南高端网站建设wordpress评论头像问题
  • flash网站下载长沙 网站优化
  • 温州营销网站制作费用王占郡
  • Vala编程语言高级特性-错误处理
  • 建设网站公司建网页商城网站数据库表关系设计
  • 网站源码上传图片出错WordPress中英文旅游模板
  • 网站开发 价格差异想招聘员工去哪个网站
  • 外贸做的社交网站有哪些网站系统开发毕业设计
  • 响应式设计 手机网站wordpress个性首页
  • 网站制作怎么做语音搜索框wordpress更改生成小图大小
  • 文登建设局网站wordpress 主题开发环境
  • 网站开发公司建站源码网页开发需求定制
  • 湘潭网站建设 皆来磐石网络免费中文网站模板