沐游虞笔记
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 必看导言

    • 就业的核心问题

      • 课件
    • 表现力的训练

      • 课件
  • 简历制作

    • 课件
    • 简历准备课堂笔记
    • 个人信息课堂笔记
    • 求职意向课堂笔记
    • 技术栈课堂笔记
    • 教育经历课堂笔记
    • 个人优势与评价课堂笔记
    • 工作经历课堂笔记
    • 项目
    • 项目亮难点问题

    • 项目经历

  • 项目准备

    • 课件
    • 课件
  • 技术重点

    • 划重点

    • 非技术环节
  • 简历投递和面试准备

    • 简历投递
    • 面试准备
  • 笔面试环节知识讲解
  • 项目准备
  • 难点攻关
  • 跨标签页通信
luzhichang
2024-09-18
目录

12-面试讲解

# 跨标签页通信

# 面试讲解

# 知识点图谱

image-20240628173659326

# 难点描述

**模拟问题:**我看你的简历里面写了对于跨标签页的通信,能聊一下这个吗?

问题分析:

跨标签页的通信本身实现并不复杂,特别是如果是通过BroadCastChannel方式的实现。但是像跨页面通信的这种问题,并不像我们之前讲解的微前端,前端监控这种,本身就是一个比较大的概念,所以我们需要多站在宏观的角度去聊问题。而这个问题,需要给面试官展示的是思考解决问题的过程,对知识的掌控,虽然你在了解了BroadCastChannel这个API之后,可能自己会觉得很简单,但是你简单的泛泛而谈,和你引经据典并且包含着具体解决方案的去谈,给人的感觉是不一样的

参考答案:

在我们的项目中,有这样子的需求,在其中一个标签页上做了操作,其他页面需要同步对应的状态。这其实就涉及到浏览器的跨标签页通信了。

(思考过程)其实一开始考虑的方式是通过WebSocket来实现,不过WebSocket需要务器端的支持,而我们需要的仅仅是一个纯前端的支持,所以直接pass掉了。当然就考虑到了LocalStorage,通过事件window.onstorage来监听,只要其他标签页修改了LocalStorage中的内容,window.onstorage就会被触发,而且事件返回的数据也非常全面,我甚至用LocalStorage已经实现了一版,不过这个实现还是有比较明显的短板,我们想要的是实时通信,但是LocalStorage实际最大的作用是共享数据,而且随着我们的操作变多,LocalStorage中存放的内容也越来越多。后面又发现有SharedWorker,不过没有过多的研究,因为看到了兼容性就直接否定了。

**(确定解决方案)**最后发现了有BroadCastChannel API,研究了一下就发现,这个API完全和浏览器标签通信的原理契合的(埋钩子),可以很简单方便的实现跨标签页通信,最后我们技术方案的选择就是BroadCastChannel

不过具体的细节在工程化环境中还是有一些注意的点,特别是在我们现在响应式数据的工程中,像Vue方式处理的响应式数据,不能够直接通过BroadCastChannel管道进行传递,这是由于浏览器页签之间传递克隆数据原因引起的(埋钩子,引起面试官的询问,也可以带出另外的话题点)。

如果退出页面,BroadcastChannel的监听也需要退出,所以,如果是单独封装的类或函数,需要单独处理退出关闭的,一般我们会做闭包处理(埋钩子,很有可能引起另外一个谈论的话题点)。再返回一个函数即可

还有就是如果页面上这样的需求比较多,那么管道的命名需要规范,毕竟在同一个域下面,BroadCastChannel管道的名字是唯一的,我们指定了相关的规范协议,来统一管道的命名

**(处理结果)**通过这样处理之后,不需要复杂的处理,不需要共享数据,也不需要经过后端的中转。我们就可以直接在前端实现跨标签页的通信,而且通信还是实时的。最重要的这个API的兼容性还行,只有IE浏览器不兼容,不过我们的项目这些特殊的需求本身也没有考虑老旧的浏览器,所以用起来都非常舒畅

(主动提问:看面试官还有什么细节需要了解)

# 知识点叙述

1、BroadcastChannel的原理

**模拟问题:**你用到了BroadcastChannel,那你知道实现它的基本原理吗?

问题分析:

这个基本上是我们埋下的钩子,引导面试官来问这个问题,表示我们不仅仅只了解了API的表面,实际掌握了基本的原理。

参考答案:

BroadCastChannel API,他的原理就是一个命名管道,我们的浏览器每个标签页本身就是一个独立的进程,基于管道的通信,本来就是进程之间的通信方式之一。所以这个玩意就是为跨标签页通信存在的。

具体API实现比较的简单,既然原理是命名管道,所以每个 BroadcastChannel 对象都需要使用一个唯一的名称来标识通道。一个页面通过 postMessage 方法将消息发送到频道中,而其他页面则可以监听 message 事件来接收这些消息,所以实现起来不存在难度。

**模拟问题:**你刚才说浏览器每个标签页本身就是一个独立的进程,这是什么意思?

问题分析:

同样考察的是基本常识

参考答案:

每个浏览器标签页通常被视为一个独立的进程,而不是一个线程。这种多进程架构被称之为多进程浏览器,谷歌浏览器就是采用这种方式。

这种架构的方式的主要目的是提高浏览器的稳定性、安全性和性能。

在多进程浏览器中,每个标签页都独立运行在独立的进程中,这样一旦一个标签页崩溃或遇到问题,不会影响其他标签页和浏览器本身的稳定性。而每个进程都有属于自己的内存。

不过进程之间的通信就稍微麻烦了一些,在多进程浏览器中,不同标签页之间的通信是通过进程间通信 IPC 机制来实现的(Inter-Process Communication,指至少两个进程间传送数据或信号的一些技术或方法)

实现通信的方式一般是通过:管道,信号Signal,消息队列,套接字Socket,共享内存等等

而BroadCastChannel API实现的基本原理其实就是命名管道,和进程的通信方式十分的契合

2、BroadcastChannel克隆

**模拟问题:**你刚刚说的细节问题中,提到了克隆的问题,BroadcastChannel通信为什么还和克隆有关系?

问题分析:

这是上面我们回答时候埋下的钩子,如果面试官不问的话,这个也可以一开始自己就说出来。

参考答案:

因为不同标签页之间是通过消息传递数据,传递的消息可以是任意的类型,当然也可以是对象类型,而这对象类型我们不可能直接赋值传递的。因为不同的进程中不可能存放同一个地址的数据。因此肯定是做克隆传递。而响应式数据,比如在Vue3中都是通过Proxy做了代理的,那么在做克隆的时候就会出现问题,不能对Proxy代理的对象进行克隆,知道这个原理之后,解决也很简单,消除Vue3数据的响应式即可,可以直接使用展开运算符,也可以使用vue给我们提供的方法toRaw。

**模拟问题:**你刚刚提到了克隆,你能说说什么是浅克隆,什么是深克隆吗?实现浅克隆,深克隆有哪些方式?

问题分析:

这也是我们埋下的钩子,浅克隆,深克隆,算是一个非常常见的八股问题,但是埋在我们具体的难点亮点的项目中,才更具有意义。

参考答案:

浅克隆创建的新对象,只复制一层深度的属性。对于嵌套对象或数组,浅克隆只复制对象引用,而不是嵌套对象的实际内容。

深克隆创建的新对象,是原始对象的完全独立副本,包括嵌套对象的所有内容。深克隆复制所有嵌套对象和数组的内容,使新对象与原始对象完全分离。修改深克隆后的对象不会影响原始对象,反过来也一样。

在我们一般的操作中,浅克隆一般是:

Object.assign(),展开运算符 (...),Array.prototype.slice(),Array.prototype.concat()

深克隆操作的话,如果是简单对象,可以直接使用JSON.parse(JSON.stringify()),

不在意兼容性的话也可以使用新的 Web API,structuredClone,大多数复杂的结构都支持,只是不支持克隆函数和 DOM 节点

所以一般,我们可以自己实现,当然,也能使用第三方库,比如lodash的实现

const obj = {
  re: /hello/,
  f() {},
  date: new Date(),
  map: new Map(),
  list: [1, 2, 3],
  a: 3,
  b: 4,
};
 
const obj2 = { loop2: obj, name: "obj2" };
obj.loop = obj2;
 
function deepClone(source, cache = new WeakMap()) {
  //原始类型或函数直接返回
  if (typeof source !== "object") {
    return source;
  }
 
  //加入缓存解决循环引用
  if (cache.has(source)) {
    return cache.get(source);
  }
  let res = new source.constructor();
  cache.set(source, res);
 
  //处理JS内置数据结构:Array、Map、Set、Object
  if (source instanceof Array) {
    source.forEach((v) => {
      res.push(deepClone(v, cache));
    });
  } else if (source instanceof Map) {
    for (const [k, v] of source) {
      res.set(k, deepClone(v, cache));
    }
  } else if (source instanceof Set) {
    for (const v of source) {
      res.add(deepClone(v, cache));
    }
  } else if (Object.prototype.toString.call(source) == "[object Object]") {
    for (const key in source) {
      res[key] = deepClone(source[key], cache);
    }
  } else {
    //处理自定义对象(需遵循协议new constructors时为深拷贝)
    res = new source.constructor(source);
  }
 
  return res;
}
 
const newObj = deepClone(obj);
console.log(newObj);
Theme by Vdoing | Copyright © 2021-2024 蜀ICP备2024068710号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式