总结:二面基本问简历项目以及实习
1.VUE-router这一块你有没有遇到就是在跳转的时候,有没有白屏这种情况,尤其是路由切换的时候,是怎么处理的
- 懒加载组件: 如果你使用了懒加载(异步组件)来延迟加载某些路由组件,在切换路由时可能会导致白屏,因为组件的加载是异步的。
- 处理方法: 确保懒加载的组件都正确配置了懒加载语法,例如使用 import() 语法。同时,可以考虑在组件加载前显示一个加载状态,以避免白屏的显著影响。
-
const MyComponent = () => import(/* webpackChunkName: "my-component" */ '@/components/MyComponent')
- 路由守卫和异步操作: 在路由守卫中执行了异步操作,如果这些异步操作尚未完成,就会导致组件未能完全加载。
- 处理方法: 确保在路由守卫中没有进行过多的异步操作,或者使用 beforeRouteEnter 钩子来确保异步操作完成后再进入路由。
-
beforeRouteEnter(to, from, next) { fetchDataAsync().then(() => { next() }) }
- 全局样式加载延迟: 如果你的样式表很大或者在全局样式中有一些复杂的样式计算,可能导致页面白屏。
- 处理方法: 尽量优化样式表,确保样式表的加载和解析不会成为性能瓶颈。可以考虑将一些非必要的全局样式延迟加载,或者按需加载。
- 资源加载问题: 如果路由切换涉及到大量资源的加载,可能会导致白屏。
- 处理方法: 使用懒加载和异步加载的方式,确保只在需要时加载资源。可以使用Webpack的代码分割功能,将代码拆分成小块,按需加载。
-
/ 在路由配置中使用懒加载 const MyComponent = () => import('@/components/MyComponent') // 使用Webpack的代码分割 import(/* webpackChunkName: "my-chunk" */ '@/path/to/my-chunk')
Webpack的代码分割是通过将代码拆分成更小的块,然后按需加载这些块,从而提高应用程序的性能。 不太会
- 网络问题: 如果在路由切换时,网络请求耗时较长,也可能导致白屏。
- 处理方法: 优化网络请求,确保数据的快速加载。可以使用loading状态或者骨架屏等方式在数据加载时提供用户反馈。
// 使用loading状态或者骨架屏
data() {
return {
isLoading: true,
// other data
}
},
created() {
fetchDataAsync().then(data => {
this.data = data
this.isLoading = false
}).catch(error => {
console.error('Error fetching data:', error)
this.isLoading = false
})}
2. 假设你某一个单页面,比较大,我iport的时间比较旧的话,这种场景,如何让他变得体验好一点
1. 代码分割(Code Splitting):
如前所述,使用Webpack的代码分割功能来按需加载模块。这可以减小初始加载的大小,提高页面加载速度。尽可能地将不同页面或功能的代码拆分成独立的块。
2. 懒加载(Lazy Loading):
将不是立即需要的模块延迟加载。这样可以使初始加载更快,只有在用户需要时才加载额外的模块。使用动态 import()
或框架提供的懒加载机制。
3.这样一个情况,有一个图片,这个图片是有一个高度的,我加载这个图片的一瞬间,会把我们图片内容给顶到下面去。比如:本来我想点一个按钮,但是一开始不知道哪里有一个图片懒加载,让我点按钮的一瞬间,图片加载出来了,把按钮顶到下面去了。这考虑国就是,图片加载会引起页面布局的变化你应该了解吗?有什么办法去解决吗?拿图片举例,有的方案会有一个纯色的底图,他会在懒加载出来之后,给你替换掉,有知道是怎么去实现的吗?
是的,这是一个常见的问题,被称为"加载位移"或"图片闪烁"。当页面中的图片懒加载完成后,会引起页面布局的变化,从而导致用户体验不佳。为了解决这个问题,可以考虑以下一些方法:
1.设置图片占位符: 在图片加载之前,可以使用一个占位符,例如纯色的底图或者和图片相似的小尺寸的预览图。这个占位符的大小应该与实际图片相同,以保持页面布局的稳定性。当图片加载完成后,再替换为实际的图片。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Loading</title>
<style>
.image-container {
position: relative;
width: 300px; /* 设置图片容器的宽度 */
height: 200px; /* 设置图片容器的高度 */
}
.placeholder {
width: 100%; /* 占位符宽度与容器相同 */
height: 100%; /* 占位符高度与容器相同 */
background-color: #ddd; /* 设置占位符的背景颜色 */
}
.actual-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none; /* 初始时隐藏实际图片 */
}
</style>
</head>
<body>
<div class="image-container">
<div class="placeholder"></div>
<img class="actual-image" src="path/to/your/image.jpg" alt="Actual Image">
</div>
<!-- 其他页面内容 -->
</body>
</html>
2.指定图片的固定高度: 在加载图片之前,可以为图片元素设置一个固定的高度(如果宽度是固定的,则同时设置宽度),这样即使图片未加载时,占位的空间也已经预留好,不会因为图片加载引起布局变化。
3.使用样式属性min-height: 可以为图片元素设置min-height属性,以确保在图片加载之前,元素有一个最小高度,从而防止页面布局的变化。
4.使用缓存: 尽量利用浏览器缓存,如果图片已经被加载过,再次加载时可以直接从缓存中获取,减少加载时间。
5.使用CSS动画: 可以使用CSS动画来平滑过渡图片加载。例如,可以在图片元素上应用一个淡入的动画,使得图片加载时过渡更加柔和,减轻用户感知的变化。
<style>
.image-container {
width: 300px;
height: 200px;
overflow: hidden; /* 用于隐藏溢出的内容 */
}
.actual-image {
width: 100%;
height: 100%;
opacity: 0; /* 初始时设置透明度为0 */
transition: opacity 0.5s ease; /* 添加过渡效果 */
}
.actual-image.loaded {
opacity: 1; /* 图片加载完成后透明度变为1 */
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
var img = document.querySelector('.actual-image');
img.onload = function () {
img.classList.add('loaded'); /* 图片加载完成后添加loaded类 */
};
img.src = 'path/to/your/image.jpg'; /* 设置图片路径触发加载 */
});
</script>
4.有遇到过,有大量的图片在一个区域内展示,在加载完的时候,他就是一大串图片在这展示,但是在没加载完的时候,他们的节点就是会都挤在一起,懒加载会失效,因为这时候observe的判断,就会认为你的图片都在可加范围内,还是会导致大量的请求
作者:菜鸟过渡者
链接:酷家乐_牛客网
来源:牛客网
理解了,这是一个常见的问题,当一大串图片挤在一起并且在加载过程中,懒加载机制可能会失效。为了解决这个问题,可以考虑以下几种方案:
1. 占位符 + 懒加载
在图片加载之前,可以使用占位符来占据图片的位置,防止图片加载前导致的节点挤在一起的情况。可以使用一张小尺寸的占位图或者使用纯色的占位符。
<div class="image-container">
<div class="placeholder"></div>
<img class="lazy-load" data-src="path/to/your/image.jpg" alt="Actual Image">
</div>
然后使用懒加载库,比如 Intersection Observer 来加载图片:
<script>
document.addEventListener('DOMContentLoaded', function () {
var lazyLoadImages = document.querySelectorAll('.lazy-load');
var observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
var img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
lazyLoadImages.forEach(function (img) {
observer.observe(img);
});
});
</script>
2. 图片容器样式设置
使用CSS样式来确保图片在加载前不会导致节点挤在一起。可以设置图片容器为固定的高度,或者使用 min-height 来避免在加载前发生布局的改变。
.image-container {
min-height: 200px; /* 设置最小高度 */
overflow: hidden; /* 避免溢出 */
}
3. 图片瀑布流布局
如果有大量图片,可以考虑使用瀑布流布局,这样即使在加载前也能更好地分散图片,减少挤在一起的情况。
这些方法可以根据具体情况组合使用,以确保在加载前和加载后都能有良好的展示效果。
瀑布流布局是一种动态网页布局方式,常用于图片等元素的展示。每一列的高度会根据当前列的内容动态变化,从而呈现出瀑布流的效果。
HTML 结构
html
<div class="masonry">
<div class="item"><img src="path/to/image1.jpg" alt="Image 1"></div>
<div class="item"><img src="path/to/image2.jpg" alt="Image 2"></div>
<!-- More items... -->
</div>
CSS 样式
css
.masonry {
column-count: 3; /* 列数 */
column-gap: 10px; /* 列之间的间隔 */
}
.item {
break-inside: avoid-column; /* 避免元素在列间断开 */
margin-bottom: 10px; /* 元素之间的间隔 */
}
在这个例子中,我们创建了一个 .masonry 容器,使用 column-count 设置列数,通过 column-gap 设置列之间的间隔。每个图片项使用 .item 类,并通过 break-inside: avoid-column 防止元素在列间断开,从而更好地展示出瀑布流效果。
1.如何判断链表有环:
快慢指针方法:
一个快指针一个慢指针,如果链表中存在环,快指针最终会追上慢指针,否则,如果链表是一个线性链表,则快指针会提前到达链表尾部。
以下是详细思路和使用JavaScript的实现:
- 定义两个指针,一个称为慢指针(slow),另一个称为快指针(fast)。
- 初始时,慢指针指向链表的头节点,而快指针指向头节点的下一个节点。
- 使用循环,每次迭代中,慢指针移动一步,而快指针移动两步。
- 如果链表中存在环,快指针最终会追上慢指针,即它们会指向同一个节点。
- 如果链表中不存在环,快指针会提前到达链表尾部,此时可以判断链表无环。
class ListNode {
constructor(value) {
this.value = value;
this.next = null;
}
}
function hasCycle(head) {
if (!head || !head.next) {
return false; // 链表为空或只有一个节点,肯定无环
}
let slow = head;
let fast = head.next;
while (slow !== fast) {
if (!fast || !fast.next) {
return false; // 如果快指针或快指针的下一个节点为空,说明链表无环
}
slow = slow.next;
fast = fast.next.next;
}
return true; // 快指针追上慢指针,链表有环
}
2.我有一个数组,然后我想现在有一个操作就是删除其中的一个元素,怎么去做?那我不想影响原始的数组,我想构建一个新的数组,这个怎么做?假设 我不关心数组的位置,我删掉以后,数组元素的位置他变不变也无所谓,有没有什么办法在o(1)的复杂度完成这个动作。就是我删除索引为3的数值,我不想遍历它,就让他的复杂度为o(1)。不关心顺序
这个方法的思路是将待删除索引位置的元素替换为数组的最后一个元素,然后通过 pop 方法删除最后一个元素。这样就能在 O(1) 复杂度内完成删除操作。需要注意的是,这样的操作会改变数组中元素的顺序。
请注意,这并不是严格意义上的删除,而是一种替换的方法。
function deleteAtIndex(arr, index) {
if (index < 0 || index >= arr.length) {
return arr.slice(); // 索引越界,返回原数组的副本
}
const lastElement = arr.pop(); // 弹出数组的最后一个元素
if (index < arr.length) {
const deletedElement = arr[index];
arr[index] = lastElement; // 将最后一个元素放到删除位置
}
return arr;
}
// 示例用法
const originalArray = [1, 2, 3, 4, 5];
const newArray = deleteAtIndex(originalArray, 2);
console.log(originalArray); // 原数组不受影响
console.log(newArray); // 新数组删除了索引为2的元素
3.我有一个二维数组,他的值是几,高度就是几,求问这些块级的表面积。边界考虑
- 上表面积: 每个块都有上表面积,因此先将总表面积增加2。
- 左侧表面积: 对于每个块,我们需要考虑其左侧是否有相邻块。如果有,我们计算两者高度差,取其最大值。这个值表示了左侧表面积的增加量。
- 右侧表面积: 同样,对于每个块,我们需要考虑其上方是否有相邻块。如果有,我们计算两者高度差,取其最大值。这个值表示了右侧表面积的增加量。
在边界处,我们通过条件判断确保不会越界。这个实现方法适用于表示高度的二维数组,其中数组的值表示块的高度。这个例子中,exampleGrid 是一个二维数组,然后我们调用 surfaceArea 函数计算块级的表面积。
function surfaceArea(grid) {
const rows = grid.length;
const cols = grid[0].length;
let totalArea = 0;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
const height = grid[i][j];
if (height > 0) {
// 上表面积,每个块都有上表面积,面积为2
totalArea += 2;
// 左侧表面积,考虑相邻块高度差
totalArea += Math.max(0, height - (i > 0 ? grid[i - 1][j] : 0));
// 右侧表面积,考虑相邻块高度差
totalArea += Math.max(0, height - (j > 0 ? grid[i][j - 1] : 0));
}
}
}
return totalArea;
}
// 示例用法
const exampleGrid = [
[1, 3],
[2, 4]
];
const result = surfaceArea(exampleGrid);
console.log(result); // 输出块级的表面积
4.复杂请求的预检请求 怎么优化
预检请求(Preflight Requests)是一种在实际请求之前,浏览器会先发送一个 OPTIONS 请求到服务器的机制。这通常发生在跨域请求时,特别是对于复杂请求(带有自定义头部、使用某些不常见的 HTTP 方法等)。
为了优化预检请求的过程,可以考虑以下几个方面:
1. 使用简单请求避免预检请求:
简单请求是指满足一定条件的请求,它们不会触发预检请求。条件包括:
1.使用以下 HTTP 方法之一:GET、HEAD、POST。
2.只使用简单标头(simple headers),例如:Accept、Accept-Language、Content-Language、Content-Type(但限于特定的值)。
如果请求可以设计成简单请求,就可以避免预检请求的发送。
2. 合理设置请求头:
3.尽量避免在请求头中添加不必要的自定义头部。
4.如果确实需要添加自定义头部,确保这些头部是必需的,否则考虑是否能够通过其他方式满足需求。
3. 使用CORS配置进行缓存:
对于跨域资源,服务器可以配置 CORS(Cross-Origin Resource Sharing)响应头中的 Access-Control-Max-Age,表示预检请求的结果可以被缓存的时间,减少不必要的预检请求。
Access-Control-Max-Age: 3600
4. 合理配置CORS允许的方法:
如果不需要支持所有 HTTP 方法,可以在 CORS 配置中只允许实际需要的方法,减少预检请求中的方法列表。
Access-Control-Allow-Methods: GET, POST, PUT
5. 合理配置CORS允许的头部:
如果有必要,可以在 CORS 配置中只允许实际需要的自定义头部,减少预检请求中的头部列表。
Access-Control-Allow-Headers: Content-Type, Authorization
6. 使用代理或反向代理:
在某些情况下,使用代理或反向代理可以将跨域请求转换为同源请求,从而避免预检请求。
7. 使用 JSONP 或其他跨域技术:
对于一些简单的跨域请求,例如获取 JSON 数据,可以考虑使用 JSONP 或其他适合的跨域技术。
以上方法的选择取决于具体的应用场景和需求。在设计 API 和前端应用时,合理规划请求头、方法和 CORS 配置,以减少预检请求的次数,提高请求效率。
5.简单请求和复杂请求的区别
跨域请求根据其复杂性可以分为简单请求和复杂请求。这两者之间的主要区别在于浏览器在发送请求前是否会发送一个预检(preflight)请求。
简单请求(Simple Request):
1.HTTP方法: 只使用以下几种 HTTP 方法之一:GET、HEAD、POST。
2.Content-Type: 请求的 Content-Type 只能是以下三者之一:
3.application/x-www-form-urlencoded
4.multipart/form-data
5.text/plain
6.自定义头信息: 只能使用以下几种自定义头信息之一:
7.Accept
8.Accept-Language
9.Content-Language
10.Content-Type(限于上述规定的几种值)
对于简单请求,浏览器会直接发送请求,不会先发送预检请求。服务器在收到请求时,如果允许跨域,会在响应头中包含 CORS 相关的头信息(例如 Access-Control-Allow-Origin)。
复杂请求(Complex Request):
不符合简单请求条件的请求就被认为是复杂请求。
11.HTTP方法: 使用其他方法,如 PUT、DELETE。
12.Content-Type: 使用了除了上述简单请求中规定的三种之外的 Content-Type。
13.自定义头信息: 使用了除了上述简单请求中规定的几种之外的自定义头信息。
对于复杂请求,浏览器在发送实际请求之前,会先发送一个 OPTIONS 请求,进行预检。服务器需要响应这个预检请求,确认是否允许实际请求。只有在预检请求的响应中包含了相应的 CORS 头信息,并且服务器明确允许实际请求,浏览器才会发送实际请求。
这种预检的机制帮助确保对服务器的访问是安全的,并防止恶意网站对用户数据的滥用。