前端面试题整理(Vue篇)
1.vue中hash和 history的区别
- 首先最大的区别是带#和不带#的区别
- hash是利用 onhashchange()方法监听location.hash的改变 ,history是使用pushState()改变url但是不发送请求和replaceState()方法读取浏览器历史栈并对;浏览器历史进行修改。
- history需要后端的支持 ,每个url地址需要在后端中配置路径 如果找不到的话 就会返回404 ,所以后端资源中得有一个是覆盖所有页面的候选资源 前端得配置一个404页面。
注意: 浏览器输入一个url发生了什么?
2.浏览器输入一个url 后发生了什么?
1.首先解析域名 ,DNS对域名进行解析 ,解析成一个ip地址
2.进行 三次握手
发送端向接收端发送一个带有SYN的数据包 ,
接收端收到服务包以后返回给发送端一个SYN /ACK 的数据包 ,
发送端接收到以后 再返回给接收端一个ACK数据包
3.客户端发送HTTP 请求 带有请求头请求体之类的
4.渲染页面
5. 有可能会四次挥手 有可能是会复用连接
3.简述一下虚拟dom
虚拟dom是用JavaScript描述的一个dom节点 ,是对dom的一层抽象描述 。
我们每次操作页面的时候如果频繁的操作dom元素会对性能造成影响,所以我们造成抽象dom
在patch的过程中,尽可能的将差异一次性的更新到dom中,这样dom不会出现性能很差的情况
他的设计初衷一开始是为了跨平台 ,比如 node就没有虚拟dom ,所以要实现服务端渲染就要借助虚拟dom
它本身就是JavaScript对象
4. 说一下回流和重绘
重绘:当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,
浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。
回流:
任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发回流,
当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,
浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),
然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)
注意:
如何避免回流重绘:
1.尽量少使用style改变样式,使用class来改变样式
2.对于动画尽量放在display:absolute 或者fixed上
3.对于resize 或者 scroll这种要进行 防抖/节流
4.使用display:none,因为在display:none的元素不会触发回流重绘
5.项目中如何将http 换成https
1.我们项目的地址都放在baseUrl字段 只需要更改baseURL中的http 即可
2.可以使用meta改变http
<meta http-equiv ="Content-Security-Policy" content="upgrade-insecure-requests">
6. 说一下diff算法吧
diff 算法是一种通过同层的树节点进行比较的高效算法 ,Diff算法实现的是最小量更新虚拟DOM
其有两个特点:
比较只会在同层级进行, 不会跨层级比较
在diff比较的过程中,循环从两边向中间比较
diff 算法的在很多场景下都有应用,在 vue 中,作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较
原理分析:
当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁
通过isSameVnode进行判断,相同则调用patchVnode方法
patchVnode做了以下操作:
找到对应的真实dom,称为el
如果都有都有文本节点且不相等,将el文本节点设置为Vnode的文本节点
如果oldVnode有子节点而VNode没有,则删除el子节点
如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el
如果两者都有子节点,则执行updateChildren函数比较子节点
updateChildren主要做了以下操作:
设置新旧VNode的头尾指针
新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程、调用createElem创建一个新节点,从哈希表寻找 key一致的VNode 节点再分情况操作
7.如何解决1px的问题
1px的问题是 当我们设置 border:1px solid #fff ;时 在某些机型上会显示 2个像素,不会显示 1px;
解决办法:
1.写成0.5px ,但是不推荐,因为兼容性不行,ios支持8以上,安卓不支持
2.使用伪元素先放大后缩小#container[data-device="2"] { position: relative; } #container[data-device="2"]::after{ position:absolute; top: 0; left: 0; width: 200%; height: 200%; content:""; transform: scale(0.5); transform-origin: left top; box-sizing: border-box; border: 1px solid #333; } }
3.viewport 缩放来解决const scale = 1 / window.devicePixelRatio; // 这里 metaEl 指的是 meta 标签对应的 Dom metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
但是这样会被无差别的缩小
8.封装一个组件需要注意的事情
首先我们要注意一下是UI组件还是业务组件 。在UI组件中我们要注意不能写业务,要将逻辑代码提出来 ,考虑组件的复用性以及通用性。所以我们就要用到组件prop传值。其实就是我们要考虑代码的可读性以及向上向下兼容性。
Vue组件的API主要包含三部分:prop、event、slot
1.prop 是父组件向子组件传值
但是 prop是单向数据流 要注意不可以在子组件中更改prop传来的值
2.event 是子组件向父组件传递消息的重要途径;
3.slot可以给组件动态插入一些内容或组件,是实现高阶组件的重要途径;当需要多个插槽时,可以使用具名slot
9.vuex的原理
Vuex仅仅是Vue的一个插件。Vuex只能使用在vue上,因为其高度依赖于Vue的双向绑定和插件系统。
vuex是一个状态管理工具。里面包含 5 种 属性State、 Getter、Mutation 、Action、 Module。
state是一个单一状态树 ,存放了数据 。
Getter类似于Vue的 computed 对象。是根据业务逻辑来处理State,使得生成业务所需的属性。
Mutation是唯一用来更改Vuex中数据的方法 ,使用commit修改state中的数据。
Action是用来解决异步操作而产生的,它提交的是Mutation。
Module是将Vuex模块化的对象,目的是更好的维护。
注意:在刷新网页后,保存在vuex实例store里的数据会丢失 我们可以存放在本地存储中
10.vue中computer和watch有什么区别
1.computer 有缓存 只有当computer依赖的数据改变才会改变 。watch 没有缓存 。
2.computer 不能处理异步请求 ,但是watch可以 。
3.watch监听的数据必须在data或者props中存在 ,而computer是通过计算得到的一个新值。
4.在computer中有两个属性 ,一个是get一个是set,当数据变化时,调用 set 方法。watch监听有两个参数 ,一个是oldValue,一个是newValue