前端面试笔记*****敲黑板***重点

本文详细介绍了基于React全家桶开发的博客系统,涵盖增删改查功能、用户交互、性能优化技术如memo、懒加载、shouldComponentUpdate,以及ES6新特性、CSS优化、JS高级概念、Vue与React对比、React生命周期管理、组件通信、Redux核心API和虚拟DOM原理。
摘要由CSDN通过智能技术生成

自我介绍

..........

项目简介

该项目是基于react全家桶开发的一个博客系统,具有简单的增删改查、用户对文章的评论、收藏、点赞等功能;该项目是从后端到前端的开发,后端使用了 node 搭建框架并且安装了生产依赖(npm install --save express dotenv )及开发依赖(npm install --save-dev nodemon 自动检测文件变化)、使用 MySQL 建立的数据库,其中使用了一些可视化工具像 postman 、navicat ; 前端使用了 create-react-app 脚手架 、UI页面(v1版本是手敲的ui页面、v2版本中使用了antd组件库进行ui页面的搭建)还使用到的技术 react 、react-router-dom 中 <Route>和<Switch>以及<Link> 组件等 、prop-types"(检查数据类型)等,在后面的项目部署中使用了 redux 技术像 store.getState() 获取数据、dispatch 处理请求数据等;最后在git上引用了静态资源库以及同步代码到git仓库。

性能优化:

  1. memo()

用memo进行包裹的组件在组件更新时memo会查看自身包裹的组件是否有数据更新,

如果没有就会阻止自身组件重新渲染,可以减少一些性能损耗。

使用方法:

引入 import {memo} from 'react'; 后直接使用memo()包裹即可.

  1. 懒加载 React.lazy

在路由模块使用懒加载后只有访问该模块时才会加载,不访问的不加载,减少资源加载所消耗的性能

使用方法:

引入 import {lazy} from 'react';后使用lazy包裹例:

const Home = lazy(()=>import('./router/Home'))

  1. 生命周期函数 shouldComponentUpdate()

在函数内部判断修改的数据是否跟原数据一致,如不一致则修改,一致则保持原有状态。

使用方法:

在类组件中直接使用即可。

ES6新增属性

  1. let 、const 都是块级作用域

    let 不能重复声明变量,var 可以重复声明变量; var 全局作用域 声明时会变量提升 let 定义不会变量提升 const 一旦定义不能修改

  2. 数组、对象 解构赋值

    ps: let [tool1, tool2, tool3] = Web let {name, age, tell} = liMing

  1. import export

    import 导入模块 export 导出模块

  2. class 类

    封装、继承、多态

  3. 箭头函数

    ()=>{} 注意:当函数中只有一个参数时可以省略() 当函数中只有一个表达式时可省略{}

  4. 模板字符串

    ``

  5. 展开运算符

    let color =['red','yellow'] [...color]

  6. Promise

    Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

css

盒子模型 浮动 清除浮动 定位(分别有哪几种)

盒子模型:

盒子即容器--由元素的内容、内边距(padding)、边框(border)和外边距(margin)组成。

浮动:

float:none ; 不浮动(默认值)

float:left ; 左浮动

float:right ; 右浮动

解决方法:

父级添加overflow: hidden

添加伪类 ::after

定位:

1.静态定位 (static)---一般的标签元素不加任何定位属性都属于静态定位;

2.绝对定位 (absolute--position: absolute;)---绝对定位元素可层叠,层叠顺序可通过 z-index 属性控制,z-index值为无单位的整数,大的在上面,可以有负值。

3.相对行为 (relative--position: relative;)---相对定位元素不可层叠,依据left、right、top、bottom等属性在正常文档流中偏移自身位置。同样可以用z-index分层设计

4.固定定位 (fixed)---固定定位与绝对定位类似,但它是相对于浏览器窗口定位,并且不会随着滚动条进行滚动。

元素隐藏

visibility: hidden;与display:none;区别

visibility:hidden; 属性会使对象不可见,但该对象在网页所占的空间没有改变,等于留出了一块空白区域,

display:none; 属性会使这个对象彻底消失不显示,也不再占用位置。

css元素垂直居中

1.通过与父元素的绝对定位来让自身实现垂直居中。

2.通过与父元素相对定位来让自身实现垂直居中。

3.c3新特性 只能作用在( display:table 或者 dispaly:table-cell ) 中使用 vertical-align属性可以实现元素垂直居中( vertical-align :middle ) .

4.absolute+margin :绝对定位+margin

让元素脱离文档流,然后距离上下都是0之后,设置margin的值为auto会自动撑开元素,让元素垂直居中。

ps:

​​

.app { width: 500px; height: 500px; background: red; position: relative; } .block { width: 200px; height: 200px; background: blue; position: absolute; bottom: 0; top: 0; margin: auto; }

5.flex布局

flex容器的主要特征是能够修改其子项的宽度或高度,以在不同的屏幕尺寸上以最佳方式填充可用空间。

ps:

.app { width: 500px; height: 500px; background: red; display: flex; align-items: center; } .block { width: 200px; height: 200px; background: blue; }

元素溢出 使用 overflow

overflow: auto;如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。

overflow: hidden;内容会被修剪,并且其余内容是不可见的。

overflow: scroll;内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容。

overflow: visible;默认值。内容不会被修剪,会呈现在元素框之外。

选择器 权重

选择器:

行内、ID、class;

权重:

(!important>style(行内)>id>class)

ps:权重是可以叠加的

CSS精灵图

把网页中一些背景图片整合到一张图片文件中。

再利用CSS的"background-image",“background-repeat”,"background-position"的组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。

CSS伪元素

CSS伪元素是添加到选择器的关键字,可用于设置所选元素的特定部分的样式。

“first-line” 伪元素用于向文本的首行设置特殊样式,只能用于块级元素!下面的属性可应用于 “first-line” 伪元素:font,color,background,word-space,letter-space,text-decoration,text-transform,line-height,clear。

“first-letter” 伪元素用于向文本的首字母设置特殊样式,只能用于块级元素!下面的属性可应用于 “first-letter” 伪元素:font,color,background,margin,padding,border,text-decoration,line-height,clear,text-transform。

js

JS 的基本数据类型和数据类型

基本数据类型:

Number(数值型),String(字符串类型),Boolean(布尔类型),Underfind(未定义),Null(空)

symbol,bigint(两个为ES6新增)

Symbol 的本质是表示一个唯一标识 作用:(1)防止命名冲突:

BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值以任意精度表示整数的能力尤为重要。使用BigInt,整数溢出将不再是问题。

引用数据类型:

Object(对象),[] 数组,function(函数)

Underfind 和 Null区别:

简单理解就是:undefined 是没有定义的,null 是定义了但是为空。

JS数组都有哪些方法?

  1. Array.push(),后增,向数组的末尾添加一个或多个元素,并返回新的数组长度。原数组改变。

  2. unshift() 前增

  3. pop() 后删 ;pop() 用于删除并返回最后一个元素。

  4. shift() 前删;shift() 用于删除并返回首个元素;删除首部元素,返回被删元素,改变原数组

  5. concat() 拼接 var a = [1,2,3] var b = [4,5] var c = a.concat(b) console.log(c) // [1,2,3,4,5]

  6. join();join() 方法用来将数组转换为字符串;不改变原数组,返回转换后的字符串

  7. sort() 排序;按ascii码排序

  8. reverse() 倒序顺序;颠倒数组中元素的顺序。;返回的是颠倒后的数组,会改变原数组。

  9. filter() 过滤;返回数组中满足条件的元素组成的新数组,原数组不变;filter()的参数是一个方法 var a = [1,2,3,4,11] // 第一个参数为一个方法,有三个参数,current:当前值 index:当前值下标 array:这个数组对象 var b = a.filter(function(current,index,array){ return current < 10 }) console.log(b) // [1,2,3,4] console.log(a) // [1,2,3,4,11]

  10. map() 格式化数组;map() 方法来根据需求格式化原数组,返回格式化后的数组。原数组不变 var a = [1,2,3,4,5] // 参数同filter方法 var b = a.map(function(current,index,array){ return current + 1 }) console.log(b) // [2,3,4,5,6] console.log(a) // [1,2,3,4,5]

  11. forEach() 数组遍历;遍历整个数组,中途不能中断 var arr = ['a','b','c'] var copy = [] arr.forEach(function(item){ copy.push(item) }) console.log(copy)

this指向

普通函数=>this指向是window

对于普通函数:由于没有对象的或者实例的调用,这就相当于在全局当中打印this,所以this都是指向js的顶级对象window.

构造数=>this指向的是调用它的实例对象(谁调用指向谁)

li:

function Person(name,age){

this.name=name

this.age=age

this.say=function(){

console.log(this); //Person{name:'gt',age:20,say:fun...}

console.log(this.name,this.age) // gt,20

}

}

let person1=new Person('gt',20)

person1.say() //谁实例化调用this指向谁 这里this指向person1

箭头函数=>本身没有this 逐级向上查找找到最近的函数作用域的this

JS作用域链

各个作用域的嵌套关系组成一条作用域链;

作用域链主要是进行标识符(变量和函数)的查询,标识符解析就是沿着作用域链一级一级的搜索标识符的过程,而作用域链就是保证对变量和函数的有序访问。

ps:自身作用域未声明的变量,沿着作用域链逐渐向上查找。

JS 预加载如何处理?

JS 预加载--浏览器载入 JS 代码时会扫描定义的全部变量设置为 undefined 然后再从上到下执行 JS 代码,遇到赋值情况则替换掉该值;

ps:

var a,b;

a='新值';

预加载时,首先会设置 变量 a,b 的值为 undefined ,然后向下执行给a赋值为新值,b 还是undefined。

闭包的原理 带来的影响

说起闭包就要从变量的作用域开始说起了,变量分为全局变量和局部变量,JS 语言的特点是在函数内部可以直接读取全局变量,但是在函数外部无法读取函数内的局部变量;

想要从外部读取到函数内部的局部变量,就要在函数内部再定义一个函数;

闭包就是能够读取其他函数内部变量的函数,这就是所谓的闭包

影响:

由于闭包的使用会使得函数中的变量被保存在内存中,内存消耗大,如果滥用闭包的化,会造成像IE内存泄漏等问题;

解决方法:

在退出函数之前,将不使用的局部变量全部删除。

其他

vue 和 react 的区别?

共同点:

都是组件化开发---(在UI层,将页面功能组件化--(方便复用),嵌套形成网页)

都是数据驱动视图---(解决了频繁操作DOM来实现页面效果交互的问题;只需要关注数据变化即可)

都使用虚拟DOM---(通过 JS 的 Object 对象模拟 DOM 中的节点,然后再通过特定的 render 方法将其渲染成真实的 DOM 节点。)

不同点:

我认为二者最大的不同在于生态环境的不同,

vue 框架简单通俗易理解,上手难度小,但是相对 react 来说生态环境较差,比如 vue2 和 vue3 两版本的区别差异就很大,从 vue2 到 vue3 就需要重新的学习;

而 react 的生态环境相对来说比较好,有着更多的插件、依赖来支撑。

react 生命周期函数:

1.constructor()

创建和初始化对象时调用;

当中 super(props) 是用来给 props 实例化的 (this.props = props)

2.render()

渲染--第一次挂在和更新(类组件中必须实现的方法--是一个存函数)

3.componentWillMount()

在第一次组件渲染之前执行-render()之前执行--且只会执行一次

4.componentDidMount()

组件挂载完成时触发--在第一次渲染之后立即执行

5.shouldComponentUpdate()

每当进行数据更新或页面重新渲染时会触发,当函数返回值为 true 时页面可以更新,当返回值为 false 时页面不会更新而会保持原有状态。

注意:--shouldComponentUpdate() 函数可以做性能优化使用,在函数内部判断修改的数据是否跟原数据一致,如不一致则修改,一致则保持原有状态。

6.componentWillUpdate()

组件每次更新前调用此函数--由于安全性问题后改名为 UNSAFE_componentWillUpdate()

7.componentDidUpdate()

组件每次更新完毕后立即执行

8.componentWillUnmount()

将要卸载函数,在将要卸载函数组件前调用

9.componentWillReceiveProps()

父组件中改变了 props传值时触发的函数

React组件通信:

父子组件通信

父组件通过props把数据传给子组件,子组件通过this.props去使用相应的数据。

子父组件通信

可以采用 props + 回调 的⽅式。

当⽗组件向⼦组件传递 props 进⾏通讯时,可在该 props 中传递一个回调函数,当⼦组件调⽤该函数时,可将⼦组件中想要传递给父组件的信息作为参数传递给该函数。由于 props 中的函数作⽤域为⽗组件⾃身,因此可以通过该函数内的 setState 更新到⽗组件上。

兄弟组件

可以通过兄弟节点的共同⽗节点,再结合以上2种⽅式,由⽗节点转发信息,实现兄弟间通信。

发布订阅模式

发布者发布事件,订阅者监听到事件后做出反应。

我们可以通过引⼊ event 模块进⾏此种方式的通信。

全局状态管理⼯具

可以借助 Redux 或 Mobx 等全局状态管理⼯具进⾏通信,它们会维护⼀个全局状态中⼼(Store),并可以根据不同的事件产⽣新的状态。

redux

核心api

核心方法:

getState() dispatch(action) subscribe(listener)

使用:

store.getState() // 获取数据

store.dispatch({type:'INCREMENT', number})

store.subscribe(render)

react 技术栈的原理

......

虚拟DOM 和 真实 DOM

真实的dom是一个对象,它的属性非常多,在浏览器中做dom操作,会比较消耗性能

虚拟dom是一个对象,它的属性相比较于真实的dom就比较少---用少量的属性描述一个dom,无法在浏览器中直接显示

使用虚拟DOM的好处

虚拟dom比真实dom体积小,操作是相对来说消耗性能少,如果在页面中删除一个dom,会引起重绘,影响后边元素的布局

重绘和回流

重绘:

DOM树没有元素增加或删除,只是样式的改变,针对浏览器对某一元素进行单独的渲染,这个过程就叫做重绘

回流:

DOM树中的元素被增加或者删除,导致浏览器需要重新的去渲染整个DOM树,回流比重绘更消耗性能,发生回流必定重绘,重绘不一定会导致回流。

因为重绘和回流的存在导致真实DOM性能不佳,所以VUE 和 recat 等框架增加了虚拟DOM技术,就是为了减少真实DOM的重绘和回流从而减少浏览器性能消耗,这就是虚拟DOM的好处。

promise和setTimeout的区别

promise 是微任务

setTimeout 是宏任务

JS执行顺序:执行时先执行同步再执行异步;执行异步时先执行微任务再执行宏任务

异步请求

setState

定时器 setTimeout

解决方法:

使用callback回调函数

使用 new Promise 对象封装

async / await

Ajax 的实现原理

实现过程:

首先,有客户端事件触发Ajax事件。

然后,创建 xmlHttpRequest 对象,根据浏览器不同,创建的 xmlHttpRequest 对象不同。调用open方法,用 send 发送请求给Ajax引擎。

最后,执行完毕后,把结果返回给客户端。

好处:

不用页面刷新,并且在等待页面传输数据的同时可以进行其他操作。

readyState属性有五个状态值。

0:是uninitialized,未初始化。已经创建了XMLHttpRequest对象但是未初始化。

1:是loading,send for request but not called .已经开始准备好要发送了。

2:是loaded, send called,headers and status are available。已经发送,但是还没有收到响应。

3:是interactive,downloading response,but responseText only partial set.正在接受响应,但是还不完整。

4:是completed,finish downloading.接受响应完毕。

responseText:服务器返回的响应文本。只有当readyState>=3的时候才有值,根据readyState的状态值,可以知道,当readyState=3,返回的响应文本不完整,只有readyState=4,完全返回,才能接受全部的响应文本。

三次握手 四次挥手

ps:客户端想要与服务器建立连接,必须经过三次握手;

(建立可靠的通信信道,双方确认自己与对方的发送与接收是正常的)

三次握手过程:

第一次:建立连接,客户端发请求包到服务器,并等待服务器确认;

第二次:服务器收到请求包并且确认后再向客户端发送确认包;

第三次:客户端收到来自服务器的确认包后,再向服务器端发送确认包,完成建立连接。

简化过程:

客户端 ->你好,可以连接吗-> 服务器

服务器 ->收到你好,回复同意-> 客户端

客户端 ->收到同意,回复同意-> 服务器

ps:---释放连接,需要四次挥手。

(由于tcp的半关闭特性性-一端关闭发送后还能接收数据

两次握手就可以释放一端到另一端的TCP连接,完全释放连接一共需要四次握手。)

四次挥手过程:

(主机1--主机2---可以是客户端也可以是服务器端)

第一次:主机1向主机2发送一个关闭请求;

第二次:主机2收到主机1发来的请求后回复主机1同意关闭请求;

第三次:主机2再向主机1发送报文,请求关闭连接;

第四次:主机1收到主机2发来的请求后再向主机2发送同意,主机2收到后关闭连接。

简化过程:

主机1 ->请求关闭-> 主机2

主机2 ->收到请求,回复同意请求-> 主机1

主机2 ->发送请求关闭连接-> 主机1

主机1 ->收到请求关闭连接,发送同意-> 主机2

HTML 语义化

代码结构清晰,方便阅读,有利于团队合作开发。

方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。

有利于搜索引擎优化(SEO)。

便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化。

网页加载 HTML CSS JS 的过程

网页加载流程:

浏览器发送请求,拿到 HTML 资源,并开始解析,解析过程中如遇到 <Link> 标签,浏览器会发出对 CSS 文件的请求,

继续向下解析,遇到 <body> 标签,并且 CSS 文件已经下载完成,就可以开始渲染页面,当浏览器遇到 <script>

标签,阻止页面的解析以及其他资源的下载,直到 JS 文件加载执行完毕,这样浏览器就完成了解析 HTML 页面。

跨域的产生与解决方案

产生:

当一个网络请求url时,协议、域名、端口三者之间任意一个与当前页面不同即为跨域

解决方案:

1.通过W3C标准的 cors 跨域资源共享的方式解决;(通过配置文件的请求头的方式解决)

2.通过设置代理服务器的方式解决;

(像vue中在文件 vue.config.js 中配置 proxy:{...} 开启代理服务器

ps: //配置代理服务器

proxy:{

'/dev-api':{ // 遇到该情况是进行

target:'http:/localhost:8001', //需要代理到的地址

changeOrigin:true, // 开启代理

pathRewrite:{ //替换为空

'/dev-api':''

}

}

}

)

3.通过 nginx 代理的方式解决跨域原理与 cors 一样

4.通过 JSONP 解决;(jsonp的原理就是利用 JS 标签没有跨域限制,通过 JS 标签 src 属性,发送带有 callback 参数的 GET 请求,服务端将接口返回数据拼凑到 callback 函数中,返回给浏览器,浏览器解析执行,从而前端拿到 callback 函数返回的数据。)

http 与 https 的区别?

http协议传输的数据是未加密的(明文的),传输隐私信息不安全。

https是由SSL+HTTP协议构建的可进行加密传输、身份认证,比较安全

http 状态码

  1. 1XX Informational(信息性状态码) //接受的请求正在处理

  2. 2XX Success(成功状态码) //请求正常处理完毕 200 OK:请求已正常处理。

  3. 3XX Redirection(重定向状态码) //需要进行附加操作以完成请求

  4. 4XX Client Error(客户端错误状态码) //服务器无法处理请求 400 Bad Request:服务器端无法理解客户端发送的请求,请求报文中可能存在语法错误。 404 Not Found:服务器上没有请求的资源。路径错误等

  5. 5XX Server Error(服务器错误状态码) //服务器处理请求出错 500 Internal Server Error:貌似内部资源出故障了。该状态码表明服务器端在执行请求时发生了错误。也有可能是web应用存在bug或某些临时故障。 503 Service Unavailable:抱歉,我现在正在忙着。该状态码表明服务器暂时处于超负载或正在停机维护,现在无法处理请求。

Git与 SVN

SVN是集中式版本控制系统:版本集中放在中央服务器,想要从中央服务器获取最新版本,需要联网,对网络带宽要求较高,安全性高

Git是分布式版本控制系统:每个人的电脑就是一个版本库,不需要联网,但是安全性低

git命令:

本地 -- 暂存区 -- 远程仓库

add --- commit --- push

远程仓库 -- 暂存区 -- 本地

push ------------- >

创建仓库:

git init --or-- git clone [url]

新创建仓库 克隆仓库

提交文件:

git add . 添加所有需要更新的文件

git status 查看是否添加成功需要更新的文件

git commit -m "new code" 提交到本地仓库

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值