先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
正文
先说两句
关于我今天想写的内容,大部分你其实都可以在React
官方文档上学习到。那为什么我还是想写?因为作为一个写了差不多有三年的React
的人,我居然没有正儿八经的通读过官方文档,我想告诉的可能是和我类似的人吧,同时也补充一些我自己的理解和看法。
问你几个问题
性能优化这个问题啊,真的是永远都逃不了,是个面试官都要问几句,不过说实话不知道是React
做的太好了,还是我做的项目都太基础了,基本没遇到过什么性能问题,导致我在很长一段时间内根本不知道 React 还有很多跟性能优化有关的 API。
先来看个代码,我直接在一个文件里定义多个组件方便大家观看,正式编写代码的时候一个文件就是一个组件。
import React from ‘react’;
class Test extends React.Component {
componentDidUpdate() {
console.log(‘Test componentDidUpdate’);
}
render() {
return
;}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((state) => ({
count: state.count + 1,
}));
}
handleTestClick() {}
render() {
return (
);
}
}
这代码没什么好说的,每次点击click
更新state
,我现在问几个问题,你先思考一下~
-
每次点击
click
的时候,Test
组件会打印Test componentDidUpdate
吗? -
如果我把
Test
组件的React.Component
替换为React.PureComponent
,结果与上面一样吗?如果不一样,为什么? -
如果我修改这一行代码
<Test onClick={this.handleTestClick} />
为<Test onClick={() => {}} />
结果又如何?
shouldComponentUpdate
好像所有的内容都要从这个东西说起,shouldComponentUpdate
作为React
生命周期的一部分,大多数React
开发者至少还是听说过它的,简单来说在这个函数中返回一个布尔值,React
会根据这个布尔值来判断组件是否需要重新渲染。
shouldComponentUpdate
接收两个参数,一个是更新后的props
,一个是更新后的state
,可以通过比较两个props
和state
来决定是否需要重新渲染组件。
import React from ‘react’;
class Test extends React.Component {
componentDidUpdate() {
console.log(‘Test componentDidUpdate’);
}
// 每次点击 click 都会打印 Test componentDidUpdate
// 添加这个函数后当 count 没有变化时不会打印 Test componentDidUpdate
shouldComponentUpdate(nextProps) {
if (this.props.count === nextProps.count) {
return false;
}
return true;
}
render() {
return
;}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((state) => ({
count: state.count,
}));
}
render() {
return (
);
}
}
这段代码也算比较直观的说明了shouldComponentUpdate
的用法,为什么要这么做?当只有一个Test
组件的时候可能影响不大,那如果有一千个乃至一万个Test
的时候呢,每点击一次click
就有一千个、一万个Test
的componentDidUpdate
被调用,这就有点夸张了。所以当你在使用循环渲染组件的时候就一定要注意到这一个点,它可能会成为你应用的瓶颈。
现在我们来解一下第一个问题,每次点击click
的时候,Test
组件会打印Test componentDidUpdate
吗?
是的,每次点击click
的时候,Test
组件会打印Test componentDidUpdate
,除非我们在Test
中定义了shouldComponentUpdate
,同时返回了false
阻止其重新渲染。
PureComponent
关于React
的这个 API,相信大家也没有那么陌生,根据官方文档的说法Component
和PureComponent
很相似,两者的区别在于PureComponent
中实现了shouldComponentUpdate
函数,这也是为什么我说要从shouldComponentUpdate
说起。
import React from ‘react’;
class Test extends React.PureComponent {
componentDidUpdate() {
console.log(‘Test componentDidUpdate’);
}
// 错误的用法
shouldComponentUpdate(nextProps) {
if (this.props.count === nextProps.count) {
return false;
}
return true;
}
render() {
return
;}
}
如果你在PureComponent
中又使用了shouldComponentUpdate
你应该会得到这样一个警告,侧面也告诉我们PureComponent
已经实现了shouldComponentUpdate
这个函数了。
Test has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.
官网文档中说PureComponent
中以浅层对比props
和state
的方式来实现了这个函数,也就是浅比较,那什么又是浅比较呢?可以简单的理解为a === b
,这里面还是有一些说头的,不过不在本文探讨范围内,举两个例子,大家可以自行搜索理解。
let a = 5;
let b = 5;
let c = {};
let d = {};
console.log(a === b); // true
console.log(c === d); // false
在来看一段因为不当的代码导致的问题,大家一定要注意这部分的内容。
import React from ‘react’;
class Test extends React.PureComponent {
// 根据从 App 中传来的 animal 渲染组件
// 在 App 中每次点击添加新的动物后, 这里还是原来的 dog
render() {
return
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
// 默认为一只狗
this.state = { animal: [‘dog’] };
this.handleClick = this.handleClick.bind(this);
}
// 每次点击把新的值添加进 animal 中
// 此处有一个 Bug, 由于 animal.push 方法虽然更新了原来的数组
// 但是他们还是一个数组(这个说法有些奇怪), 指针还是一样的
// 可能需要读者自行搜索理解 JS 中基本类型和引用类型的存储方式
// 所以当 Test 组件接收到新的 animal 时, 通过浅比较会发现它们其实是一样的
// 也就意味着 Test 不会重新渲染
handleClick(val) {
const { animal } = this.state;
animal.push(val)
this.setState({
animal,
});
}
// 根据 state 中的 animal 渲染组件
render() {
return (
);
}
}
看到这里相信你应该能解答第二个问题和第三个问题了,不过我们还是一起再来看看~
问:如果我把Test
组件的React.Component
替换为React.PureComponent
,结果与上面一样吗?如果不一样,为什么?
答:因为每次传递props
中的onClick
都是App
组件中的handleTestClick
,同时使用了PureComponent
,所以每次浅比较都是一致的,所以不会在打印Test componentDidUpdate
了。
问:如果我修改这一行代码<Test onClick={this.handleTestClick} />
为<Test onClick={() => {}} />
结果又如何?
答:虽然使用了PureComponent
,但是由于App
每次调用render
函数的时候都会重新声明一个方法,此方法和上一次传递给Test
的方法不同,所以每次点击还是会打印Test componentDidUpdate
。
剩点内容补充
除了上述两个 API 以外,其他 API 或多或少只是它们的改版,所以我就放在一起说了。
memo
React.memo
在我看来就是PureComponent
无状态组件版本,如果用的是class
就用PureComponent
,如果用的是无状态组件就用memo
。
import React from ‘react’;
最后
小编综合了阿里的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析
虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
10419193354991.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tlcGxlcl9JSQ==,size_16,color_FFFFFF,t_70)
虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-bpTOp1KW-1713455007900)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!