React—8—受控组件和非受控组件;高阶组件
一、概念
我的理解是,是否有react提供数据,分为受控组件和非受控组件。
比如input元素,只要绑定了value属性,那么在react中,用户在输入框输入的值不会显示在输入框(react应该做了限制,原生html的input框即使value绑定了值依然可以输入),
这就导致,想改变value的值,必须监听onChange事件,然后再onChange事件里拿到用户输入的值然后再去改变message,然后value才改变。
二、使用受控组件来使用表单
import React, { PureComponent, createRef, forwardRef } from 'react'; // 编写一个组件 class App extends PureComponent { constructor() { super(); this.state = { username: '', password: '', isAgeree: false, hobbies: [ { value: 'sing', text: '唱', isChecked: false }, { value: 'dance', text: '跳', isChecked: false }, { value: 'rap', text: 'rap', isChecked: false } ], fruit: '', fruits: [] }; } handleSumbit = event => { // 先阻止默认的事件提交。 event.preventDefault(); console.log(this.state) }; handleChange = e => { // 对于类型为text或者password的输入框, 可以给input框绑定一个name属性值,然后可以通过可以e.target.name获取绑定的name属性值。 // 通过e.target.value获取到输入框的值 console.log('[ ] >', e.target, e.target.name); const { name, value } = e.target; this.setState({ [name]: value }); }; handleCheckBox = e => { // 对于checkbox类型的输入框, 可以通过e.target.checked获取到是否选中的ture或false; e.target.value没有值。 const { checked } = e.target; this.setState({ isAgeree: checked }); }; handleHobbies = (e, index) => { console.log(e); const hobbies = [...this.state.hobbies]; hobbies[index]['isChecked'] = e.target.checked; this.setState({ hobbies }); }; handleSelect(event) { // seleced选中的值在event.target.selectedOptions.value const fruit = event.target.selectedOptions.value; this.setState({ fruit }); } handleSelectMultiple(event) { //多选情况下,seleced选中的值在event.target.selectedOptions是一个集合,需要先用array.from转化为一个数组,这样就可以用数组的方法了。 const selectedArr = Array.from(event.target.selectedOptions); const fruits = selectedArr.map(e => e.value); this.setState({ fruits }); } render() { const { username, password, isAgeree, hobbies, fruit, fruits } = this.state; return ( <div> <form onSubmit={e => this.handleSumbit(e)}> {/* 受控组件---输入框 */} <div> <label htmlFor="username"> 用户名: <input type="text" name="username" value={username} onChange={e => this.handleChange(e)} /> </label> <label htmlFor="password"> 密码: <input type="password" name="password" value={password} onChange={e => this.handleChange(e)} /> </label> </div> {/* 受控组件---单选框 */} <input type="checkbox" checked={isAgeree} onChange={e => this.handleCheckBox(e)} /> 同意协议 {/* 受控组件---多选框 */} <div> {hobbies.map((item, index) => { return ( <div key={item.text}> <input type="checkbox" id={item.value} checked={item.isChecked} onChange={e => this.handleHobbies(e, index)} /> {item.text} </div> ); })} </div> {/* 受控组件---下拉框()单选 */} <select name="" id="" value={fruit} onChange={e => this.handleSelect(e)}> <option value="orange">橘子</option> <option value="bnana">香蕉</option> <option value="putao">葡萄</option> </select> {/* 受控组件---下拉框()多选 按住ctrl键可以实现多选 */} <select name="" id="" value={fruits} onChange={e => this.handleSelectMultiple(e)} multiple> <option value="orange">橘子</option> <option value="bnana">香蕉</option> <option value="putao">葡萄</option> </select> <button type="submit">登录</button> </form> </div> ); } } export default App;
三、高阶组件hoc
3.1什么是高阶组件
什么是高阶组件呢?
相信很多同学都知道(听说过?),也用过 高阶函数, 它们非常相似,所以我们可以先来回顾一下什么是 高阶函数。
高阶函数的维基百科定义:至少满足以下条件之一:
- 接受一个或多个函数作为输入;
- 输出一个函数;
JavaScript中比较常见的filter、map、reduce都是高阶函数。
那么说明是高阶组件呢?
高阶组件的英文是 Higher-Order Components,简称为 HOC;
官方的定义:高阶组件是参数为组件,返回值为新组件的函数;
我们可以进行如下的解析:
- 首先, 高阶组件 本身不是一个组件,而是一个函数;
- 其次,这个函数的参数是一个组件,返回值也是一个组件;
我们前面用的memo()和forwardRef()都是高阶组件。
3.2高阶组件目的是
1.对组件做拦截做处理
2.处理代码是可复用的。不用对每一个要拦截的代码,都写一遍处理代码,那是在他麻烦了。
3.3举例
这里,我们可以计算每个页面的挂载时长。
得到一个组件,可以通过props给他传递一些信息,然后最终返回一个组件(类组件和函数组件都可以),
import { PureComponent } from 'react'; function logMountTime(OriginComponent) { return class extends PureComponent { constructor() { super(); this.state = { foo: '这里可以添加一些处理操作' }; } UNSAFE_componentWillMount() { this.beginTime = new Date().getTime(); } componentDidMount() { this.endTime = new Date().getTime(); console.log(`页面${OriginComponent.name}渲染时间是${this.endTime - this.beginTime}ms`); } render() { return <OriginComponent {...this.state}></OriginComponent>; } }; } export default logMountTime;
Head组件用高阶组件包裹之后,再export default logMountTime(Head)返回出去。
import React, { PureComponent } from 'react' import { } from './hoc' import logMountTime from './hoc' export class Head extends PureComponent { render() { return ( <div> Head {this.props.foo} <ul> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> <li>数据列表</li> </ul> </div> ) } } // export default Head export default logMountTime(Head)
由于Head组件里是用的export Default导出的,所以App在引入的时候可以自己起别名,那就还叫Head,然后由于App组件正常引入即可展示。
import React, { PureComponent, } from 'react'; import Head from './Head.jsx' // 编写一个组件 class App extends PureComponent { constructor() { super(); this.state = { }; } render() { return ( <div> <Head></Head> </div> ); } } export default App;
3.4发展历程
由于hoc也可以给组件复制props,如果嵌套过多,可以出现同一个叫name的props被重复赋值。
mixin没必要学了,hoc可以理解,重点掌握后面的hooks。
分类:
3.前端框架
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!