面试题
前端优化性能的方法
- 压缩字体文件 使用 fontmin-webpack 插件对字体文件进行压缩
- 减少 HTTP 请求
- 使用字体图标 iconfont 代替图片图标
- 使用 webp 格式的图片
- 减少重绘重排
- 使用事件委托
- 使用 Web Workers
html + css
1. HTML和CCS3新增那些内容?
- 广义上的html5指的是最新一代前端开发技术的总称,包括html5,CSS3,新增的webAPI。
- Html中新增了:header,footer,main,nav等语义化标签,新增了video,audio,canvas画布。新增了一些标签属性,例如input的placeholder。
- Css3中新增了:圆角,阴影,滤镜,vwvh单位,flex布局,媒体查询,过度和动画,伪类。线性渐变
- webAPI新增了:localStorage和sessionStorage,querySelector,webSocket,requestAnimationFrame,Worker(类似分线程),地理位置。
2. 什么是HTML语义化?HTML语义化的好处是什么?
-
html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重;
-
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
3. 前端页面中动画都有那些实现方式,各自分别使用那些使用场景
- Transition:简单的动画,只需要在两个状态之间变化的动画。
- keyframeAnimation:适合需要在多个状态连续进行的动画。
- js动画:功能最强的动画,但是效率最低。
4. 怪异和模型和盒模型的区别
- 在标准模式下,块的总宽度= width + margin(左右) + padding(左右) + border(左右)
- 怪异模式下,块的总宽度= width + margin(左右)(即width已经包含了padding和border值)
- box-sizing来设置盒子属性
-
- content-box (默认)宽度盒高度即为元素内容区,再内容区之外加padding、border、margin(标准盒模型)
- box-sizing 属性为border-box时,设置的宽度和高度是元素的边框盒,此时,为元素设置的padding和border也包含其中,content的实际大小为宽高减去内边距和边框的大小。(怪异盒模型)
- box-sizing属性为inheri时,该元素继承父元素的box-sizing属性。
- content-box (默认)宽度盒高度即为元素内容区,再内容区之外加padding、border、margin(标准盒模型)
5. css3中transtion和animation的区别
-
transition只有开始和结束两个状态,并且需要通过事件触发
-
animation可以通过定义关键帧指定多个动画状态,可以自动播放
6. 页面中常用那些单位,有什么区别
- px 以物理像素为基准
- em以当前元素font-size为基准
- rem以html font-size为基准
- vw/vh以浏览器窗口宽高为基准 100vw=浏览器窗口宽度
- rpx 适用于小程序或uniapp中可以实现自适应 750rpx=屏幕宽度
7. 怎么实现元素上下左右都居中?
- 实现元素本身内容居中:text-align:center+行高。
- 实现子元素在父元素中居中:绝对定位 + 上下左右设置 0 + margin:auto。
8. 网页性能优化方案?
- 减少http请求次数:CSS 精灵图 , JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
- 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
- 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
- 当需要设置的样式很多时设置className而不是直接操作style。
- 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
- 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
- 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。
9. < link>和@import导入样式的区别
- link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
- link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
- link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
- link支持使用Javascript控制DOM去改变样式;而@import不支持。
10. display: flex;
- flex-direction 决定主轴的方向
-
row
(默认值):主轴为水平方向,起点在左端。row-reverse
:主轴为水平方向,起点在右端。column
:主轴为垂直方向,起点在上沿。column-reverse
:主轴为垂直方向,起点在下沿。
- flex-wrap 决定换行
-
nowrap
(默认):不换行。wrap
:换行,第一行在上方。wrap-reverse
:换行,第一行在下方。
- flex-flow flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
- justify-content 主轴上的对齐方式。
-
flex-start
(默认值):左对齐flex-end
:右对齐center
: 居中space-between
:两端对齐,项目之间的间隔都相等。space-around
:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
- align-items 交叉轴上的对齐方式。
-
flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
- align-content 多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
-
flex-start
:与交叉轴的起点对齐。flex-end
:与交叉轴的终点对齐。center
:与交叉轴的中点对齐。space-between
:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around
:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch
(默认值):轴线占满整个交叉轴。
- 以下6个属性设置在项目上。
-
order
:属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。flex-grow
: 定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大。flex-shrink
: 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。flex-basis
: 定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto
,即项目的本来大小。flex
:flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
。后两个属性可选。align-self
:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。默认值为auto
,表示继承父元素的align-items
属性,如果没有父元素,则等同于stretch
。
11. 重绘和回流
- 重绘(repaint):当元素样式的改变不影响页面布局时,比如元素的颜色,浏览器将对元素进行的更新,称之为重绘。
-
- 常见的重绘操作有:改变元素颜色,改变元素背景色 ……
- 回流(reflow):也叫做重排。当元素的尺寸或者位置发生了变化,就需要重新计算渲染树,这就是回流,比如元素的宽高、位置,浏览器会重新渲染页面,称为回流,又叫重排(layout)。
- 关系:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。
11. 浏览器渲染的原理
- 处理
HTML
并构建DOM
树。 - 处理
CSS
构建CSSOM
树。 - 将
DOM
与CSSOM
合并成一个渲染树。 - 根据渲染树来布局,计算每个节点的位置。
- 调用
GPU
绘制,合成图层,显示在屏幕上
12. git 常用的命令
- 查看 git 版本: git --version
- 设置用户签名:git config --global user.name 用户名
- 设置用户签名:git config --global user.email 邮箱
- 初始化本地库:git init
- 查看本地库状态:git status
- 添加到缓存区:git add 文件名
- 提交到本地库:git commit -m “日志信息” 文件名
- 查看历史记录:git reflog
- 版本穿梭:git reset --hard 版本号
- 推送版本:git push origin master 将本地库储存的代码推送到远程库
- 拉取:git pull origin master 将远程库更新拉取到本地库
- 查看提交历史版本:git log
- 查看缓存区文件:git ls-files
- 查看分支:git branch
- 创建分支:git branch 分支名
- 将某个分支合并到当前分支:git merge 分支名
- 查看分支记录:git reflog 分支名
- 从远程仓库拉取代码:git clone 远程库的地址(./1.png)
css 可以继承的属性
行高,color,关于字体的,关于文本的,列表布局,光标属性,元素可见型
JavaScript
1. Js数据类型有那些?
- 数值、字符串、布尔、undefined、null、数组、对象、函数
2. 引用类型和值类型的区别
- 值类型存在于栈中, 存取速度快 引用类型存在于堆,存取速度慢
- 值类型复制的是值本身 引用类型复制的是指向对象的指针
- 值类型结构简单只包含基本数据, 引用类型结构复杂,可以实现多层嵌套
3. 判断数据类型的方法
typeof instanceof constructor Object.prototype.toString.call()
- typeof:只能判断基本数据类型,不能判端引用数据类型
- instanceof :只能正确判断引用数据类型,而不能判断基本数据类型。
instanceof
运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的prototype
属性。 - constructor:有两个作用,一是判断数据的类型,二是对象实例通过
constrcutor
对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor
就不能用来判断数据类型了: - Object.prototype.toString.call():使用 Object 对象的原型方法 toString 来判断数据类型:
4. null 和 undefined 的区别?
首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。
undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null
主要用于赋值给一些可能会返回对象的变量,作为初始化。
undefined 在 js 中不是一个保留字,这意味着我们可以使用 undefined 来作为一个变量名,这样的做法是非常危险的,它
会影响我们对 undefined 值的判断。但是我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。
当我们对两种类型使用 typeof 进行判断的时候,Null 类型化会返回 “object”,这是一个历史遗留的问题。当我们使用双等
号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false。
5. Promise有那些使用场景?
- 在页面打开时,要同时执行多个ajax请求,可以使用promise处理多异步任务并发执行
- 有些ajax请求之间存在依赖关系,需要顺序执行,造成结构嵌套,可以使用promise解决异步任务多层嵌套的问题, 实现链式调用
- 在项目中封装网络请求时,使用peomise封装ajax请求并返回peomise对象
- 两个常用的静态方法:
-
- .all 所有都成功了才会返回
- .race 只要有一个成功或者失败 都会返回
- .all 所有都成功了才会返回
6. Js函数中的this有那些指向?怎样改变函数中this的指向?
- 一般情况下,通过谁调用,就指向谁
-
- 在js全局作用域, this指向window
- 在对象中,this指向这个对象本身
- 构造函数中,this是正在创建的对象。
- 在事件函数中,this指向事件目标
- (注意: 在计时器中this会被还原成window或置空,但箭头函数可以保留this指向)
- 在js全局作用域, this指向window
- 可用通过call(), apply(), bind()改变this的指向
-
- apply() 和 call() 一样,修改指向的同时调用函数,唯一的区别是,传参方式不同,aplly需要提供一个数组。
- bind() 修改this指向时不会调用函数,而是生成一个新的函数,新的函数和原函数代码一样,但是里面的this是绑定过的。
- apply() 和 call() 一样,修改指向的同时调用函数,唯一的区别是,传参方式不同,aplly需要提供一个数组。
7. 什么是原型和原型链?
Js中的对象都有一个属性叫做__ptoto__(也是一个对象),表示对象的原型。当访问对象中的属性或方法时,首先在对象本身中寻找,如果找不到则会在原型中寻找,原型中也找不到时会在原型的原型中寻找,直到最顶层为止。
js中的类(构造函数)都有一个prototype的属性,表示本类的原型类型,通过这个类实例化的对象(这个构造函数创建的对象), proto__都指向本类的prototype,从而实现了类方法或属性的共享。一个类的prototype也是一个对象,它也有__proto,把它的__proto__指向另一个类的prototype时,那么这个类的对象就能访问另一个类中的方法,从而实现了方法的继承。
A类的prototype指向另一个类B,B的prototype又可以指向C,这种结构叫做原型链。
8. new在执行时会做四件事情:
- 在内存中创建一个中间对象
- 将该中间对象的 propo 指向构造函数原型
- 构造函数的 this 指向中间对象
- 返回该中间对象也是就是返回了实例对象
9. Js原生Ajax实现流程?
- 创建XMLHttpRequest请求对象
- open方法指定请求方式、请求路径、同步异步
- 设置响应HTTP请求状态变化的函数
- send方法发送请求
- 响应成功使用JavaScript和DOM实现局部刷新
10. 闭包是什么?有什么作用?
- 当一个函数A的作用域被内部的B函数引用时,A函数的作用域就会被B函数闭包,当A函数执行完毕时,A函数的作用域也不会释放。
- 闭包可以实现对象的私有属性和私有方法。
- 闭包可以封装变量,从简减少对全局作用域的污
- 总结:闭包并不会引起内存泄漏,只是由于IE9 之前的版本对JScript对象和COM对象使用不同的垃圾收集,从而导致内存无法进行回收。
11. 闭包的注意点
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
12. 作用域
当你需要使用一个变量的时候首先在自己作用域内部查找如果有就直接使用没有的话就去上一级作用域查找 直到全局作用域都没有那么就报错
13. 作用域链作用域链
一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值
但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
14. 什么是函数防抖和函数节流?
- 函数防抖:对于频繁触发的事件,如果只希望其最后一次(或第一次)执行绑定函数的执行,则需要使用函数防抖。
- 函数节流:对于频繁触发的事件,希望其按照一定的频率进行绑定函数调用,则使用函数节流。
- 函数防抖和节流都可以通过settimeout实现。
15. 栈和队列的区别是什么?js中怎样实现栈结构?
- 栈和队列都是线型数据结构,栈只有一个入口,同时也是出口,所以数据遵循先进后出,后进先出的规则。队列一侧是入口,另一侧是出口,所以数据先进先出,后进后出。
- Js中的数组可以实现栈和队列。Push和pop方法是一对栈操作,push和shift是一对队列操作。
16. 什么是深拷贝和浅拷贝?
-
浅拷贝就是只复制数组(对象)本身,而不复制其内容(引用类型的数据内容),最终两个数组中指向同一套数据。
-
深拷贝则是既赋值本身也赋值内容。
Js中对于引用类型的数据,默认进行的都是浅拷贝。
17. 深拷贝的实现方法
- 递归
- JSON对象的两个方法 序列化和反序列化
- JQuery中的extend()方法
深拷贝改变不会影响源数据 复制的是指针
18. 浅拷贝的实现方法
- 枚举
- 数组合并
- 数组切割
- 解构
浅拷贝改变数据会影响源数据 复制的是指针还有内容
19. ES6中新增了那些特性?
- 箭头函数,字符串模板,let块级作用域声明方式,const常量,class声明类,结构赋值,Promise,ES6模块化。
20. 箭头函数和普通函数的区别
- 箭头函数内部this跟函数所在上下文this保持一致
- 没有arguments参数集合,可以用rest替代
- 不能使用call、bind、apply来改变this的指向
21. 什么是立即执行函数
立即执行函数就是创建一个匿名函数 然后立马执行调用 它创建一个独立的作用域 避免了全局污染 不用括号包起来 浏览器会报语法错误()
(function(){alert('我是匿名函数')} ()) // 用括号把整个表达式包起来 或者(function(){alert('我是匿名函数')}) () //用括号把函数包起来
以一个著名的面试题为:
var liList = ul.getElementsByTagName('li')for(var i=0; i<6; i++){ liList[i].onclick = function(){ alert(i) // 为什么 alert 出来的总是 6,而不是 0、1、2、3、4、5 }}
解决办法
var liList = ul.getElementsByTagName('li')for(var i=0; i<6; i++){ !function(ii){ liList[ii].onclick = function(){ alert(ii) // 0、1、2、3、4、5 } }(i)}
22. 使用 axios 发 ajax 请求无法携带 cookie,什么原因,如何解决?
- axios默认跨域请求不使用凭证,当服务器在响应头中设置了cookie后, axios会默认隐藏这部分信息,
- 设置 axios.defaults.withCredentials = true;即可
23. Ajax 中 get和post 两种请求方式的区别
- 运行速度:get请求简单,运行速度也更快(存在缓存);
- 缓存:get存在缓存(优:提升速度,缺:不能及时获取最新数据)post没有缓存;
- 数据储量:get有数据量的限制,post则没有限制
- 数据安全:发送包含未知字符的用户输入时,post比get 更稳定也更可靠;数据安全:发送包含未知字符的用户输入时,post比get 更稳定也更可靠;
- 传参方式:get参数拼接在url后,post放在send里面并且需要设置请求头xmr.setRequestHeader("content-type","application/x-www-form-urlencoded"
24. cookie 和 localstorage 有什么区别?
- 都可以实现在用户的浏览器中存储一些数据。
- 不同:cookie是由服务端主导的,主要用于存储用户身份验证信息。localstorage是由前端js控制的,主要用于缓存业务逻辑数据。Cookie会随着请求头和响应头往返于服务器和浏览器之间。
25. localStorage、sessionStorage和cookie的区别?
- 本地存储容量更大有5MB左右,cookie只有4KB
- 本地存储没有过期时间,localStorage持久保存,除非手动清除,sessionStorage窗口关闭自动清除
- cookie会在客户端与服务器端之间往返,服务器端可以操作cookie,本地存储只存储于本地
26. cookie 和session 的区别?
- cookie数据存放在客户的浏览器上,session数据放在服务器上。Session基于cookie。
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
27. webSocket是什么?适用于哪些网站?
webSocket是一种双工通信技术,可以实现服务器主动向客户端发送数据。
一般适用于需要实时通信的网站, 比如人工客服服务和在线页游等
28. webpack工具的功能是什么?
- Webpack是为前端开发设计的自动化打包工具,能够对项目中的js、css、图片等资源进行打包(其中js可以直接打包,其他类型资源需要各自对应的loader支持),相比于传统的grunt、gulp等构建工具,webpack在打包js代码时,能够识别多种模块化语法,进行模块化打包。
- Webpack还可以配合脚手架工具构建项目的框架
29. 什么是WebWorker?在哪些场景下需要使用WebWorker?
WebWorker是h5中新增的WebAPI,用于启动一个独立的线程,主线程和分线程只能通过相互发送消息进行通信。当前端页面中有耗时很长的代码需要执行时,可以放在worker中执行,否则会卡塞主线程,影响用户体验。
30. 什么是MVC和MVVM?
MVC:model-view-controller
MVVM:model-view-view-model,
MVC模式通过controller控制器协调model和view的交互,View 传送指令到 Controller,Controller 完成业务逻辑后,要求 Model 改变状态,Model 将新的数据发送到 View,用户得到反馈,所有通信都是单向的。
MVVM模式使用数据双向绑定,model和view直接进行交互。
31. get请求缓存怎么解决?
Get请求的数据会被缓存到浏览器本地, 重复发起同一个get请求,会把请求重定向到本地缓存获取数据(请求状态码304)
在请求时添加时间戳,保证每次请求字段不同, 就不会被重定向到缓存
32. 什么是正则表达式? 如何使用?
正则表达式, regular expression 也叫规则表达式, 主要用于字符串的检索判断操作
如, 检索一个字符串中是否包含一定规则的字符, 或判断一个字符串是否符合一定规则
常用于用于登录注册时的账号,密码,手机号,邮箱等的验证
33. 宏任务和微任务:
-
重点提示:
-
- js中有同步代码和异步代码,同步代码在主线程执行,形成一个执行栈,而异步代码在任务队列中执行。
- js任务队列中放置的有宏任务和微任务,所以异步代码有宏任务和微任务之分,像setTimeout,setInterval,xhr等是宏任务,像Promise,asnyc等是微任务。
- 当异步的宏任务和微任务在同一个任务队列时,先执行微任务,再执行宏任务。
34. 什么是立即执行函数?谈谈什么是闭包?闭包的优缺点?什么是全局污染?
- 立即执行函数就是创建一个匿名函数,然后马上调用,它创建了一个独立的作用域,避免了全局污染,(声明全局变量、函数等时,它们将进入全局命名空间。除了性能/内存问题(这可能会出现),您可能会遇到不幸的名称冲突)
- 闭包就是能够读取其他函数内部变量的函数,在js中只有函数内部的子函数才能读取局部变量,因此闭包是定义在一个函数内部的函数。在本质上的话,闭包就是将函数内部和函数外部连接起来的一座桥梁.
- 闭包最大的有点就是可以读取函数内部的变量和让这些变量始终保持在内存中. 因为闭包会让函数变量保存在内存中,内存消耗大,如果滥用的话,会让页面卡顿,内存泄漏
35. 什么是继承?js继承方式有哪些?谈谈每一种继承方式的特点?
-
继承是为了子类可以使用父类的所有的功能 并且能对这些功能进行扩展
-
继承方式有
-
构造函数继承(call & apply)直接利用call 或者apply方法将父类的构造函数的this绑定为子类构造函数的this就可以
缺点:是无法继承原型链上的属性和方法
-
原型继承 将子类的原型挂载到父类上;
缺点:子类new的实例 父类的属性没有隔离 会互相影响
-
组合继承:组合上面的构造函数与原型继承的功能 call方法已经拿到父类的所有属性 后面在使用原型时也会有父类所有属性
-
寄生式继承: 解决组合继承重复属性的问题,直接将子类的原型等于父类的原型,或者是用Object.create继承原型但不执行父类构造函数;
注意:处理子类实例的 constructor 指向问题,new Parent2()也有这个问题;
-
class继承 Class 的 Extends 继承原理
补充:new与Object.create()区别
new创建一个对象,执行构造函数。
Object.create相当于创建一个对象,但是不执行构造函数。
36. 你接触过的异步方案有哪些?分别谈谈?
-
我经常会用callback,promise和事件监听的方式来处理异步
-
callback就是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行
-
如何使用事件监听,用onclick和addEvenListener方法
事件监听的函数有on,bind,listen,addEventListener,observe
37. 你接触到的js缓存方案有哪些?分别描述优点及缺点?
-
利用storage来对数据进行存储(sessionStorage、localStorage)
-
-
sessionStorage:临时的会话存储,只要当前的会话窗口未关闭,存储的信息就不会丢失,即便刷新了页面或者在编辑器中更改了代码,存储的会话信息也不会丢失。
-
localStorage:是一种如果你不主动去清除,会一直将数据存储在客户端的储存方式,即使关闭了浏览器,下次打开的时候仍然可以看到之前存储的未主动清除的数据(即便是
杀毒软件或者浏览器自带的清除功能,也不能将localStorage存储的数据清除掉).
-
cookie属于较老且最常见用的最多的技术了
cookie兼容所有的浏览器,但存储的数据是有大小限制,一般是4kb;
本地存储的数据会被发送到服务器
-
38. 什么是Promise? 谈谈async和await?
- (总结) promise是一个对象,主要用于异步计算,可以解决函数回调地狱,
- promise有三个状态:
-
- pending[待定]初始状态
- fulfilled[实现]操作成功
- rejected[被否决]操作失败
- await后面接一个会return new promise的函数并执行它.只能放在async函数里.能使我们的异步代码更像同步的代码
39. 在浏览器输入一个url地址,浏览器都干了什么?
域名解析 --> 发起3次握手 --> 建立连接后发起http请求 --> 服务器响应请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
- 浏览器向DNS服务器查找输入URL对应的IP地址。
- DNS服务器返回网站的IP地址。
- 浏览器根据IP地址与目标web服务器在80端口上建立TCP连接
- 浏览器获取请求页面的html代码。
- 浏览器在显示窗口内渲染HTML。
- 窗口关闭时,浏览器终止与服务器的连接。
- 浏览器将该html文本显示内容
40. 开发中常用的几种 Content-Type ?
(1)application/x-www-form-urlencoded浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。该种方式提交的数据放在 body 里面,数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL转码。
(2)multipart/form-data该种方式也是一个常见的 POST 提交方式,通常表单上传文件时使用该种方式。
(3)application/json告诉服务器消息主体是序列化后的 JSON 字符串。
(4)text/xml该种方式主要用来提交 XML 格式的数据。
41. js中的模块规范
前端模块规范共有三种:
- CommonJS(同步)
- AMD CMD这两个均是异步用在浏览器环境
-
- AMD 提前执行
- CMD延迟执行
- AMD 提前执行
- CommonJS 用在服务器端 输出模块变量的最好方法是使用module.exports对象。
42. 递归实现深拷贝
var obj={ //原数据,包含字符串、对象、函数、数组等不同的类型 name: "test", main: { a: 1, b: 2 }, fn: function () { }, friends: [1, 2, 3, [22, 33]]} function deep_copy (obj) { let new_obj=null; if (typeof (obj)==='object'&&obj!==null) { new_obj=obj instanceof Array? []:{}; for (const i in obj) { new_obj[i]=deep_copy(obj[i]); } } else { new_obj=obj; } return new_obj} let obj1=deep_copy(obj) obj.name='666'obj.main.a=10086console.log(obj, obj1);
43. 密封对象
-
Object.seal() 密封对象不可扩展,而且已有的属性成员[[configurable]]特性将被设置成false 可以用 Object.isSealed() 来判断对象是否已经被密封
44. 冻结对象
-
Object.freeze() 冻结的对象既不可以扩展,又是密封的,而且对象数据属性的[[writable]]特性会被设置为false。
44. 不可扩展对象
-
Object.preventExtensions() 仅阻止添加自身的属性。但属性仍然可以添加到对象原型。 可以用 Object.isExtensible(obj) 来判断对象是否可扩展
45. for in 跟 for of 的区别
for...in 循环主要是为了遍历对象而生,不适用于遍历数组
for...in 循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。for...of 则不会这样
for...of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象
for...of 循环可以与break、continue 和 return 配合使用,跳出循环
for...of 不能循环没有迭代器的对象
46. 状态码
常见的状态码:
200 - 请求成功
301 - 资源(网页等)被永久转移到其URL
404 - 请求的资源(网页)不存在
500 - 内部服务器错误
1开头的
100 继续。客户端继续请求
101 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议
2开头的
200 请求成功
201 一创建。成功请求并创建了新的资源
202 已接收。已经接受请求,但未处理
203 请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 部分内容。服务器成功处理了部分GET请求
3开头的
300 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 查看其它地址。与301类似。使用GET和POST请求查看
304 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 使用代理。所请求的资源必须通过代理访问
306 已经被废弃的HTTP状态码
307 临时重定向。与302类似。使用GET请求重定向
4开头的
400 客户端请求的语法错误,服务器无法理解
401 请求要求用户的身份认证
402 保留,将来使用
403 服务器理解请求客户端的请求,但是拒绝执行此请求
404 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 客户端请求中的方法被禁止
406 服务器无法根据客户端请求的内容特性完成请求
407 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 服务器等待客户端发送的请求时间过长,超时
409 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 服务器无法处理客户端发送的不带Content-Length的请求信息
412 客户端请求信息的先决条件错误
413 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 请求的URI过长(URI通常为网址),服务器无法处理
415 服务器无法处理请求附带的媒体格式
416 客户端请求的范围无效
417 服务器无法满足Expect的请求头信息
5开头的
500 服务器内部错误,无法完成请求
501 服务器不支持请求的功能,无法完成请求
502 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 充当网关或代理的服务器,未及时从远端服务器获取请求
505 服务器不支持请求的HTTP协议的版本,无法完成处理
47. map跟foreach的区别
相同点:
都是循环遍历数组中的每一项
forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项)、index(索引值)、arr(原数组)
匿名函数中的this都是指向window
只能遍历数组
区别:
map() 有返回值,可以return 出来。
forEach() 没有返回值。
forEach() 比map()运行更快
应用场景:
Vue
1. 什么是MVVM?
MVVM是model-view-viewModel的简写, 它是一种开发模式, 它实现了视图和数据逻辑之间的分离, model模型指的是后端传递的数据, view视图指的是所看到的页面, viewModel是连接视图view和模型model的桥梁, 从而实现模型model到视图view的转化 和 视图view到模型model的转化, 也就是我们所说的双向数据绑定, 使用MVVM模式实现的前端框架有 vue 和 react
2. < keep-alive></ keep-alive>的作用是什么?
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。提高渲染效率
3. 说几个vue中的指令和它的用法?
- v-model双向数据绑定; (v-model不过是一个父子组件通信的语法糖,真正实现靠的是v-bind:绑定响应式数据,触发oninput(事件在内容绑定且失去焦点时触发)事件并进行传参)
- v-for循环; (同一级别下,v-for优先级比v-if高,如果他们放在同一级下,每次渲染都会先执行循环在判断条件,不管如何循环都会浪费性能的.要解决的话,把v-if放在外层,内层进行循环)
- v-if, v-show 显示与隐藏;
- v-bind 动态绑定属性
- v-on事件绑定; (可以同时监听多个函数,它相当于DOM原生api添加事件监听者,addEventlistener)
- v-once: 只绑定一次。
4. vue中v-if和v-show有什么区别
- v-if的原理是根据判断条件来动态的进行增删DOM元素, 比较耗费性能和内存, 频繁显示隐藏不建议使用
- v-show是根据判断条件来动态的进行显示和隐藏元素, 通过设置样式display为block和none来实现, 适用于频繁显示隐藏的情况
5. vue循环中为什么使用key?
需要使用key来给循环中每个节点做一个唯一标识,要保证一个循环中key的值各不相同, 以避免vue中的重用机制造成可能的渲染异常. 从底层来看, key属性主要为了Diff算法就可以正确的识别此节点。并高效的更新虚拟DOM。
6. vue 中 key 值的作用?
vue 中 key 值的作用可以分为两种情况来考虑。
第一种情况是 v-if 中使用 key。由于 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此当我们使用 v-if 来实现元素切换的时候,如果切换前后含有相同类型的元素,那么这个元素就会被复用。如果是相同的 input 元素,那么切换前后用户的输入不会被清除掉,这样是不符合需求的。因此我们可以通过使用 key 来唯一的标识一个元素,这个情况下,使用 key 的元素不会被复用。这个时候 key 的作用是用来标识一个独立的元素。
第二种情况是 v-for 中使用 key。用 v-for 更新已渲染过的元素列表时,它默认使用“就地复用”的策略。如果数据项的顺序发生了改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处的每个元素。因此通过为每个列表项提供一个 key 值,来以便 Vue 跟踪元素的身份,从而高效的实现复用。这个时候 key 的作用是为了高效的更新渲染虚拟 DOM。
7. computed 和 watch 的差异?
(1)computed 是计算一个新的属性,并将该属性挂载到 Vue 实例上,而 watch 是监听已经存在且已挂载到 Vue 实例上的数据,所以用 watch 同样可以监听 computed 计算属性的变化。
(2)computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值。而 watch 则是当数据发生变化便会调用执行函数。
(3)watch 支持异步操作
(4)从使用场景上说,
computed 适用一个数据被多个数据影响, 例子: 购物车商品结算的时候
watch 适用一个数据影响多个数据。 例子:搜索数据
8. vue的组件配置对象中都有哪些常用字段?分别是什么作用?
- Data 组件中的数据
- props 组建的属性数据,接收父组件的传值
- computed 计算属性
- components 定义或引用子组件
- methods 自定义函数
- watch 属性监听
- filters 数据过滤器
- mounted 等生命周期函数
9. 监听器,方法,计算属性的区别?如何进入深度监听?
-
computed是基于他的依赖进行缓存的,computed只有在他的相关依赖发生变化,方法才会执行
-
watch和computed都是以vue的依赖追踪机制为基础的.
-
watch和computed各自处理的数据关系场景不同
-
watch擅长一条数据影响多条数据(如:搜索数据)
-
computed擅长一个数据受多条数据影响(如:购物车商品结算)
10. 列举一下Vue组件生命周期函数,什么时候需要在destroyed中写代码?
- beforeCreate (创建前)
- created (创建完成后)
- beforeMount (挂在之前)
- mounted (挂在完成后)
- beforeUpdate (更新前)
- updated (更新后)
- beforeDestroy (实例销毁之前)
- destroyed (实例销毁之后)
- 当前页面有事件监听器或者计时器时,需要在destroyed中取消或销毁
11. vue路由的钩子函数有哪些?
- 全局的路由钩子函数:beforeEach、afterEach
- 单个的路由钩子函数:beforeEnter
- 组件内的路由钩子函数:beforeRouteEnter、beforeRouteLeave、beforeRouteUpdate
12. 介绍以下vue组件内的路由守卫(即路由的生命周期/钩子函数),有哪些参数(to,from,next)
- vue组件中的路由钩子方法有
-
- beforeRouteEnter 进入路由前调用。这里组件还未创建, 不能使用this
- beforeRouteUpdate 路由更新之前被调用, 组件不会重新初始化, 可以使用this
- beforeRouteLeave 离开路由之前被调用,可以访问里面的this属性
- 方法中都有三个参数:
-
- to:即将要进入的目标路由对象;
- from:当前导航即将要离开的路由对象;
- next :调用该方法后,才能进入下一个路由钩子函数
13. vue中数据绑定是怎么实现的?双向绑定指令v-model的本质是什么?
- Vue组件data中的数据在组件创建时,都会被改造为set,get类型的属性,当数据发生变化时set方法就会调用,set方法中添加了重新渲染的代码。
- v-model相当于 v-bind:value 加 v-on:input
14. vue中路由如何传值?
- 使用url拼接字符串的形式传值 使用$route.query接收
- 使用query对象传值 使用$route.query接收
- 使用占位符 使用$route.params接收
- 使用命名路由params字段传值 使用$route.params接收
15. vue中有哪些数据传递方式?
- 组件传值: 父传子,通过props属性或slot插槽传递, 子传父,通过$emit发射自定义事件传递, 非父子,通过bus总线传递
- 路由传值: 可通过url路径传值和编程式导航对象传值
- vuex状态管理传值
16. vuex如何使用?
- 首先在项目中 npm install vuex 安装
- 新建vuex状态管理文件,导入vuex并添加状态数据
- 在组件中使用mapState()函数映射状态数据并使用
- 在组件中使用commit()函数提交申请修改状态数据
17. Vuex的核心概念有哪些?组件如何使用store中的数据如何改变store中的数据?
- state => 存储状态(变量)
- getters => 对数据获取之前的再次编译,可以理解为state的计算属性。我们在组件中使用 $sotre.getters.fun()
- mutations => 修改状态,并且是同步的。在组件中使用$store.commit('',params)。这个和我们组件中的自定义事件类似。
- actions => 修改状态,异步操作。在组件中使用是$store.dispath('')
- modules => 模块化Vuex
VueX状态管理通过vue.use()扩展到vue框架上使用,在实例化一个仓库中,state是单一状态树、支持响应式、默认保存到内存中,无法持久化,不能直接更改,数据的变化无法准确追踪和维护,在严格模式下会报错;在使用时在main.js中挂载后,就会在vue对象中扩展了一个内置对象$store(仓库实例),在组件中使用双花括号$store.state打点调用;在create生命周期中使用this.$store。只能通过mutations来更改仓库中的state(数据)。 mutation是唯一一种更改数据的方法,且是同步的。
更改数据需要在仓库中使用mutation来更改数据,在里面定义很多的处理程序handlers,来更改state中的数据;处理程序(函数方法)要求:第一个参数是state,第二个参数是载荷payload(携带过来的数据);在组件中调用处理函数时,通过$store.commit(‘函数方法’)也就是把用户的更改【提交】到仓库,让仓库【改变】对应的数据
18. axios和ajax的区别:
-
axios实现了网页布局数据刷新,实现了对ajax的封装
-
axios是通过promise实现对ajax技术的一种封装,就像jQuery实现ajax封装一样。
-
简单来说: ajax技术实现了网页的局部数据刷新,axios实现了对ajax的封装。
19. vue中虚拟DOM的实现原理
虚拟DOM是通过js对象的结构来记录html标签节点, 当组件数据更新需要渲染视图时,先用diff算法计算变化前后js对象(也就是虚拟DOM树)结构的不同, 得到最小差异, 然后针对性的更新部分真实DOM节点, 这样可以极大提高视图渲染效率, 节省内存消耗
20. vue组件中如何监听路由?
- 在组件的watch监听器中对$route这个字段进行监听
- 全局监听路由在app.vue组件中,watch监听$route可以监听全局路由
- 也可以在全局路由守卫beforeEach函数中操作全局路由
21. vue中如何实现父子组件间的双向数据绑定?
- Vue中父子组件双向绑定利用父子组件传值原理,
- 父组件向子组件传值, 通过给子组件定义value属性来接收传值
- 子组件向父组件传值, 通过子组件$emit发射名为input的自定义事件
- 在父组件中使用子组件标签时, 在子组件标签上通过v-model绑定父组件数据,实现父子组件的双向绑定
22. Vue.nextTick()方法有什么作用?
- 当vue中动态数据修改时,会导致界面的更新,而界面的更新属于异步更新, 当打印界面数据时, 异步更新尚未完成, 所以打印结果是更新之前的数据
- Vue.nextTick表示异步更新函数, 其参数是更新完成的回调函数
23. 简述vue响应式原理?(v-model指令的原理?)
创建vue实例时,vue会遍历data选项的属性,用object defineProperty将他们转为getter/setter,并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新
24. 在vue中如何获取dom节点?什么是虚拟DOM?
利用js原生的获取dom节点方法 在vue中引用jquery 使用res属性获取,在组件模板元素添加ref,在js中庸this.$refs获取
vue将DOM抽象成一个js对象为节点的虚拟DOM树,以VNode节点模拟真是的DOM,并且可以进行增删改查的操作,这个就是虚拟DOM
25. vue常用的修饰符,并简要描述?
-
v-model修饰符
-
- .lazy(输入框改变的时候,这个数据就会改变,.lazy会在光标离开输入框是执行)
- .trim(输入框过滤首尾的空格)
- .lazy(输入框改变的时候,这个数据就会改变,.lazy会在光标离开输入框是执行)
-
事件修饰符
-
- .stop(阻止事件冒泡,相当于调用了event.stopPropagation()方法)
- .prevent(阻止默认行为,相当于调用了event.preventDefault()方法,比如表单的提交、a标签的跳转就是默认事件)
- .once(只能使用一次)
- .stop(阻止事件冒泡,相当于调用了event.stopPropagation()方法)
26. 单页面应用和多页面应用区别及优缺点?
-
单页面(首次进入会请求一个html文件.刷新之后,点击组件,路径会变化,但不会有新的HTML请求)
-
- 优点:页面切换快 缺点:首屏时间慢
-
多页面(每次进行跳转,都会请求一个新的HTML)
-
- 优点:首屏进入的时间快
- 缺点:页面切换会慢
27. vue的组件配置中都有哪些常用字段?都有什么用?
-
data:组件中的数据
-
props 组件的属性数据,接收父组件的传值
-
computd 计算属性
-
component 定义或者引用组件
-
methods 自定义函数
-
watch 监听器
-
filters 数据过滤器
-
mounted等生命周期函数
28. vue中如何处理跨域请求
- 我在开发中,我会设置代理服务器来解决跨域问题.
- 在跟目录下手动创建comfig.js文件,在devServer中配置代理服务器
- 然后在使用axios请求数据(直接使用代理的地址),
- 中间件代理
29. vue 中 mixin 和 mixins 区别?
mixin 用于全局混入,会影响到每个组件实例。
mixins 应该是我们最常使用的扩展组件的方式了。如果多个组件中有相同的业务逻辑,就可以将这些逻辑剥离出来,通过 mixins 混入代码,比如上拉下拉加载数据这种逻辑等等。另外需要注意的是 mixins 混入的钩子函数会先于组件内的钩子函数执行,并且在遇到同名选项的时候也会有选择性的进行合并
30. 自定义指令
- 全局指令:
// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() }})
- 局部指令:
directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } }}
-
钩子函数
-
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
-
钩子函数的参数
-
el
:指令所绑定的元素,可以用来直接操作 DOM。binding
:一个对象,包含以下 property:-
name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
31. 父子组件嵌套执行的生命周期顺序
- 加载渲染过程:
-
- --> 父 beforeCreate --> 父 created --> 父 beforeMount
- --> 子 beforeCreate --> 子 created --> 子 beforeMount -> 子 mounted
- --> 父 mounted
- --> 父 beforeCreate --> 父 created --> 父 beforeMount
- 子组件更新过程
-
- --> 父 beforeUpdate
- --> 子 beforeUpdate --> updated
- --> 父 updated
- --> 父 beforeUpdate
- 父组件刚更新过程
-
- --> 父 beforeUpdate --> updated
- 销毁过程
-
- --> 父 beforeDestroy
- --> 子 beforeDetroy --> destroyed
- --> 父 destroyed
- --> 父 beforeDestroy
32. vue的优点和缺点
优点:
- 简单好用: Vue.js包含基于HTML的标准模板,可以更轻松地使用和修改现有应用程序。
- 单页面应用, 使用单文件组件结构, 用户体验好,
- 性能比较好:相比其他框架, 它占用更少的空间,并提供更好的性能。
- 基于MVVM模式, 数据驱动视图, 更高效
- 适应性强:组件化设计可以提高开发效率,方便代码复用, 提升整个项目的可维护性
缺点:
- vue生态环境不如react和angular, 但有追赶和超越的趋势
- vue不支持IE8
- vue封装的比较深入,不利于seo优化, 报错不明显,
33. 校验props
接收的时候使用props写成对象的形式它的属性有
type可以是以下原生类型 String Number Boolean Function Object Array Symbolrequired有两个值 true 必填 false 默认不必填使用default选项来指定当父组件未传入参数时props变量的默认值:validator 当校验规则很复杂,默认提供的校验规则无法满足的时候可以使用自定义函数来校验。
vue3相比于vue2有哪些区别?
-
vue2使用时直接导入vue构造函数,vue3使用时通过对象解构方式按需导入
-
vue3中新增了setup函数,数据的定义,更新计算,监听等都在setup函数中执行
-
setup函数中的数据都需要return导出才能在组件模板中调用
-
setup中this为空,可以有效避免this指向修改带来的问题
-
Vue中的生命周期也在setup中实现,其中取消了beforeCreata和created,其他的生命周期函数名有更新,如destoryed改成了onUnmounted
-
Vue3中使用ref函数定义值类型数据,使用reactive函数定义引用类型数据
-
Vue3中的ref, reactive,computed等功能函数都需要从vue中解构导出才能使用
-
Vue3废弃了filters过滤器,建议使用计算属性
vue跟React的有那些区别
相同点:
- 都通过虚拟DOM实现了视图的渲染与更新
- 都是组件化编程, 把整个项目分割成一个个的组件来实现
- 都有单向数据流的规则执行数据流动, 父组件通过props属性向子组件传值
不同点:
- vue常用html标签模板,使用js实现逻辑,视图与逻辑分离, react使用jsx语法实现模板, html与js相结合
- vue组件中的data数据可以直接调用并更新 而react中的state数据需要使用setState()函数执行更新
- vue属于渐进式前端框架,更适用于开发小型,灵活的项目, react生态更丰富,更适用于开发专业,大型的项目
- vue在组件中提供了指令,过滤器,属性监听等,可以方便快捷的操作DOM
为什么配置代理服务器能解决跨域
跨域主要是浏览器行为,是客户端行为了,浏览器根据策略,判断是否是跨域。服务器端,是没有跨域这种说法的。而且,服务器之间的调用,大部分情况下是为了获取接口数据的,功能复杂,但是单一,你vue设置代理,也主要是为了避免直接请求过去,浏览器认为跨域,自己设置个代理解决而已了
什么情况下使用VUEX
- 如果数据还有其他组件复用,建议放在vuex
- 如果需要跨多级组件传递数据,建议放在vuex
- 需要持久化的数据(如登录后用户的信息),建议放在vuex
- 跟当前业务组件强相关的数据,可以放在组件内
描述vuex
VueX状态管理通过vue.use()扩展到vue框架上使用,在实例化一个仓库中,state是初始化数据、支持响应式、默认保存到内存中,无法持久化,不能直接更改,数据的变化无法准确追踪和维护,在严格模式下会报错;在使用时在main.js中挂载后,就会在vue对象中扩展了一个内置对象$store(仓库实例),在组件中使用双花括号$store.state打点调用;在create生命周期中使用this.$store。只能通过mutations来更改仓库中的state(数据)。 mutation是唯一一种更改数据的方法,且是同步的。异步更新数据action 需要mutation来提交
更改vuex
更改数据需要在仓库中使用mutation来更改数据,在里面定义很多的处理程序handlers,来更改state中的数据;
处理程序(函数方法)要求:第一个参数是state,第二个参数是载荷payload(携带过来的数据);
在组件中调用处理函数时,通过$store.commit(‘函数方法’)
也就是把用户的更改【提交】到仓库,让仓库【改变】对应的数据
React
1. React中有哪些生命周期函数?
16版本之前
- constructor(props) { } 组件初始化
- componentWillMount() 渲染前 (不建议使用)
- componentDidMount() 渲染后 开启定时器
- componentWillReceiveProps() 接收props传值时
- shouldComponentUpdate()控制组件是否更新
- componentWillUpdate() 组件将要更新
- Render() 组件正在渲染
- componentDidUpdate() 组件已经更新
- componentWillUnmount() 组件将要移除 移除定时器
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染 (1).constructor() =====> props用来接收外部传递的数据 (2).componentWillMount() =====> 组件渲染前执行,(一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息) (3).render() =====> 渲染 (4).componentDidMount() =====> 常用 渲染后 2. 更新阶段: 由组件内部this.setSate()或父组件render触发 (1).shouldComponentUpdate() =====> 返回一个布尔值,返回true,让组件更新,返回false不让组件更新 (2).componentWillUpdate() =====> 数据更新前执行 (3).render() =====> 必须使用的一个 (4).componentDidUpdate() =====> 数据更新后执行3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发 (1).componentWillUnmount() =====> 常用 (一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息)
16版本之后
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染 (1).constructor() =====> props用来接收外部传递的数据 (2).getDerivedStateFromProps (3).render() (4).componentDidMount() =====> 常用 (一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息)2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发 (1).getDerivedStateFromProps (2).shouldComponentUpdate() =====> 返回一个布尔值,返回true,让组件更新,返回false不让组件更新 (3).render() =====> 渲染 (4).getSnapshotBeforeUpdate (5).componentDidUpdate() =====> 组件更新完毕3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发 (1).componentWillUnmount() =====> 常用 (一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息)
2. React组件中的state 和 props 有何区别?
- State 是一种数据结构,在组件构造器中定义, 是可读可写的, 用于组件内部数据的初始化和更新。 state中一般只放纯数据
- Props 则是组件的配置。props 由父组件传递给子组件,就子组件而言,props 是只读的。组件不能改变自身的 props,但可以修改传递给子组件的props。props也可以传递回调函数
3. React中keys是什么,有什么作用?
-
Keys是列表通过map循环时给循环标签添加的属性,用于标记每一个循环的元素
-
在循环中要保证每一个循环标签keys属性值都不相同
-
在列表数据更新时, 通过keys可以快速高效的区分哪些元素是新的,然后确保视图更新的正确和高效
4. React组件之间通讯有哪些方式?
-
父组件向子组件传值:父组件通过自定义属性向子组件传值,子组件props参数接收并处理
-
子组件向父组件传值:父组件通过自定义属性向子组件传函数,子组件props接收函数并调用
-
非父子组件传值:在全局作用域下定义变量, 通过在不同组件中对全局变量的赋值与取值来实现组件传值
5. react的优缺点
- 优点:
-
- 可以通过构造函数或类结构描述视图组件,
- 集成虚拟DOM(渲染性能好)
- 单向数据流(好处是更容易追踪数据变化排查问题)
- 一切都是component:代码更加模块化,重用代码更容易,可维护性高
- 大量使用 es6 新特性
- 缺点:
-
- jsx的一个问题是,渲染函数render()常常包含大量逻辑,最终看着更像是程序片段,而不是视觉呈现。后期如果发生需求更改,维护起来比较麻烦
- 功能强大而全面,比vue更难上手
6. react使用单向数据流有什么好处?
- 单向数据流是对数据传递的一种约束, 他保证了组件的数据传递结构稳定且不易耦合.
- 数据只能从父组件向下流动到子组件中,反过来则不行。这样会防止从子组件意外改变父级组件的状态 , 极大的降低了我们组件间通信的代码耦合
- 数据流动单一, 便于追踪, 追查问题比较便捷 q
7. 类组件和函数式组件有何不同?
-
函数式组件通过ES5的构造函数结构创建, 一般以数据的展示为主, 功能简单, 组件中的逻辑代码较少
-
类组件通过ES6的类结构创建, 允许使用更多功能,如组件状态数据,生命周期钩子, 访问redux仓库等
8. refs的作用是什么?
shouldComponentUpdate这个函数是用来判断是否需要调用render函数重新描绘DOM, 因为DOM的绘制非常消耗性能, 如果我能能在这个函数中写一些优化算法逻辑,控制DOM绘制的频率和次数, 则能极大的提高网页渲染效率, 优化性能
9. react路由跳转时如何传递数据?
- 路由传值一共有4中方式:
-
- 使用url添加?拼接字符串形式传值, 目标组件使用this.props.location.search 接收
- 使用友好url动态传值, 目标组件使用this.props.match.params接收
- 使用自定义对象传值, 路径使用pathname, 目标组件使用this.props.location.xxx接收
- 使用编程式导航跳转路由并传值this.props.history.push()
- 注意:使用对象传值以及编程式导航传值时如果页面刷新,那么传递的值就会消失;
10. 什么是Redux?
Redux是一款热门的前端开发库, 它是javascript程序的可预测状态容器,可用于react项目的状态管理, 使用Redux开发的应用易于测试,可以在不同环境中运行,并显示相同行为.
11. Redux有哪三大原则?
- 唯一数据源(整个应用的 state 状态数据被储存在一个状态树(对象)中,单一状态树更容易跟踪数据的变化, 方便调试检查应用程序)
- State 状态是只读的, 想要更改数据必须经过派发action事件,通过接收action参数修改
- reducer必须是纯函数(一个输入必须对应着唯一的输出, 返回值取决于参数)
12. React组件之间传递数据有哪些方式?
- 组件传值: 包括父传子, 子传父, 兄弟组件
- 路由传值: 包括url拼接传值, 友好url传值和对象传值
- Redux传值: 把需要传递的数据放入状态管理中,各组件共享
13. 说一下你对高阶组件的理解
高阶组件: 是 React 中用于重用组件逻辑的高级技术, 它本身不是react中的组件, 而是一个函数, 这个函数接受一个react组件作为参数,并返回一个新组件, 实现了对原有组件的增强和优化, 可以对原有组件中的state, props和逻辑执行增删改操作, 一般用于代码重用和组件增强优化
14. 高阶组件有哪些实现方式? 高阶组件有哪些实现方式?
-
属性代理。高阶组件通过被包裹的React组件来操作props, 可以增强组件模板和props
-
反向继承。高阶组件继承于被包裹的React组件 可以更新state
15. 说说你对Hooks组件的理解
-
hooks组件即使用了hooks语法构建的函数式组件
-
hooks是react中的一项新功能, 它可以在不使用class类的情况下实现state组件状态和生命周期等功能, 通过useState函数实现组件状态,通过useEffect函数实现生命周期
-
hooks语法是向下兼容的, 在旧版本的react项目中可用.
-
hooks 可以很好的替代高阶组件实现组件的抽象和复用
-
hooks只能在函数式组件中使用, 不能在普通函数或class类组件中使用, 也不建议在循环或判断逻辑中使用
16. Hooks 与 React 生命周期的关系
Hooks可以模拟实现react组件的生命周期,通过API函数useEffect并控制其第二个参数的传入可以模拟组件不同时期的生命周期钩子
17. Hooks 与 高阶组件有何区别?
它们之间最大的不同在于,高阶组件仅仅是一种开发模式,它本身是js函数结构, 而hooks是react提供的API模式,它既能更加自然的融入到react的渲染过程也更加符合react的函数编程理念。
18. 什么是渲染劫持?
渲染劫持指对一个组件渲染内容的装饰或修改, 一般通过高阶组件来实现, 把一个组件传入高阶组件, 可以对这个组件的模板进行修改后执行渲染, 也可以阻止组件渲染,并修改组件中的数据和逻辑
19. react严格模式有什么作用?
StrictMode严格模式是一个用来突出显示应用程序中潜在问题的工具, 它可以识别不安全的生命周期调用, 警告过时或已弃用的API, 并检测意外的副作用
20. react有状态组件和无状态组件有什么区别?
-
有状态组件通过class类结构定义,也叫类组件,主要用于处理业务逻辑和做数据交互
-
无状态组件通过函数结构定义, 也叫函数式组件, 主要用于定义模板,用于数据的展示
21. 函数式组件有没有生命周期?
函数时组件默认是没有生命周期的,因为函数式组件的主要功能是展示数据, 如果需要做很多业务逻辑的情况下可以选用类组件,使用类组件的生命周期, 也可以使用hooks提供的useEffect函数模拟实现组件的生命周期
22. 什么是受控组件和非受控组件?
-
受控组件和非受控组件是针对表单组件处理数据时的不同概念
-
受控组件指组件的状态数据根据用户输入,实时更新,显示在视图中, 例如input标签使用onChange绑定输入事件并通过setSatate函数更新state数据, 此时组件中的数据是可控的
-
非受控组件指组件状态数据与表单标签没有直接关联, 用户输入与视图更新不同步, 例如input标签没有绑定onChange事件或者value属性, 而使用refs 的DOM查找操作表单数据, 并用作逻辑处理, 此时组件中的数据是不可控的
-
总之一句话: 受控组件就是内部表单通过了value和onChange绑定的组件
23. 说一说你对react虚拟DOM的理解
虚拟DOM是对DOM的抽象,本质上是JavaScript对象, 即通过js对象模拟DOM中的节点,由于react使用jsx语法构建页面,浏览器无法直接运行jsx, 所以会把jsx结构解析成js对象结构, 然后通过js对象渲染DOM树, 当数据更新时虚拟DOM会通过内部的diff算法,得到节点的变化,从而局部更新变化的DOM节点, 避免了不必要的DOM操作, 提高性能
24. 说一下react虚拟DOM优化性能的实现步骤
-
用JavaScript对象结构表示DOM树的结构(虚拟DOM);然后用这个js对象构建一个真实DOM树,插到文档当中
-
当状态变更的时候,重新构造一棵新的虚拟DOM树。然后通过diff算法比较新的树和旧的树,记录两棵树差异
-
把diff算法比较的差异更新到步骤1所构建的真正的DOM树上,视图就更新了
25. react中如何监听路由
-
使用react-router-dom路由模块提供的WithRouter高阶组件给根组件props中添加路由对象
-
在根组件app.js的componentDidMount钩子函数中this.props.history,listen()监听全局路由
-
注意: 不要在react页面组件中监听路由,因为页面销毁时,路由监听不会取消, 可能造成重复监听
26. react中如何实现样式隔离?
- React组件之间默认没有样式隔离, 所有组件的样式都是全局样式,
- 我们可以给每一个组件根组件添加class值, 在设置这个组件样式时,以根组件class选择器开头, 只在根标签中起效, 以实现组件的样式隔离
27. redux
-
redux 是 js 应用的可预测状态的容器。 可以理解为全局数据状态管理工具(状态管理机),用来做组件通信等。
-
为什么使用redux
当没有使用
redux
时兄弟组件间传值将很麻烦,代码很复杂冗余。使用redux
定义全局单一的数据Store
,可以自定义Store
里面存放哪些数据,整个数据结构也是自己清楚的。 -
核心概念
-
- state:前端中的state就是数据,就是一个对象。redux中的state是不能直接修改的,只能通过action来修改,相当于我们在单例中定义setter方法。
- action:redux 将每一个更改动作描述为一个action,要更改state中的内容,你需要发送action。一个action是一个简单的对象,用来描述state发生了什么变更。
- dispatch:是组件发出action的唯一方法。
- store:store就是整个项目保存数据的地方,并且只能有一个。创建store就是把所有reducer给它。
- reducer:数据
state
,指示action
都有了那么就是实现了。reducer就是根据action来对state进行操作。
- state:前端中的state就是数据,就是一个对象。redux中的state是不能直接修改的,只能通过action来修改,相当于我们在单例中定义setter方法。
小程序
1. 小程序的生命周期
- onLoad:页面加载
- onReady:页面初次渲染完成
- onShow:页面显示
- onHide:页面隐藏
- onUnload:页面卸载
2. 一页小程序页面有哪些文件组成,分别是什么作用
- .wxml: 使用微信框架设计的一套组件构建页面结构
- .wxss: 用于设置页面样式, 和css基本一致
- .js : 设置页面数据与逻辑
- .json: 页面的配置信息
3. 小程序中rpx和px有什么不同
- px是固定单位, 指的是物理像素, 小程序样式不建议使用px,而建议用rpx
- rpx是相对单位, 小程序把页面宽度统一设置为750rpx, 它可以根据不同屏幕宽度进行自适应,更有利于屏幕适配
4. 列举几个小程序常用组件及用法
- view : 视图组件,块级元素, 用于显示块级视图及包裹子视图
- text: 文本组件, 用于文字的渲染, 支持换行
- Image: 图片组件, 用于渲染本地或在线图片
- Button: 按钮组件
- Input: 输入框组件
- Picker: 选择器组件
- Swiper: 轮播图组件
5. 简述小程序开发流程
- 首先在微信公众平台注册小程序账号, 获取appID
- 填写小程序基本信息,并下载微信开发者工具
- 使用小程序appID创建小程序项目,并编写完善项目
- 上传小程序项目为测试版, 由测试人员测试并修改BUG
- 测试完成后,在微信公众平台提交发布, 人工审核通过即可
6. 小程序中有哪些事件
- tap, touchstart, touchmove, touchend, touchcancel,
- Input, change, blue, focus, confirm
7. 简述微信小程序原理
微信小程序采用 JavaScript、WXML、WXSS 三种技术进行开发,本质就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但又可以通过微信客户端调用原生的各种接口微信的架构,是数据驱动的架构模式,它的 UI 和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现
8. 小程序的双向绑定和vue哪里不一样
- Vue双向绑定使用v-model指令即可实现
- 小程序双向绑定需要自己绑定value属性和input事件
- 而且vue中this.data即可修改数据并更新视图,
- 小程序中只能用this.setData()修改数据才可更新视图
9. 微信小程序的优劣势
优势:
- 容易上手,基础组件库比较全,基本上不需要考虑兼容问题;
- 即用即走,不用安装,省流量,省安装时间,不占用桌面
- 依托微信流量,天生推广传播优势
- 开发成本比 App 低
缺点:
- 样式单一,部分组件已经是成型了的,样式不可修改,例如:幻灯片、导航入口
- 相对传统 App 要深很多
- 限制较多,页面大小不能超过2M。不能打开超过5个层级的页面
10. bindtap和catchtap的区别?
相同点:首先他们都是作为点击事件函数,就是点击时触发。在这个作用上他们是一样的,可以不做区分
不同点:他们的不同点主要是bindtap是不会阻止冒泡事件的,catchtap是阻值冒泡的
11. 请谈谈WXSS和CSS的异同?
- 都是用来设置页面样式
- WXSS 具有 CSS 大部分的特性,也做了一些扩充和修改;
- WXSS新增了尺寸单位,WXSS 在底层支持新的尺寸单位 rpx;
- WXSS 仅支持部分 CSS 选择器;
- WXSS 提供全局样式与局部样式
12. 小程序和H5的不同
-
运行环境不同(小程序在微信运行,h5在浏览器运行);
-
开发成本不同(h5需要兼容不同的浏览器);
-
获取系统权限不同(系统级权限可以和小程序无缝衔接);
-
应用在生产环境的运行流畅度(h5需不断对项目优化来提高用户体验);
13. 小程序如何实现分享
- 只需要实现onShareAppMessage这个函数,即可点击右上角菜单分享
- 调用API wx.showShareMenu() 开启分享功能, 点击右上角菜单分享
- 给button组件添加 open-type="share" 属性, 即可点击按钮执行分享
14. 小程序组件中有哪些生命周期函数
-
created: 组件实例刚刚被创建时执行
-
attached: 组件实例进入页面节点树时执行
-
ready: 组件在视图层布局完成时执行
-
moved: 组件实例被移动到节点树另一个位置时执行
-
detached: 组件实例被从页面节点树移除时执行
-
error: 组件方法抛出错误时执行
15. 小程序中的传值方式有哪些:
-
- 页面(父组件)向子组件传值: 通过调用子组件的props中自定义的属性传值, 或者 通过slot插槽传值
-
- 子组件向父组件(页面)传值: 子组件调用triggerEvent()函数发射自定义事件, 把数据放入事件函数的参数传递, 在子组件标签bind绑定事件, 数据的参数e.detail中
-
- 页面(父组件)主动读取子组件数据, 通过this.selectComponent()函数可得到子组件实例
-
- 页面到页面之间传值: 通过路由传值, 把数据拼接到url路径上传递, 在目标页面用onLoad参数接收
-
- 使用全局状态管理传值: 在app.js中globalData字段定义全局数据, 可以在每一个页面getApp()引入并读写
-
- 使用数据缓存传值, 在一个页面中wx.setStorage存值, 另一个页面wx.getStogage取值
16. 如何实现下拉刷新和触底刷新
下拉刷新
- 页面的下拉刷新功能默认时关闭状态, 可以在json文件中添加字段允许下拉刷新
- "enablePullDownRefresh": true
- 然后,下拉页面会自动调用 onPullDownRefresh()函数, 在这里请求新数据
- 最后,数据请求完成的success函数中,调用wx.stopPullDownRefresh停止下拉刷新的状态
触底
- 触底功能默认开启, 当页面滚动到底部,会调用onReachBottom()函数
17. 你是怎么封装微信小程序的数据请求的?
- 将所有的接口放在统一的js文件中并导出
- 在app.js中创建封装请求数据的方法
- 在子页面中调用封装的方法请求数据
18. 小程序中如何解决跨域问题?
- 开发时, 可在开发工具的设置选项中勾选”不校验合法域名”, 以忽略跨域限制
- 发布时, 需在小程序后台开发设置添加小程序中使用的域名地址,使之合法即可
19. 说一些小程序中的常用API及用法
- wx.request 发起网络请求
- wx.navigateTo 执行路由跳转
- wx.showModal 展示模态框
- wx.downloadFile 下载文件
- wx.setStorage 本地存储
- wx.chooseImage 从相册选择图片
- wx.getUserInfo 获取用户信息
20. 小程序如何获取用户信息?
- 使用wx.getUserInfo() 这个API,不再弹窗获取授权,建议使用以下方式
- 在事件函数中调用wx.getUserProfile() 弹框获取用户授权, 每次都弹窗
- 给按钮添加open-type=”getUserInfo”属性, 用bindgetuserinfo事件绑定函数获取
- 使用open-data组件标签,添加type属性获取某一个用户信息
21. 微信API有哪些限制让你觉得不爽?
- 个人开发者不能使用支付API
- 个人开发者不能用webview组件
- 某些微信API有调用频次限制,例如分享API
22. 小程序页面跳转navigateTo,redirectTo的区别?
- navigateTo 指的是路由跳转, 如果跳转到二级页, 导航条会有返回按钮
- redirectTo 指的是路由重定向, 不会有历史记录,导航条也就不会有返回按钮
23. 小程序 绑定事件怎么传递参数?
在触发事件的组件标签上添加data-前缀的自定义属性,在事件函数中,通过e.currentTarget.dataset打点调用自定义属性获取参数
白屏问题
- 路由懒加载
- 使用Gzip压缩,减少文件体积,加快首屏页面打开速度
- 骨架屏
- loading
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!