前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端面经:面试了 10+ 家公司,面试题总结和经验分享

前端面经:面试了 10+ 家公司,面试题总结和经验分享

作者头像
肥晨
发布于 2024-11-12 07:01:09
发布于 2024-11-12 07:01:09
28300
代码可运行
举报
文章被收录于专栏:农民工前端农民工前端
运行总次数:0
代码可运行

最近想重新找工作,在苏州和上海面试了挺多公司,总结出一些面经,和大家分享一下。

现在面试,其实大部分还是以前的经典八股文,绝大部分都能用以前的老八股: (点击来看这篇文章)2023金九银十必看前端面试题!2w字精品!

还有一些比较新颖的面试题,和大家分享一下。

1.vue父子组件的生命周期?

刚听到这个问题还是愣了一下的,最后回来🔍了学习,和大家总结分享一下。

父子组件的生命周期钩子是相互独立的,但是有一定的顺序,子组件的生命周期钩子一般会在父组件的生命周期钩子之前执行。

使用这些生命周期钩子可以控制父子组件间的行为,比如数据初始化、DOM 更新、销毁等操作。

Vue 父子组件的生命周期顺序

当一个父组件渲染子组件时,子组件的生命周期钩子会比父组件的生命周期钩子早执行。下面是父子组件生命周期的顺序和相关的生命周期钩子:

  1. 父组件的生命周期(从上到下)
    • beforeCreate: 在父组件实例被创建之前。
    • created: 父组件实例已经创建完成,此时数据已经初始化,但未渲染 DOM。
    • beforeMount: 在父组件挂载到 DOM 之前被调用。
    • mounted: 父组件挂载完成,DOM 元素已可用。
  2. 子组件的生命周期(从上到下)
    • beforeCreate: 子组件实例被创建前。
    • created: 子组件实例已经创建,数据已经初始化,尚未挂载到 DOM。
    • beforeMount: 子组件准备挂载前被调用。
    • mounted: 子组件挂载完成,DOM 元素已可用。
  3. 父组件的生命周期(继续执行)
    • beforeUpdate: 父组件的响应式数据发生变化时调用。
    • updated: 当父组件的 DOM 更新后调用。
    • beforeDestroy / beforeUnmount(Vue 3 使用 beforeUnmount):父组件即将被销毁前调用。
    • destroyed / unmounted(Vue 3 使用 unmounted):父组件销毁后调用。
  4. 子组件的生命周期(如果父组件有子组件销毁)
    • beforeUnmount: 子组件即将被销毁前调用。
    • unmounted: 子组件销毁后调用。
父子组件生命周期钩子详细介绍
1. beforeCreate 和 created
  • 父组件beforeCreatecreated 是在父组件实例创建过程中调用的。
    • beforeCreate 阶段无法访问任何数据、计算属性、方法等,因为这些还没有初始化。
    • created 阶段可以访问到父组件的响应式数据、计算属性和方法,但是尚未渲染 DOM。
  • 子组件beforeCreatecreated 也是子组件生命周期的初始阶段。
    • beforeCreate 阶段子组件的响应式数据尚未被初始化,因此不能使用任何数据。
    • created 阶段,子组件的数据、计算属性和方法已初始化,但尚未挂载到 DOM。
2. beforeMount 和 mounted
  • 父组件beforeMountmounted 发生在父组件挂载到 DOM 时。
    • beforeMount 阶段,父组件尚未渲染和挂载 DOM。
    • mounted 阶段,父组件的 DOM 渲染完成,已经可供操作。
  • 子组件:当父组件渲染子组件时,子组件的 beforeMountmounted 会先于父组件的 beforeMountmounted 执行。
    • beforeMount 阶段,子组件准备挂载到 DOM,但尚未挂载。
    • mounted 阶段,子组件挂载完成,DOM 元素可用。
3. beforeUpdate 和 updated
  • 父组件:当父组件的响应式数据变化时,beforeUpdate 会在组件更新之前调用,updated 会在 DOM 更新之后调用。
    • beforeUpdate 阶段,父组件的响应式数据发生变化,但 DOM 还没有更新。
    • updated 阶段,父组件的 DOM 已经更新,变化已反映到视图上。
  • 子组件:子组件的生命周期钩子 beforeUpdateupdated 也在父组件更新时被触发。
    • beforeUpdate 阶段,子组件的响应式数据变化,但 DOM 尚未更新。
    • updated 阶段,子组件的 DOM 已更新,视图已变化。
4. beforeUnmount 和 unmounted(销毁时)
  • 父组件beforeUnmountunmounted 钩子在父组件销毁时调用。
    • beforeUnmount 在父组件销毁前调用,通常用于清理定时器、事件监听等副作用。
    • unmounted 在父组件销毁之后调用。
  • 子组件beforeUnmountunmounted 在子组件销毁时调用,顺序是子组件先销毁,再销毁父组件。
    • beforeUnmount 在子组件销毁之前调用。
    • unmounted 在子组件销毁之后调用。
示例:父子组件生命周期钩子
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 父组件 Parent.vue -->
<template>
  <div>
    <p>父组件</p>
    <Child />
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child
  },
  beforeCreate() {
    console.log('父组件 beforeCreate');
  },
  created() {
    console.log('父组件 created');
  },
  beforeMount() {
    console.log('父组件 beforeMount');
  },
  mounted() {
    console.log('父组件 mounted');
  },
  beforeUpdate() {
    console.log('父组件 beforeUpdate');
  },
  updated() {
    console.log('父组件 updated');
  },
  beforeUnmount() {
    console.log('父组件 beforeUnmount');
  },
  unmounted() {
    console.log('父组件 unmounted');
  }
};
</script>

<!-- 子组件 Child.vue -->
<template>
  <p>子组件</p>
</template>

<script>
export default {
  beforeCreate() {
    console.log('子组件 beforeCreate');
  },
  created() {
    console.log('子组件 created');
  },
  beforeMount() {
    console.log('子组件 beforeMount');
  },
  mounted() {
    console.log('子组件 mounted');
  },
  beforeUpdate() {
    console.log('子组件 beforeUpdate');
  },
  updated() {
    console.log('子组件 updated');
  },
  beforeUnmount() {
    console.log('子组件 beforeUnmount');
  },
  unmounted() {
    console.log('子组件 unmounted');
  }
};
</script>
控制台输出顺序

当父子组件渲染时,控制台输出的生命周期钩子的顺序如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
子组件 beforeCreate
子组件 created
子组件 beforeMount
子组件 mounted
父组件 beforeCreate
父组件 created
父组件 beforeMount
父组件 mounted

当父组件数据发生变化时,父子组件的生命周期钩子会继续执行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
父组件 beforeUpdate
子组件 beforeUpdate
父组件 updated
子组件 updated

2.二叉树数据类型如何处理?

JavaScript 中处理二叉树时,通常会使用类或对象来定义二叉树结构,并实现常见的树操作(如遍历、插入、删除等)。

Vue 中,可以通过组件的递归方式来展示树形结构,并通过 Vue 的响应式机制来实时更新数据或交互操作。

二叉树的常见操作

前序遍历(Pre-order Traversal)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function preOrder(node) {
  if (node === null) return;
  console.log(node.value);  // 处理当前节点
  preOrder(node.left);      // 递归遍历左子树
  preOrder(node.right);     // 递归遍历右子树
}

preOrder(root);  // 输出:1 2 4 5 3

中序遍历(In-order Traversal)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function inOrder(node) {
  if (node === null) return;
  inOrder(node.left);       // 递归遍历左子树
  console.log(node.value);  // 处理当前节点
  inOrder(node.right);      // 递归遍历右子树
}

inOrder(root);  // 输出:4 2 5 1 3

后序遍历(Post-order Traversal)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function postOrder(node) {
  if (node === null) return;
  postOrder(node.left);      // 递归遍历左子树
  postOrder(node.right);     // 递归遍历右子树
  console.log(node.value);   // 处理当前节点
}

postOrder(root);  // 输出:4 5 2 3 1

插入节点 插入节点时,一般遵循二叉树的基本规则:如果节点值小于当前节点,则进入左子树,反之则进入右子树。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function insert(root, value) {
  if (root === null) {
    return new TreeNode(value);  // 插入新节点
  }
  if (value < root.value) {
    root.left = insert(root.left, value);
  } else {
    root.right = insert(root.right, value);
  }
  return root;
}

root = insert(root, 6);  // 在树中插入值 6

vue基本二叉树组件渲染举例 通过递归组件的方式来渲染二叉树节点,每个节点可能会显示它的值,并且包含对左子树和右子树的指针。

例子:使用递归组件渲染二叉树

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div v-if="node">
    <div class="node">
      <span>{{ node.value }}</span>
      <div class="children">
        <TreeNode v-if="node.left" :node="node.left" />
        <TreeNode v-if="node.right" :node="node.right" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TreeNode',
  props: {
    node: Object
  }
}
</script>

<style scoped>
.node {
  margin: 10px;
  padding: 5px;
  border: 1px solid #ccc;
  display: inline-block;
}

.children {
  margin-left: 20px;
}
</style>

在父组件中使用这个递归组件来传递一个二叉树的根节点:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div>
    <TreeNode :node="root" />
  </div>
</template>

<script>
import TreeNode from './TreeNode.vue';

export default {
  components: {
    TreeNode
  },
  data() {
    return {
      // 创建一个简单的二叉树
      root: {
        value: 1,
        left: { value: 2, left: null, right: null },
        right: { value: 3, left: null, right: null }
      }
    };
  }
}
</script>

3. 前端图片上传处理流?

在文件上传过程中,小文件大文件上传有不同的实现思路。为了更好地组织两者的上传流程,可以把它们的上传方式按不同的需求进行划分,确保上传效率和稳定性。

以下是一个详细的对比分析:

小文件上传

思路:

小文件通常指文件大小较小的文件,一般是在几MB以内(通常小于10MB)。上传小文件时,因为文件较小,传输过程中没有大文件所面临的网络超时、内存溢出等问题,所以可以直接使用传统的上传方法。

主要步骤:
  1. 选择文件
    • 通过 <input type="file"> 标签选择文件。
    • 可通过 JavaScript 获取文件对象。
  2. 上传文件
    • 文件通过 FormData 或者 XMLHttpRequest 直接发送给服务器
    • 可以直接使用 fetch APIXMLHttpRequest 进行文件上传。
  3. 服务器接收
    • 服务器接收到文件后,直接存储到服务器文件系统中。
  4. 返回结果
    • 上传完成后,服务器返回上传结果,包括文件存储位置、文件ID等。

大文件上传

思路:

大文件上传通常是指文件大小超过 10MB,甚至几GB的文件。大文件上传时,由于网络不稳定、内存不足、服务器超时等问题,需要考虑切片上传、断点续传等机制。

主要步骤:
  1. 文件切片
    • 将大文件分割成多个小块(切片)。切片大小可以根据网络带宽、文件总大小和内存等因素进行设置(通常在 1MB 到 10MB 之间)。
    • 可以通过 JavaScript 的 Blob.slice() 方法进行切片。
  2. 上传每个切片
    • 将每个切片单独上传到服务器。
    • 可以使用 FormData 携带文件切片以及其他元数据(如文件哈希、切片编号、文件总大小等)上传。
  3. 上传进度显示
    • 前端需要根据每个切片的上传情况,更新文件上传的整体进度条。
  4. 断点续传
    • 如果上传过程中发生中断(如网络异常、浏览器关闭等),可以通过记录每个切片上传的状态来实现断点续传。
  5. 服务器合并切片
    • 服务器在接收到所有切片后,需要合并成一个完整的文件。
  6. 返回结果
    • 上传完成后,服务器返回合并文件后的状态,告知客户端文件上传是否成功。

小文件与大文件上传的对比

特点

小文件上传

大文件上传

文件大小

小于10MB

大于10MB,可能达到GB级别

上传方式

直接上传

切片上传

上传过程

直接通过 FormData 上传

切割文件成多个小块逐个上传

进度显示

一般不需要进度条

需要显示上传进度条

断点续传

不需要(或不常用)

需要支持断点续传

服务器处理

直接保存文件

合并所有切片后保存文件

适用场景

小型文件上传,如图片、文档等

视频、音频、大型数据文件等

对于小文件上传,可以直接将文件通过 FormData 上传给服务器,而大文件上传则需要考虑切片上传、上传进度的显示、断点续传等技术。两者的核心差异在于文件大小及上传的稳定性和效率考虑。

4.骨架屏的原理及实现

什么是骨架屏?

骨架屏(Skeleton Screen)是一种用户体验优化的技术,通常用于提升页面加载的速度感。它通过在内容加载时显示一个简单的占位符(骨架结构),而不是白屏或加载指示器,来让用户知道页面正在加载。它可以减少加载过程中用户的焦虑感,让用户感觉页面正在快速渲染。

骨架屏通过在页面加载时展示简洁的占位符,帮助提升用户的体验,尤其是在网络不稳定或页面加载较慢的情况下。

通常,骨架屏会用灰色、模糊的色块或者简单的图形来表示内容位置和结构。随着内容的逐渐加载,骨架屏会逐步被实际内容替代。

骨架屏的原理

骨架屏的原理在于通过“占位”来模仿页面加载后的结构。在页面的首屏加载时,先展示一个由灰色块、线条等构成的占位界面,给用户一种页面结构已经准备好、正在加载内容的错觉。一旦内容加载完成,再将占位符替换为实际的内容。

骨架屏有助于:

  • 提高页面加载的感知速度;
  • 增加页面的流畅性;
  • 提升用户的体验,尤其在网络较差或加载较慢的情况下。
自动化骨架屏的优势与挑战?
  • 优势:
    • 节省时间:开发者无需手动为每个页面设计骨架屏,Puppeteer 可以自动提取并修改页面结构。
    • 一致性:自动化生成的骨架屏具有统一的样式,确保不同页面的体验一致。
  • 挑战:
    • 复杂页面:对于动态内容丰富的页面,自动化提取骨架屏可能会较为复杂,需要对不同类型的内容进行定制化处理。
    • 性能:运行 Puppeteer 的过程需要消耗一定的资源,生成骨架屏的速度可能不如直接手动设计。

结尾

本次的分享就到这里,如果后续有什么新颖的面试题会持续分享,欢迎投稿!

您好,我是肥晨。 欢迎关注我获取前端学习资源,日常分享技术变革,生存法则;行业内幕,洞察先机。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 农民工前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.vue父子组件的生命周期?
  • 2.二叉树数据类型如何处理?
  • 3. 前端图片上传处理流?
    • 小文件上传
    • 大文件上传
    • 小文件与大文件上传的对比
  • 4.骨架屏的原理及实现
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档