记:京东一面

90 阅读5分钟
  1. watchEffect的依赖触发时机,如果写入if分支会怎么样?
  2. vite的lazyBundle?
  3. hooks式开发导入导出,允许异步导入吗?可以放入if分支吗?放入异步操作会怎么样?onMounted之类的怎么执行?
  4. 寻找最快的请求,且保证并发量不超过10
  5. axios、fetch怎么取消请求
  6. 频繁触发分页,如何保证获取到正确的请求数据?
  7. commonjs和esModule的区别
  8. esModule的具名导入导出和解构赋值的区别
  9. vite运行的js静态资源类型有哪些?
  10. template里面调用console.log会怎么样?

watchEffect的依赖触发时机,如果写入if分支会怎么样?

watchEffect的依赖收集时机为ref、reacicve等响应式函数的监听触发进行收集
触发时机:立即执行一次、依赖值的变化时
此处引入watch、watchEffect的区别

情况一:将整个watchEffect写入if分支中

import { ref, watchEffect } from 'vue';

const count = ref(0);
const enableWatch = ref(true);
let stopWatchEffect = null;

if (enableWatch.value) {
  stopWatchEffect = watchEffect(() => {
    console.log('Count changed:', count.value);
  });
}

// 修改 enableWatch 的值
enableWatch.value = false; // 没有影响,因为 watchEffect 已经注册
if (stopWatchEffect) {
  stopWatchEffect(); // 停止 watchEffect
}

// 修改 count 的值
count.value++; // 输出: Count changed: 1
  1. 当 enableWatch.value 为 true 时,watchEffect 被注册并开始追踪 count
  2. 即使后续 enableWatch.value 被设置为 false,已经注册的 watchEffect 不会被销毁或停止追踪。
  3. 因此,count.value++ 的变化仍然会触发 watchEffect
  4. watchEffect 的返回值是一个 stop 函数,调用它可以停止监听。

情况二:在watchEffect中写入if分支判断监听
此时可以手动触发依赖的是否监听

import { ref, watchEffect } from 'vue';

const count = ref(0);
const flag = ref(true);

watchEffect(() => {
  if (flag.value) {
    console.log('Count inside if block:', count.value);
  } else {
    console.log('Flag is false, not accessing count');
  }
});

// 修改 flag 的值
flag.value = false; // 输出: Flag is false, not accessing count

// 修改 count 的值
count.value++; // 没有输出,因为此时 if 分支未被触发,count 不被追踪

vite的lazyBundle?

很陌生的一个概念,见名知意猜测是说的依赖预构建的冷启动,惰性编译? 参考链接:zhuanlan.zhihu.com/p/646275784 vitejs.cn/vite3-cn/gu…

vite是基于入口文件动态加载依赖的文件,再进行编译的,并将编译结果缓存到node_modules下的.vite目录下,也就是说第一次启动时并没有缓存可用,因此会慢一些,之后的每次启动都是做增量启动,并将新的编译结果加入到.vite下。 vite团队提出了依赖预构建的概念,并推进了一个非阻塞依赖预构建的特性。

vite的冷启动只需等待依赖解析的过程,而无需等待依赖构建的过程,依赖构建在后台运行,再影响项目启动。

composable(hooks)式开发导入导出,允许异步导入吗?可以放入if分支吗?放入异步操作会怎么样?onMounted之类的生命周期怎么执行?

vue3提出了compositionApi相关api,具名导出各种响应式api及生命周期等等,给我们的编码方式提供了高聚合、高复用的便利。

  1. composable函数中,如果用到了生命周期,watch,comouted等操作时,与组件内的相应函数,按照书写顺序执行。
  2. 支持异步动态导入,不过要做好异步处理。

寻找最快的请求,且保证并发量不超过10

axios、fetch怎么取消请求

借助AbortController实现

axios

import axios from 'axios';

// 创建一个 AbortController 实例
const controller = new AbortController();

// 发起请求
axios.get('https://api.example.com/data', {
  signal: controller.signal, // 将信号传递给请求
})
  .then(response => {
    console.log('Response:', response.data);
  })
  .catch(error => {
    if (axios.isCancel(error)) {
      console.log('Request canceled:', error.message);
    } else {
      console.error('Error:', error);
    }
  });

// 取消请求
controller.abort('Request manually aborted');

fetch

// 创建一个 AbortController 实例
const controller = new AbortController();
const signal = controller.signal;

// 发起请求
fetch('https://api.example.com/data', { signal })
  .then(response => {
    if (!response.ok) throw new Error('Network response was not ok');
    return response.json();
  })
  .then(data => {
    console.log('Response:', data);
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Fetch request aborted');
    } else {
      console.error('Error:', error);
    }
  });

// 取消请求
controller.abort(); // 取消请求

频繁触发分页,如何保证获取到正确的请求数据?

  1. 定义一个全局计数器,给每个请求打上tag标识,并在请求完成后检查该标识符是否匹配当前最新的分页状态。如果不匹配,则忽略旧的响应。
  2. 取消不需要的请求。
import axios from 'axios';

export function usePagination() {
  const currentPage = ref(1);
  const data = ref([]);
  let controller = null; // 保存 AbortController 实例

  const fetchData = async (page) => {
    // 取消之前的请求
    if (controller) {
      controller.abort('New request triggered');
    }

    controller = new AbortController();
    currentPage.value = page;

    try {
      const response = await axios.get(`https://api.example.com/data?page=${page}`, {
        signal: controller.signal,
      });
      data.value = response.data;
    } catch (error) {
      if (axios.isCancel(error)) {
        console.log('Request canceled:', error.message);
      } else {
        console.error('Error fetching data:', error);
      }
    }
  };

  return { data, currentPage, fetchData };
}

commonjs和esModule的区别

特性CommonJSES Module
加载方式动态、同步静态、异步
值类型导出值的拷贝导出值的引用
语法require/module.exportsimport/export
循环依赖处理可能不完整通过引用解决
使用场景Node.js 传统项目现代浏览器、Node.js v12+

esModule的具名导入导出和解构赋值的区别

特性具名导入导出解构赋值
作用范围模块系统非模块化的普通对象或数组
是否动态静态分析,需在编译时确定动态,可在运行时执行
绑定关系动态绑定(引用)值的拷贝
语法位置模块顶层可以出现在任何地方
优化支持支持 Tree Shaking不支持
扩展功能支持默认导出和命名导出支持默认值和重命名

vite运行的js静态资源类型有哪些?

类型扩展名/语法说明
标准 JS.js.mjs.cjsESM 或 CommonJS(需插件)
TypeScript.ts.tsx原生编译支持
JSX.jsx.tsx需框架插件(如 React)
动态导入import()代码分割优化
Web Workers?worker专用线程处理
原始文本/URL?raw?url获取字符串或资源路径
Node.js 模块需 @vitejs/plugin-commonjsCommonJS 转 ESM

template里面调用console.log会怎么样?

会被vue解析为字符串直接渲染