面试题目
1、vue组件怎么透传
2、vue组件缓存
3、第一次进入缓存组件的生命周期
4、keep-alive生命周期
5、如何缓存多层路由的组件,超过两层会有问题
6、怎么封装组件库 怎么打包到cdn
7、怎么获取组件库组件自带的属性
8、长轮训和短轮询区别
9、websocket
10、微前端应用之间传参
11、session能不能不同域名
12、大文件上传,原理,怎么保证准确
13、文件预览
14、node调小键盘
15、Electron 的主进程和渲染进程
16、如何在 Electron 中进行远程通信?
17、electron应用怎么做更新!!
面试详解
1、vue组件怎么透传
透传 attribute
指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute(属性) 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上
如果一个子组件的根元素已经有了 class 或 style attribute,它会和从父组件上继承的值合并
// 父组件中这样透传
<MyButton class="large" />
<!-- <MyButton> 的模板 -->
<button class="btn">Click Me</button>
// 则最后渲染出的 DOM 结果会变成
<button class="btn large">Click Me</button>
- 这些透传进来的 attribute 可以在模板的表达式中直接用 $attrs 访问到。
- 这个 $attrs 对象包含了除组件所声明的 props 和 emits 之外的所有其他 attribute,例如 class,style,v-on 监听器等等。
- attrs 不提供验证或默认值
- attrs 不是响应性的,不能像props一样跟踪它的变化。
2、vue组件缓存
组件缓存通常指的是在组件切换时保留其状态,避免重新渲染或重新执行某些耗时操作
Vue的<keep-alive>
元素可以缓存不活动的组件实例,避免反复销毁和重建,适用于组件状态需要保留的情况。
3、第一次进入缓存组件的生命周期
1、beforeCreate:在组件实例初始化之后被调用。此时,组件的数据选项尚未被处理
2、created:在组件实例创建完成后被调用。这时,组件的实例已完全创建好,但是组件尚未挂载到DOM上
3、beforeMount:在挂载开始之前被调用。此时,相关的DOM还未创建。
4、mounted:在组件被挂载到DOM后立即被调用
5、activated:当组件被 <keep-alive>
缓存并首次激活时调用。这类似于 mounted,但仅用于被 <keep-alive>
包裹的组件。
6、deactivated: 当组件被 <keep-alive>
缓存并首次停用时调用。这通常发生在组件被 <keep-alive>
包裹且从页面上移除时。
当组件被 <keep-alive>
包裹时,直接的组件切换不会触发 destroyed 钩子,因为组件实例实际上并没有被销毁,而是被缓存起来了。只有当组件实例最终被 <keep-alive>
排除缓存时,destroyed 钩子才会被调用。
此外,如果组件在 <keep-alive>
中被重新激活,它将不会再次经过 created 和 mounted 钩子,而是会调用 activated 钩子。如果组件被 <keep-alive>
停用,将调用 deactivated 钩子。
4、keep-alive生命周期
1、activated:当使用 <keep-alive>
包裹的组件第一次被激活,或者从停用状态变为激活状态时调用
2、deactivated:当使用 <keep-alive>
包裹的组件从激活状态变为停用状态时调用。这通常发生在组件被 <keep-alive>
包裹且从页面上移除时
5、如何缓存多层路由的组件,超过两层会有什么问题
1、使用<keep-alive>
包裹路由出口
<template>
<keep-alive>
<router-view />
</keep-alive>
</template>
2、使用<keep-alive>
的include和exclude属性: 可以使用include属性来指定需要缓存的组件名,或者使用exclude属性来排除不需要缓存的组件。
<keep-alive include="ChildA,ChildB">
<!-- 只有ChildA和ChildB会被缓存 -->
<router-view />
</keep-alive>
超过两层的嵌套路由可能会遇到的问题:
- 内存使用: 缓存多层嵌套组件可能会导致内存使用增加,特别是当这些组件包含大量状态或数据时。
- 组件状态管理: 多层嵌套组件可能会使组件状态管理变得更加复杂,特别是当组件间存在状态共享或依赖时。
- 数据同步问题: 如果缓存的组件内部数据依赖于外部数据,可能需要额外的逻辑来确保数据在路由切换时保持同步。
- 组件更新问题: 当父组件重新渲染时,被
<keep-alive>
缓存的子组件可能不会重新渲染,这可能会导致显示过时的数据。 - 导航逻辑复杂性: 多层嵌套的组件可能会使导航守卫和路由配置变得更加复杂。
- 性能考虑: 虽然
<keep-alive>
可以提高性能,但如果不正确使用,也可能导致性能问题,比如不必要的内存占用。 - 组件激活和停用: 使用
<keep-alive>
时,需要正确处理组件的activated和deactivated生命周期钩子,以确保组件在激活和停用时执行正确的逻辑。
6、怎么封装组件库 怎么打包到cdn
在package.json
中填一些基本信息 在命令行里登录npm账号,
package.json
中author尽量与npm账户一致
npm adduser
Username: your name
Password: your password
Email: yourmail
配置成功之后提交代码
npm publish
如果提示包不能为private,需要执行下面的发布方式:
npm publish --access public
7、websocket
WebSocket是一种网络通信协议,它提供了一个全双工通信渠道,通过一个单一的长期连接允许服务器主动向客户端发送消息。WebSocket 用于实现实时通信。
特点:
- 全双工通信:WebSocket连接允许服务器和客户端之间双向交互,与HTTP请求-响应模式不同。
- 持久连接:一旦建立WebSocket连接,它会保持开放,直到客户端或服务器端明确关闭连接。
- 实时性能:WebSocket用于需要快速实时通信的应用,如在线游戏、聊天应用、实时数据传输等。
- 较少的开销:与HTTP相比,WebSocket通信不需要每次请求都携带HTTP头部,因此开销较小。
- 基于文本或二进制:WebSocket允许传输文本数据(JSON格式常见)和二进制数据。
- 安全性:WebSocket连接可以通过wss://(WebSocket Secure)使用TLS/SSL加密,确保数据传输安全。
// 创建一个新的WebSocket对象
const socket = new WebSocket('ws://example.com/socketserver');
// 监听连接打开事件
socket.addEventListener('open', function (event) {
// 向服务器发送消息
socket.send('Hello Server!');
});
// 监听消息事件
socket.addEventListener('message', function (event) {
// 接收服务器发送的消息
console.log('Message from server:', event.data);
});
// 监听错误事件
socket.addEventListener('error', function (event) {
console.error('WebSocket error:', event);
});
// 监听连接关闭事件
socket.addEventListener('close', function (event) {
console.log('WebSocket connection closed:', event.code, event.reason);
});
// 在适当的时候关闭连接
// socket.close();
8、WebSocket协议使用哪个端口
通常WebSocket使用端口80,而加密的WebSocket(wss://)使用端口443。
9、 长轮训和短轮询区别
短轮询(Short Polling):
- 频繁请求:客户端以固定的时间间隔(如每秒钟)向服务器发送请求,无论服务器是否有更新。
- 响应速度:如果服务器没有新数据,它会立即响应一个空的结果,客户端接收到空结果后再发起新的请求。
- 服务器负载:由于请求频繁,即使没有数据更新,也可能导致服务器负载较高。
- 实时性:实时性较差,因为数据更新有固定的延迟(等于轮询间隔)。
- 示例场景:适合数据更新不频繁且实时性要求不高的场景。
长轮询(Long Polling)
- 等待响应:客户端发送请求到服务器后,服务器会保持请求打开,直到有数据更新或超时。
- 减少请求次数:只有当数据更新或连接超时时,服务器才响应请求,然后客户端立即发送新的请求。
- 服务器负载:相比短轮询,长轮询减少了请求次数,降低了服务器的负载。
- 实时性:实时性较好,因为数据更新时客户端能够立即接收到响应。
- 示例场景:适合数据更新频繁且需要较好实时性的场景。
10、微前端应用之间怎么传参
微前端:将大型的前端应用程序分解为更小、更易于管理的独立前端应用程序。可以独立开发、测试、部署和维护。
常见的通信方式包括事件总线、全局状态管理、Web Components等。
- 全局事件总线 Event Bus
- 共享状态管理:使用共享的状态管理库(如Redux或Vuex),在多个应用之间共享状态。
- 将数据存储在Cookie或LocalStorage中,不同的应用可以访问这些存储的数据。
- 通过URL传递参数,其他应用可以通过解析URL来获取参数
- 通过iframe嵌入,可以使用window.postMessageAPI在父页面和iframe之间安全地传递消息。
11、session能不能不同域名
Session本身是与特定域名和路径关联的,由设置Session的Cookie的域(Domain)和路径(Path)属性决定。默认情况下,Session Cookie只在创建它的域名和路径下有效。
如果需要在相同的主域下的不同子域之间共享Session,可以在Cookie的Domain属性中设置主域,这样所有子域都可以访问Session。
12、大文件上传原理
原理:
- 客户端分片:大文件在客户端被分割成多个小块(片),每一片单独上传。
- 并行上传:利用多线程或JavaScript的XMLHttpRequest/fetch API并行上传这些分片,提高上传效率。
- 服务器端接收:服务器端接收这些分片,并按照正确的顺序重新组装它们。
- 分片校验:每个分片可以包含校验信息(如MD5哈希),以确保上传过程中的数据完整性。
- 断点续传:如果上传过程中断,客户端可以从中断的地方重新开始上传,而不是重新上传整个文件。
- 上传完成:所有分片上传完毕后,服务器端发送响应,告知客户端上传状态。
13、怎么保证准确
为整个文件上传过程生成一个唯一标识符,用于识别和管理分片,对每个分片生成校验码(如MD5),在上传完成后进行服务器端验证,
14、node调起虚拟键盘
使用新的进程来运行命令
- exec() 和 .execSync():用于创建与父进程的I/O保持连接的子进程,通常用于执行shell命令。
const { exec } = require('child_process');
// Windows系统下显示虚拟键盘
exec('osk');
15、Electron 的主进程和渲染进程
主进程 (Main Process)
- 单个实例:Electron 应用通常只有一个主进程实例,运行在 main.js 文件中。
- 应用生命周期管理:主进程负责管理应用的生命周期,包括初始化、运行和退出。
- 创建窗口:主进程负责创建和控制浏览器窗口(BrowserWindow)。
- 原生Node.js模块:主进程可以访问所有原生Node.js模块,用于执行文件系统操作、网络请求等。
- IPC通信:主进程可以通过进程间通信(IPC)与渲染进程或其他主进程实例通信。
- 安全性:主进程中运行的代码具有访问系统资源的能力,因此安全性非常重要,要避免执行不受信任的代码。
渲染进程 (Renderer Process)
- 多个实例:每个浏览器窗口或网页视图(标签)都有自己的渲染进程。
- Chromium 内核:渲染进程使用 Chromium 内核来渲染HTML、CSS和JavaScript,就像普通的网页浏览器一样。
- 隔离环境:每个渲染进程都是隔离的,有自己的V8引擎实例和全局作用域。
- 访问限制:出于安全考虑,渲染进程不能直接访问Node.js的核心模块。它们通常用于执行客户端脚本和用户界面逻辑。
- IPC通信:渲染进程可以通过IPC与主进程通信,请求执行一些需要Node.js能力的后台任务。
- Web技术:渲染进程中的代码可以使用所有标准的Web技术,包括HTML5、CSS3和JavaScript。
16、如何在 Electron 中进行远程通信?
通过预加载脚本将主进程和渲染进程连接起来进行通信
单向通信:
- 在预加载文件里暴露方法,使用ipcRenderer.send向主进程发送消息,在渲染进程中调用这个方法
- 在主进程中用 ipcMain.on接收消息,进行操作
双向通信:
- 在预加载文件里暴露方法,使用ipcRenderer.invoke向主进程发送消息,在渲染进程中调用这个方法
// preload脚本暴露方法
const { contextBridge, ipcRenderer } = require('electron/renderer')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title),
postMessage: () => ipcRenderer.invoke('post-message')
})
// 渲染进程调用方法
ipcMain.handle('post-message', async ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('支付宝到账100万元');
}, 2000);
});
})
- 在主进程中用 ipcMain.handle接收消息,进行操作
// 主进程中监听方法
ipcMain.handle('post-message', async ()=>{
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('支付宝到账100万元');
}, 2000);
});
})
区别:
- ipcRenderer.send: 发送消息后不返回任何值,它是单向的,发送消息到主进程后不会等待主进程的响应。
- ipcRenderer.invoke: 发送消息后会返回一个 Promise,该 Promise 在主进程处理完成后被解析,可以获取到主进程返回的结果。
- 对于 ipcRenderer.send,主进程通过 ipcMain.on 来监听并处理消息。
- 对于 ipcRenderer.invoke,主进程通过 ipcMain.handle 来注册处理程序,处理程序返回的 Promise 在处理完成后被解析,将结果返回给渲染进程。
还有一种方法:使用 WebContents 的 postMessage 和 on 事件
- 在主进程中使用 webContents 发送消息:主进程可以通过 webContents 的 postMessage 方法向渲染进程发送消息。
// 主进程 (main.js)
const { webContents } = require('electron');
const contents = webContents.fromId(id); // 替换 id 为你的渲染进程的 ID
contents.postMessage('message-from-main', '*');
2. 在渲染进程中监听消息:渲染进程可以使用 window 的 on 事件监听器来监听主进程的消息。
// 渲染进程 (renderer.js 或 index.html 中的 <script> 标签)
window.on('message', (event, message) => {
console.log('收到来自主进程的消息:', message);
});
17、electron应用怎么做更新!!
Electron 内置了 autoUpdater 模块,它利用 GitHub Releases 或自建服务器的方式获取新版本信息并进行更新。当检测到新版本时,它能自动下载并安装新的更新包,从而实现了无缝、便捷的更新体验。
使用 electron-builder 等打包工具生成新的安装包或更新包,将其上传至 GitHub Releases 或其他指定服务器。