刷刷题8

70 阅读5分钟

ResizeObserver 作用是什么

ResizeObserver 的作用是监测元素的尺寸变化。这是一种强大的 Web API,允许开发者在元素的尺寸发生改变时(无论是因为元素内容的变化、窗口大小的调整还是其他原因导致的尺寸改变),执行一些操作或布局更新。在过去,开发者通常需要依赖定时器或者窗口的 resize 事件来间接监测元素尺寸的变化,这种方法不仅不够精确,而且效率低下。ResizeObserver 提供了一种更为直接和高效的方式来响应尺寸变化。

如何使用 ResizeObserver

使用 ResizeObserver 很简单,你只需要创建一个 ResizeObserver 实例,并为它提供一个回调函数。在回调函数中,你可以基于元素尺寸的变化来执行相应的操作。然后,使用 observe 方法来指定需要被观察尺寸变化的元素。

示例代码

下面的示例代码展示了如何使用 ResizeObserver 来监测一个元素的尺寸变化,并在尺寸变化时输出新的尺寸信息:

// 监测的目标元素
const targetElement = document.querySelector(".resizable");

// 创建 ResizeObserver 实例
const resizeObserver = new ResizeObserver((entries) => {
  for (let entry of entries) {
    // entry.target 是被观察的元素
    // entry.contentRect 包含了元素的尺寸信息
    console.log("Element size changed:", entry.target);
    console.log(`New width: ${entry.contentRect.width}`);
    console.log(`New height: ${entry.contentRect.height}`);
  }
});

// 开始观察目标元素
resizeObserver.observe(targetElement);

应用场景

ResizeObserver 的常见应用场景包括:

  • 响应式布局:当容器的尺寸改变时,动态调整内容或布局,提供更好的响应式设计。

  • 图表和可视化:在图表或数据可视化的容器大小改变时,重新绘制图表来适应新的尺寸。

  • 动态元素(如弹出窗口和下拉菜单) :监测并根据内容大小自动调整元素的尺寸。

统计全站每一个静态资源加载耗时, 该如何做

要统计全站每一个静态资源(如图片、JS 脚本、CSS 样式表等)的加载耗时,你可以借助浏览器的 Performance API,特别是利用 PerformanceResourceTiming 接口来获取资源加载的详细时间信息。以下是一个基本的步骤指导和示例代码,展示如何实现这一功能:

步骤

  1. 使用 PerformanceObserver 创建一个 PerformanceObserver 实例来监听资源加载事件,能够实时收集性能数据,而且对性能影响较小。
  2. 过滤静态资源类型: 通过检查 initiatorType 属性,筛选出静态资源(例如 imgscriptcss 等)的加载事件。
  3. 计算和展示耗时: 对每个静态资源的加载耗时进行计算并展示。资源的耗时可以通过 duration 属性直接获取。

示例代码

以下是一个简单的 JavaScript 代码示例,展示了如何使用 PerformanceObserver 来统计全站静态资源的加载耗时:

// 创建性能观察者实例来监听资源加载事件
const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  for (const entry of entries) {
    // 过滤静态资源类型
    if (["img", "script", "css", "link"].includes(entry.initiatorType)) {
      console.log(`资源 ${entry.name} 类型 ${entry.initiatorType} 耗时:${entry.duration.toFixed(2)} 毫秒`);
    }
  }
});

// 开始观察 Resource Timing 类型的性能条目
observer.observe({ entryTypes: ["resource"] });

注意事项

  • 性能数据的准确性: 确保性能数据的准确性和实时性,你应该在页面加载的早期就开始监听资源加载事件,例如在 <head> 标签中就引入或嵌入这段脚本。

  • 跨域资源的时间信息: 如果你需要获取跨域资源的详细时间信息(如第三方字体或脚本),那么这些资源的服务器需要在响应头中包含 Timing-Allow-Origin 头。

  • 大量数据的处理: 如果页面包含大量静态资源,考虑如何存储、传输和分析这些数据,避免对性能和用户体验造成影响。

websocket 断联之后如何重连,且保证断联期间数据不丢失

1. 监听连接状态

首先,你需要监听 WebSocket 连接的各种事件,以便知道何时发生了断连,并根据这些事件来触发重连逻辑。

  • onclose: 当 WebSocket 连接关闭时,触发重连逻辑。
  • onerror: 出现错误时,也可视为一个触发重连的信号。
  • onopen: 连接成功时,清除重试计数器和缓存的数据(如果之前成功发送了)。

2. 实现重连逻辑

  • 使用指数退避算法来延迟重连尝试,避免短时间内频繁重连。

    • 例如,第一次重连延迟 1 秒,第二次 2 秒,然后 4 秒,最大延迟设置为 1 分钟。
  • 在每次重连时,重置 WebSocket 对象并重新发起连接。

3. 缓存数据

  • 发送数据前检查连接状态:如果 WebSocket 处于非开放状态,将数据缓存起来,待连接恢复后再发送。
  • 使用队列存储待发送数据:便于按顺序发送,保证数据的完整性和顺序。

4. 发送缓存数据

  • 在连接成功的回调(onopen事件)中,检查是否有缓存的数据,如果有,则遍历队列发送。

如何做静态资源预加载

预加载是指在用户需要数据或资源之前,提前加载这些数据或资源的过程。

预加载的优点

  • 提升加载速度:通过提前加载资源,用户在访问页面时可以更快地看到完整内容。
  • 提高用户体验:减少页面加载时的延迟,使用户感到更流畅。
  • 优化资源使用:合理安排资源加载顺序,提高网络利用率。

WebWorker 实现预加载

下面的示例将展示如何使用 Web Worker 来预加载静态资源。我们将创建一个简单的 Web Worker 脚本,用于在后台预加载一些指定的静态资源(例如图片、CSS、JavaScript 文件等)。这个过程不会阻塞主线程,使得主线程可以继续处理其他任务,如用户交互,从而提升页面的响应性能。

步骤 1:创建 Web Worker 脚本

首先,创建一个 JS 文件作为 Web Worker 的脚本。我们把这个文件命名为 preloadWorker.js

// preloadWorker.js

self.addEventListener("message", (e) => {
  const urls = e.data;
  urls.forEach((url) => {
    fetch(url)
      .then((response) => {
        // 一个简单的操作,标识资源已被预加载
        if (response.status === 200) {
          postMessage(`Resource preloaded: ${url}`);
        } else {
          postMessage(`Resource failed: ${url}`);
        }
      })
      .catch((error) => {
        postMessage(`Resource fetch error: ${url}`);
      });
  });
});

步骤 2:在主线程中使用 Web Worker

接下来,在 HTML 页面中使用这个 Web Worker。

首先,确保在你的 HTML 中引入一个脚本,初始化并使用这个 Web Worker。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Web Worker Preload Demo</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

步骤3:程脚本 main.js 用于启动和与 Web Worker 交互。
// main.js

if (window.Worker) {
  const worker = new Worker("preloadWorker.js");

  const resources = [
    "image.png", // 示例资源,确保替换为实际的 URL
    "style.css",
    "script.js",
  ];

  worker.postMessage(resources);

  worker.onmessage = (e) => {
    console.log(e.data);
  };
} else {
  console.log("Your browser doesn't support web workers.");
}

这段脚本首先检查浏览器是否支持 Web Worker。如果支持,它会创建一个指向 preloadWorker.js 的新 Worker 实例,然后将要预加载的资源列表发送给这个 Worker。最后,它设置一个事件监听器来接收并处理 Worker 发出的消息。

如何处理异步加载组件

使用 defineAsyncComponent 方法

Vue 3 提供了 defineAsyncComponent 方法,使得定义和使用异步组件变得简单。你可以通过传递一个函数,该函数返回一个 import() 调用(返回 Promise),来动态加载组件。

javascript
 代码解读
复制代码
import { defineAsyncComponent } from "vue";

const AsyncComponent = defineAsyncComponent(() => import("./components/AsyncComponent.vue"));

// 在组件中使用
export default {
  components: {
    AsyncComponent,
  },
};
加载状态处理

你还可以使用 defineAsyncComponent 的高级用法,提供一个对象来处理加载状态,如显示加载中的提示、错误处理和超时处理。

const AsyncComponent = defineAsyncComponent({
  // 加载异步组件的工厂函数
  loader: () => import("./components/AsyncComponent.vue"),
  // 加载中时要使用的组件
  loadingComponent: LoadingComponent,
  // 加载失败时要使用的组件
  errorComponent: ErrorComponent,
  // 在显示 loadingComponent 之前的延迟 | 默认值:200(毫秒)
  delay: 200,
  // 如果提供了超时时间(毫秒),超时后将显示错误组件 | 默认值:Infinity
  timeout: 3000,
});

Vue 2 中处理异步组件的方法

在 Vue 2 中,异步组件的定义略有不同,你可以直接在组件注册时提供一个返回 Promise 的工厂函数。

javascript
 代码解读
复制代码
Vue.component("async-component", () => import("./components/AsyncComponent.vue"));

或者为了处理加载状态,可以提供一个高级的对象形式:

Vue.component("async-component", (resolve, reject) => ({
  // 需要加载的组件 (应该是一个 Promise)
  component: import("./components/AsyncComponent.vue"),
  // 异步组件加载时使用的组件
  loading: LoadingComponent,
  // 加载失败时使用的组件
  error: ErrorComponent,
  // 展示加载中组件前的等待时间。默认:200ms。
  delay: 200,
  // 如果提供了超时时间 (毫秒),超时后会显示错误组件。默认:Infinity
  timeout: 3000,
}));