前端面试 Vue2/3
文章目录
- 前端面试 Vue2/3
- axios 是同步异步?异步
- 请求头中去掉host还能请求成功吗? 不能
- UDP和TCP的区别
- 渲染列表,当一个接口请求数据量较大时,怎么优化不卡顿?
- setup中顶层可以直接使用await吗?
- 在vue模板中,style中能否使用scirpt 中定义的变量
- Vue3 修改 ref的值,不触发watchEffect的原因
- [vue3中computed(), watch() 和 watchEffect()的区别](https://blog.csdn.net/DM_Cxx/article/details/131379745)
- 模块化与组件化
- vue/cli或者vite脚手架搭建的vue3项目兼容低版本谷歌浏览器
- new的四个步骤
- ajax 无法后退怎么解决
- [经典js面试题 Foo.getName](https://www.jb51.net/article/241918.htm) 优先级:函数声明提升>变量提升
- [让 Chrome 浏览器支持小于 12px 文字的方法](https://blog.csdn.net/weixin_57837275/article/details/135231461)
- 网站性能优化的10种方法
- 什么是事件冒泡,它是如何工作的?如何阻止事件冒泡?
- TS中的类型体操是什么?
- 在Vue3 中 使用`Transition`组件 多个根节点白屏或报错?
axios 是同步异步?异步
- axios是一个基于Promise的HTTP客户端,它可以用于浏览器和Node.js。默认情况下,它是异步的,即发送请求后,不会等待响应返回,而是继续执行后续代码。但是,axios也提供了一种同步的方式来发送请求,即使用
async/await
关键字。在使用async/await的情况下,请求发送后会一直等待响应返回,然后再继续执行后续代码。在实际应用中,我们可以根据需求选择异步或同步的方式来发送请求. - 在ajax中 ,如果需要使用同步请求,可以通过设置async属性为来实现同步请求.
- js XMLHttpRequest对象发送网络请求
<input name="submit" type="button" id="submit" value="向服务器发出请求" />
<script>
var xhr = new XMLHttpRequest() //实例化XMLHttpRequest 对象
var b = document.querySelector("#submit");
b.onclick = function () {
xhr.open("POST", "接口地址url", true); //建立连接,要求异步响应
xhr.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded'); //设置为表单方式提交
xhr.send("callback=functionName"); //发送请求
xhr.onreadystatechange = function () { //绑定响应状态事件监听函数
if (xhr.readyState == 4 && xhr.status == 200) { //监听readyState状态和HTTP状态码
console.log(xhr.responseText); //接收数据 json字符串,使用时需转josn对象
}
}
}
</script>
请求头中去掉host还能请求成功吗? 不能
在 HTTP/1.1 协议中,请求头中的 Host 字段是必需的,因为同一台服务器可能会承载多个网站或应用,Host 字段可以帮助服务器区分不同的请求。如果请求中去掉 Host 字段,则服务器无法正确处理该请求,因此请求不会成功。
在HTTP/2和HTTP/3中,请求头中的Host字段被强制为必需项,所以无法去掉。
UDP和TCP的区别
-可靠性: TCP协议在这就是可靠传输(安全性高),而UDP在这块就是不可靠传输(安全性低);UDP协议的传输效率是高于TCP协议的传输效率的。
渲染列表,当一个接口请求数据量较大时,怎么优化不卡顿?
- 使用虚拟列表插件
- 虚拟列表只渲染当前可见的部分数据,随着滚动条的滚动,只渲染当前可见的列表项 ,从而大大减少了渲染时间。同时支持无限滚动,用户只需要不停地滚动页面,就可以看到所有的数据,从而提高了用户的体验。
- vue2版本 vue-virtual-scroll-list
- 实现原理
- 元素固定高度的虚拟列表/ 元素不定高度的虚拟列表 /元素动态高度的虚拟列表
setup中顶层可以直接使用await吗?
<script setup>
中可以使用顶层 await。结果代码会被编译成 async setup()
setup前面会自动加一个async.
const data = await fetch(“”);
在vue模板中,style中能否使用scirpt 中定义的变量
- vue3中
<template>
<h1> shit! </h1>
</template>
<script>
export default {
data () {
return {
color: 'yellow',
font: {
weight: 100
},
}
}
}
</script>
<style>
h1 {
color: v-bind(color);
font-weight: v-bind('font.weight');
}
</style>
- vue2 中
<template>
<h1>Vue</h1>
</template>
<script>
export default {
data () {
return {
opacity: 0
}
},
mounted () {
setInterval(_ => {
this.opacity >= 1 && (this.opacity = 0)
this.opacity += 0.2
}, 300)
}
}
</script>
<style vars="{ opacity }">
h1 {
color: rgb(65, 184, 131);
opacity: var(--opacity);
}
Vue3 修改 ref的值,不触发watchEffect的原因
const myRef = ref(name: ‘jinD’)
修改 myRef.value.xxx时,不触发watchEffect的原因在于,触发trigger传入的对象是否相同,在 watchEffect 里面访问 myRef.value 时,此时 track的target 是refCompImpl实例,也就是ref
但是修改值时,是通过 myRef.value.xxx = newValue, 不是给 myRef.value = {}设置新值,触发的trigger是在 proxy 的 getter里面(ref 都给传入的对象调用了reative, 也就是把传入的对象转为了proxy),此时trigger的target = {name: ‘xxx’}, 和之前track的 target不一致,没有获取到对应的effect(一个effect就是一个依赖,这里可以理解为watchEffect传入的cb), 所以不会导致 watchEffect 传入的cb重新执行.
vue3中computed(), watch() 和 watchEffect()的区别
- computed特点
在 getter 函数中,在追踪的响应式依赖没有发生变化时,返回都会是上次缓存的数据。(计算属性和方法的区别)
只有在computed中的响应式依赖发生变化时,才会再次进行运算。 - watch特点
懒执行,仅当数据变化时执行(immediate: true 除外)
更加明确需要侦听的数据源,更精准的控制回调函数的触发时机
可以访问所侦听状态的前一个值和当前值 - watchEffect特点
首次加载会执行一次,即便是空函数
自动追踪所有能访问到的响应式属性,任一属性发生变化都会触发回调函数
无法获取前一个值和当前值
flush: 调整回调函数的刷新时机
pre: 默认值,回调会在 Vue 组件更新之前被调用,此时在回调中访问的 DOM 将是 Vue 更新之前的状态
post: Vue 组件更新之后调用侦听器的回调函数。此时在回调函数中访问的 DOM 将是 Vue 更新之后的状态
sync: 同步执行,当侦听到变化时回调函数立即执行,执行完成后才接着执行后面的代码
模块化与组件化
组件相当于库,模块相当于框架.
-
组件化就是把可以复用的、独立的、基础的代码封装到一个方法或者代码片段里,需要的地方引入使用。用极少的代码实现之前相同的功能,避免代码的复写,提高了开发的效率。
-
模块化是为了单独实现某一功能模块进行封装的方法,一个模块里可能拥有n个基础组件搭配产生。模块化属于横向分块,每个模块像一条横向把n条竖直的线串联起来形成一个整体。
模块化
概述:把多功能、高耦合的代码逻辑拆散成多个功能单一、职责明确的模块。
- 好处:
复用
解耦
协同开发 - 缺点:
编译的时间越来越长,降低了开发效率
模块的增多,不可避免的会出现耦合
模块之间的相互影响
组件化
概述:组件化开发就是将一个app分成多个模块,每个模块都是一个组件(Module),开发的过程中我们可以让这些组件相互依赖或者单独调试部分组件等,但是最终发布的时候是将这些组件合并统一成一个apk,这就是组件化开发 - 好处:
架构灵活
便于开发和维护,有利于提高效率
组件间充分解耦
每个组件可以单独测试 - 缺点:
版本引起的冲突
资源命名重复
组件和模块的区别:
组件:就像一个个小的单位,多个组件可以组合成组件库,方便调用和复用,组件间也可以嵌套,小组件组合成大组件。
模块:就像是独立的功能和项目,可以调用组件来组成模块,多个模块可以组合成业务框架。
vue/cli或者vite脚手架搭建的vue3项目兼容低版本谷歌浏览器
问题描述:当vue3项目打包上线后,最新版本的谷歌浏览器可以正常访问项目,但是低版本的谷歌浏览器打开页面后是空白页,控制台会有报错
解决方案如下:
一、vue/cli搭建的vue3项目
找到项目中的.browserslistrc文件,增加一行
chorme >48
二、vite搭建的vue3项目
1.安装插件
cnpm i @vitejs/plugin-legacy terser -D
2.在vite.config.js中配置
//引入
import legacy from "@vitejs/plugin-legacy"
//在plugins中添加
plugins:[
...
legacy({
targets:['chrome 52']
})
]
new的四个步骤
创建一个空对象—>这个新对象继承原函数的原型—>更改this指向,为对象设置属性—>返回新对象
ajax 无法后退怎么解决
AJAX(Asynchronous JavaScript and XML)是一种创建交互式网页应用的技术,不支持浏览器的后退功能。**这是因为AJAX通过XMLHttpRequest对象发送异步请求,而不是重新加载整个页面。**因此,浏览器的历史记录不会记录这些请求,无法通过后退按钮回到之前的页面状态。
有几种方法可以模拟AJAX的后退功能:
- 使用 history.pushState 和 history.replaceState 方法更新浏览器历史记录,使其记录AJAX状态。
- 使用 onpopstate 事件监听用户的后退操作,并相应地更新页面内容。
下面是一个简单的示例,演示如何使用 history.pushState 和 onpopstate 来实现AJAX的后退功能:
window.onload = function() {
var content = document.getElementById('content');
content.addEventListener('click', function(e) {
if (e.target && e.target.nodeName == "A") {
loadContent(e.target.href, e.target.title);
e.preventDefault();
}
});
window.onpopstate = function(event) {
if (event.state) {
loadContent(event.state.url, event.state.title, true);
}
};
function loadContent(url, title, replace) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
content.innerHTML = xhr.responseText;
if (replace) {
history.replaceState({ url: url, title: title });
} else {
history.pushState({ url: url, title: title }, title, url);
}
}
};
xhr.send();
}
};
在这个示例中,当用户点击一个链接时,loadContent 函数被触发,它发送一个AJAX请求来获取内容,并更新页面的显示内容。同时,使用 history.pushState 将请求的URL和标题保存到历史记录中。如果用户点击后退按钮,onpopstate 事件将被触发,然后调用 loadContent 函数,使用 history.state 来获取历史记录中的状态信息,并用它来模拟后退到之前的状态。
经典js面试题 Foo.getName 优先级:函数声明提升>变量提升
function Foo() {
getName = function () {
console.log(1);
};
return this;
};
Foo.getName = function () {
console.log(2);
};
Foo.prototype.getName = function () {
console.log(3);
};
var getName = function () {
console.log(4);
};
function getName() {
console.log(5);
};
//执行结果是什么?
Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3
让 Chrome 浏览器支持小于 12px 文字的方法
使用缩放比例:可以使用 CSS 的 transform 属性来缩放文本元素以达到小于 12px 的效果。例如,使用 transform: scale(0.8) 将文本缩放为 80% 的原始大小。请注意,这可能会导致文本外观变得模糊或失真。
.small-text {
transform: scale(0.8);
}
使用 zoom:将容器或文本元素的 zoom 属性设置为小于 1 的值,例如 zoom: 0.8;。这会缩小文本元素及其容器,使得文本看起来更小。请注意,zoom 是非标准的 CSS 属性,不一定在所有浏览器中都有效。
.small-text {
zoom: 0.8;
}
使用 -webkit-text-size-adjust:将容器或文本元素的 -webkit-text-size-adjust 属性设置为 “none” 或 “auto” 可以控制 Chrome 浏览器对文本大小的调整行为。通过将其设置为 “none”,可以禁用 Chrome 浏览器的最小字体大小限制。请注意,-webkit-text-size-adjust 是针对 WebKit 内核(包括 Chrome 和 Safari)的私有属性。
.small-text {
-webkit-text-size-adjust: none;
}
使用图片替代:如果需要应用较小的文字大小,并且无法使用缩放,可以将文本转换为图像,并将其作为背景图像或内联图像插入到元素中。这样可以绕过浏览器的最小字体大小限制。但要注意,这将增加页面加载时间并且不利于可访问性和响应式设计。
<div class="small-text">
<img src="path/to/small_text_image.png" alt="Small Text">
</div>
网站性能优化的10种方法
1)尽量减少HTTP请求次数
合并js
合并css
图片sprite
2)延迟加载内容
图片懒加载
数据懒加载(点击查看更多)
功能懒加载(曝光或者点击后加载html模块、js功能模块)
3)使用离线缓存
把常用的变动又少的js、css、图片存储到localstorage,第二次访问的时候直接走本地缓存。在移动端使用广泛。
4)CSS、JS放置正确位置
把css放在head中,保证页面看到的时候样式是对的。
把js放到body里最后位置,防止加载js阻塞页面。
5)静态资源压缩
图片、CSS、JS在发布前要压缩。
6)静态资源使用多个域名
对于图片、CSS、JS,可使用几个域名,可以并发加载。
7)静态资源使用cdn存储
用户与你网站服务器的接近程度会影响响应时间的长短。 可以把静态资源放到内容分发网络(Content Delivery Network,CDN)中加快访问速度。
8)预加载
在某个功能还没展现时,在空闲时间预先加载相关图片或者js代码
9)DOM操作优化
使用JavaScript访问DOM元素比较慢,因此为了获得更多的应该页面,应该做到:
缓存已经访问过的有关元素
线下更新完节点之后再将它们添加到文档树中
避免使用JavaScript来修改页面布局
10)优化算法
在js处理中优化查找、排序算法。尽量少使用嵌套循环
什么是事件冒泡,它是如何工作的?如何阻止事件冒泡?
在一个对象上触发某类事件(比如单击 onclick 事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即 document 对象(有些浏览器是 window)
2、阻止事件冒泡的几种方法
2.1)第一种:event.stopPropagation();
2.2)第二种:return false;
2.3)第三种:event.preventDefault();
TS中的类型体操是什么?
- 可以简单理解为类型编程,对类型参数做各种逻辑运算,以产生新的类型。
在Vue3 中 使用
Transition
组件 多个根节点白屏或报错?
- 在Vue 3中,使用组件时遇到“不支持多个根节点”的错误通常意味着你尝试过渡的元素内部包含了多个根元素。Vue 3要求的子组件必须只有一个根节点。
- 解决办法: 在内部包裹一层
<Transition> <div> <!-- 内部内容 --> </div> </Transition>