本次主要记录一下神州信息(2023.3.7)、百度前端一面 (2023.3.22中午11点)、联通数科(3.24下午1点半)
特点:
特点:
详细请看Vue中 computed 和 watch 区别及应用场景详解
hash模式:
history模式:
原理:
HashRouter的原理:
通过window.onhashchange方法获取新URL中hash值,再做进一步处理
HistoryRouter的原理:
通过history.pushState 使用它做页面跳转不会触发页面刷新,使用window.onpopstate 监听浏览器的前进和后退,再做其他处理
vue-router常见的面试题
兴业数金之promise
Pending(进行中,初始状态,既不是成功,也不是失败状态。)、Resolved(已完成,又称 Fulfilled)、Rejected(已失败)
这三种状态的变化途径只有2种:异步操作从 未完成 pending => 已完成 resolved异步操作从 未完成 pending => 失败 rejected状态一旦改变,就无法再次改变状态,这也是它名字 promise-承诺 的由来,一个promise对象只能改变一次
什么是Promise,Promise的三种状态
原型:每个函数都有prototype属性,称之为原型。因为这个属性的值是个毒性,也称之为原型对象
作用:存放一些属性和方法;在JS中实现继承
原型链:每个对象都有一个_ proto_ ,它指向它的prototype原型对象; 它的prototype原型对象又有一个_proto_,指向它的prototype原型对象,就这样层层向上直到最终找到顶级对象Object的prototype,这个查询路径就是原型链。
动态加载JS脚本有4种方法
懒加载就是延时加载(也称为按需加载)。
具体表现为:当我们访问页面时,先将img图片的路径替换成一张占位图的路径,这样就只需请求一次,而当图片进入可视区域时才把其图片的路径替换为真正的路径,从而显示图片,达到懒加载的效果。(即:懒加载就是使用同一张占位图进行占位,然后按需获取图片真正的路径,从而实现懒加载)
技术原理是:先将img的src属性隐藏,而将其真正的地址存放在img标签自定义的属性中(eg:data-src),当图片进入可视区域时,将真正的路径从data-src中取出替换回来,从而显示图片。
优点:页面加载速度快,减轻服务器端的压力,节约流量
路由懒加载:当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。
eg:
const UserDetails = () => import('./views/UserDetails')
懒加载(按需加载)原理分两步:
单向数据流在Vue中实际表现就是:当Model中的data 发生变化的时候会单向修改View中的值,而View中的值发生变化的时候,Model不会感知。 实际应用就是v-bind 单向数据。
和单向数据流相比,双向数据绑定就是多了View 变化会通知到Model层。 即MVVM的具体实现。无论Model 还是View 中的值发生变化,都会通过ViewModel通知到对方,实现同步。实际应用就是v-model双向数据绑定。
单向绑定的优点是相应的可以带来单向数据流,这样做的好处是所有状态变化都可以被记录、跟踪,状态变化通过手动调用通知,源头易追溯,没有“暗箱操作”。同时组件数据只有唯一的入口和出口,使得程序更直观更容易理解,有利于应用的可维护性。缺点则是代码量会相应的上升,数据的流转过程变长,从而出现很多类似的样板代码。同时由于对应用状态独立管理的严格要求(单一的全局store),在处理局部状态较多的场景时(如用户输入交互较多的"富表单型”应用),会显得哕嗦及繁琐。
基本上双向绑定的优缺点就是单向绑定的镜像了。优点是在麦单交万较多的场景下,会简化大量业务无关的代码。缺点就是由于都是“暗箱操作”,我们无法追踪局即状态的变化(虽然大部分情况下我们并不关心:潜在的行为大多也增加了出错时debug的难度。同时由于组件数据变化来源入口变得可能不止一个,新手玩家很容易将数据流转方向弄得紊乱,如果再缺乏一些"管制"手段,最后就很容易因为一处错误操作造成应用雪崩。
1.我们在使用Vue开发项目中,经常会有通过路由传递参数时,由于参数过多会出现会导致400 Bad Request,vuex可以解决这个问题。
2.解决多个组件共享状态时,单向数据流的简洁性很容易被破坏的问题
3.解决多个视图依赖同一状态的问题
4.解决了在中大型项目中,数据太多时,只需要在vuex更改处理数据,不用去每个页面更改
每一个 Vuex 应用的核心就是 store,里面又包括:
(1)state(数据):用来存放数据源,就是公共状态;
(2)getters(数据加工):有的时候需要对数据源进行加工,返回需要的数据;
(3)actions(事件):要执行的操作,可以进行同步或者异步事件
(4)mutations(执行):操作结束之后,actions通过commit更新state数据源(同步操作)
(5)modules:使用单一状态树,致使应用的全部状态集中到一个很大的对象,所以把每个模块的局部状态分装使每一个模块拥有本身的 state、mutation、action、getters、甚至是嵌套子模块;
vuex的工作流程就是:
(1)通过dispatch去提交一个actions,
(2) actions接收到这个事件之后,在actions中可以执行一些异步|同步操作,根据不同的情况去分发给不同的mutations,
(3)actions通过commit去触发mutations,
(4)mutations去更新state数据,state更新之后,就会通知vue进行渲染
webpack打包原理是根据文件间的依赖关系对其进行静态分析,将这些模块按指定规则生成静态资源,当 webpack处理程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,将所有这些模块打包成一个或多个bundle。
webpack的整个打包流程:
浏览器(多进程)
浏览器是多进程的,拿Chrome来说,每打开一个Tab页就会产生一个进程,使用Chrome打开很多标签页不关,电脑会越来越卡,这是因为消耗了其CPU的缘故。
浏览器包含哪些进程:
Chorme浏览器从关闭到启动,然后新开一个页面至少需要:1个浏览器进程,1个GPU进程,1个网络进程,和1个渲染进程,一共4个进程。
后续如果再打开新的标签页:浏览器进程,GPU进程,网络进程是共享的,不会重新启动,然后默认情况下会为每一个标签页配置一个渲染进程,但是也有例外,比如从A页面里面打开一个新的页面B页面,而A页面和B页面又属于同一站点的话,A和B就共用一个渲染进程,其他情况就为B创建一个新的渲染进程
所以,最新的Chrome浏览器包括:1个浏览器主进程,1个GPU进程,1个网络进程,多个渲染进程,和多个插件进程
JS的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准,因此这是一个矛盾点,是JS的功能决定了它是单线程语言。
详情可以看JS(单线程)与浏览器(多进程)
作用域:就是变量或者是函数能作用的范围。
作用域链:当查找变量的时候,会先从当前作用域的变量对象中查找,如果没有找到,就会从父级作用域(上层环境)的变量对象中查找,一直找到全局作用域的变量对象,也就是全局对象。这样由多个作用域的变量对象构成的链表就叫做作用域链。它由当前环境与上层环境的一系列变量对象组成,保证了当前执行环境对符合访问权限的变量和函数的有序访问。
理解Javascript的作用域和作用域链
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string ,number,boolean,undefined,null ,Symbol
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
判断数据类型
用const声明的常量,能不能被修改?
1、外形不同:箭头函数使用箭头定义,普通函数中没有。
2、箭头函数全都是匿名函数:普通函数可以有匿名函数,也可以有具名函数
3、箭头函数不能用于构造函数:普通函数可以用于构造函数,以此创建对象实例。
4、箭头函数中ths的指向不同:在普通函数中,ths总是指向调用它的对象,如果用作构造函数,它指向创建的对象实例。
5、箭头函数不具有arguments对象:每一个普通函数调用后都具有一个arguments对象,用来存储实际传递的参数。但
是箭头函数并没有此对象。
6、其他区别:箭头函数不具有prototype原型对象。箭头函数不具有super。箭头函数不具有new.target
undefined和null两种数据类型的区别
(1)dispaly:none 消失+重排+重绘+绑定事件不触发+无过渡;
(2)visibility:hidden 存在+不重排+重绘+绑定事件不触发+有过渡;
(3)opacity:0 存在+不重排+不一定重绘+触发自身绑定+有过渡;
(4)position:absolute 移除视线;
(5)z-index:负值 使用其他元素遮盖;
(6)transform:scale(0,0) 缩放元素为0 存在+绑定事件不触发。
事件循环机制
跨域问题
用vue进行开发,在本地起了一个项目,本地浏览的地址是localhost:8080,这是我们常见的一个地址,但是后端写的接口包括他的地址肯定不是在这个localhost:8080下,那这个时候其实就出现了跨域的情况,一般实际中处理跨域的手段就是借助那个webpack提供的那个webpack_dev-server,由它提供给我们target属性,我们再用这个target属性的时候,就可以把它转到我们的目标服务器上,这是处理跨越的手段,webpack之所以能够解决跨域,原因是本地写项目其实写在了localhost上,webpack就会在本地起一个本地服务器,也就是说这个服务器和我们前端localhost:8080是符合同源策略的,发请求发的是webpack的中间层这个代理服务器上,webpack的中间层提供的服务器和后端的服务器其实是不存在跨域问题的,由它去求求后端服务器,得到数据以后,再由中间层传给我们前端。
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8989', // target: 表示代理到的目标地址
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
ws: true,
pathRewrite: {
'^/api': '' // 自定义
}
},
}
}
网络状态响应码用来表示网页服务器HTTP响应状态的3位数字代码。请求状态码如果1开头就是临时相应,2开头一般表示成功,3开头是重定向,4开头是客户端错误,5开头是服务器错误。平时常见的响应状态码包括:200(成功)、301(永久重定向)、302(临时重定向)、304(未修改)、400(错误请求)、401(未授权)、403(禁止)、404(未找到)、500(服务器内部错误)、503(服务不可用)
浏览器缓存的全过程:
浏览器第一次加载资源,服务器返回 200,浏览器从服务器下载资源文件,并缓存资源文件与 response header,以供下次加载时对比使用;
下一次加载资源时,由于强制缓存优先级较高,先比较当前时间与上一次返回 200 时的时间差,如果没有超过 cache-control 设置的 max-age,则没有过期,并命中强缓存,直接从本地读取资源。如果浏览器不支持HTTP1.1,则使用 expires 头判断是否过期;
如果资源已过期,则表明强制缓存没有被命中,则开始协商缓存,向服务器发送带有 If-None-Match和 If-Modified-Since 的请求;
服务器收到请求后,优先根据 Etag 的值判断被请求的文件有没有做修改,Etag 值一致则没有修改,命中协商缓存,返回 304;如果不一致则有改动,直接返回新的资源文件带上新的 Etag 值并返回 200;
如果服务器收到的请求没有 Etag 值,则将 If-Modified-Since 和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回 304;不一致则返回新的 last-modified 和文件并返回 200;
1、浏览器的地址栏输入URL并按下回车
2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期
3、DNS解析URL对应的IP
4、根据P建TC连接(三次握手)
5、HTTP发起请求
6、服务器处理请求,浏览器接HTTP响应
7、渲染页面,构建DOM树
8、关闭TCP连接(四次挥手)
前端 ES6 十个新特性总结
全局路由守卫:只要路由发生了路由变化,守卫就能够监听到。
路由独享守卫:只负责一条路的守卫,beforeEnter;
组件路由守卫:只负责单个组件的守卫。