本人学习视频为B站尚硅谷,视频连接为:尚硅谷React
受控组件和非受控组件
受控组件
一般是现用现取,即需要用的时候通过ref进行传递
非受控组件
即输入时就可以查看输入内容并通过state状态保存
补充知识
高阶函数
高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
常见的高阶函数有:Promise、setTimeout、arr.map()等等
函数柯里化
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
function sum(a){
return(b)=>{
return (c)=>{
return a+b+c
}
}
}
==[dataType]是变量,而少去[]则是相当于’dataType’是字符串形式传入==
不用柯里化实现非受控
生命周期
- 组件从创建到死亡它会经历一些特定的阶段。
- React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
- 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
==点击按钮卸载组件==生命周期(旧)
初始化阶段: 由ReactDOM.render()触发—初次渲染
- constructor()
- componentWillMount()
- render()
- componentDidMount()
更新阶段: 由组件内部this.setSate触发
- shouldComponentUpdate()
- componentWillUpdate()
- render() =====> 必须使用的一个
- componentDidUpdate()
==如果阀门函数返回的是false则无法进行更新==强制更新阶段
- componentWillUpdate()
- render() =====> 必须使用的一个
- componentDidUpdate()
更新阶段: 由父组件render触发
1.componentWillReceiveProps
2. shouldComponentUpdate()
3. componentWillUpdate()
4. render() =====> 必须使用的一个
5. componentDidUpdate()
==componentWillReceiveProps这个是接收到新的参数才调用,第一次初始化render是不会调用==
生命周期(新)
==新生命周期在React17版本以上适用,删除了原来的componentWillMount(),componentWillUpdate(),componentWillReceiveProps()阶段,新增了getDerivedStateFromProps()和getSnapshotBeforeUpdate()阶段,并如下图所示:
初始化阶段: 由ReactDOM.render()触发—初次渲染
1. constructor()
2. getDerivedStateFromProps
3. render()
4. componentDidMount() =====> 常用
一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
更新之前
初始化阶段: 由ReactDOM.render()触发—初次渲染
- constructor()
- getDerivedStateFromProps
- render()
- componentDidMount() =====> 常用一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
更新阶段: 由组件内部this.setSate()或父组件重新render触发
5. getDerivedStateFromProps
6. shouldComponentUpdate()
7. render()
8. getSnapshotBeforeUpdate
9. componentDidUpdate()
更新之后
getSnapshotBeforeUpdate的使用
即将废弃的勾子
1. componentWillMount
2. componentWillReceiveProps
3. componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
diff算法
在每次更新render的时候,都是按照标签节点来比较虚拟DOM和真实DOM,如果标签内容发生更改,则会进行重新生成虚拟DOM并替换掉真实DOM,无发生更改则不替换操作,目的是为了增加效率。
key标识问题
虚拟DOM中key的作用:
(1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。
(2). 详细的说: 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,
随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1).若虚拟DOM中内容没变, 直接使用之前的真实DOM
(2).若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
b. 旧虚拟DOM中未找到与新虚拟DOM相同的key,根据数据创建新的真实DOM,随后渲染到到页面
使用index作为唯一标识(更新人员放最上面)
慢动作回放—-使用index索引值作为key
初始数据:
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
初始的虚拟DOM:
<li key=0>小张---18<input type="text"/></li>
<li key=1>小李---19<input type="text"/></li>
更新后的数据:
{id:3,name:'小王',age:20},
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
更新数据后的虚拟DOM:
<li key=0>小王---20<input type="text"/></li>
<li key=1>小张---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
==解析:使用index作为唯一标识key的时候,由于小王在最上面,key=0作为标识,而之前的key=0是小张,diff算法为最小标签算法,识别li标签内容改变重新替换展示DOM,但是input标签识别内容不变,因此保存在真实DOM,因此造就这种情况,同时由于内容的改变导致效率低==
使用id作为唯一标识(更新人员放在最上面)
慢动作回放----使用id唯一标识作为key
初始数据:
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
初始的虚拟DOM:
<li key=1>小张---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
更新后的数据:
{id:3,name:'小王',age:20},
{id:1,name:'小张',age:18},
{id:2,name:'小李',age:19},
更新数据后的虚拟DOM:
<li key=3>小王---20<input type="text"/></li>
<li key=1>小张---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
==解析:使用id作为key标识,在新数据生成新的虚拟DOM,比较后发现小张和小李的key不变没有替换,input也一样,因此不会发生偏移的情况,同时只有小王一个新的虚拟DOM来添加到真实DOM,不同于上面三个真实DOM都要替换,效率也提高了不少==
总结
用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
- 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
- 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果确定只是简单的展示数据,用index也是可以的。
发布时间: 2024-02-12
最后更新: 2022-06-04
本文标题: React学习(二)
本文链接: https://zihong135.github.io/2024/02/12/React学习(二)/
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处!
