- watchEffect的依赖触发时机,如果写入if分支会怎么样?
- vite的lazyBundle?
- hooks式开发导入导出,允许异步导入吗?可以放入if分支吗?放入异步操作会怎么样?onMounted之类的怎么执行?
- 寻找最快的请求,且保证并发量不超过10
- axios、fetch怎么取消请求
- 频繁触发分页,如何保证获取到正确的请求数据?
- commonjs和esModule的区别
- esModule的具名导入导出和解构赋值的区别
- vite运行的js静态资源类型有哪些?
- 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
- 当
enableWatch.value为true时,watchEffect被注册并开始追踪count。 - 即使后续
enableWatch.value被设置为false,已经注册的watchEffect不会被销毁或停止追踪。 - 因此,
count.value++的变化仍然会触发watchEffect。 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及生命周期等等,给我们的编码方式提供了高聚合、高复用的便利。
- composable函数中,如果用到了生命周期,watch,comouted等操作时,与组件内的相应函数,按照书写顺序执行。
- 支持异步动态导入,不过要做好异步处理。
寻找最快的请求,且保证并发量不超过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(); // 取消请求
频繁触发分页,如何保证获取到正确的请求数据?
- 定义一个全局计数器,给每个请求打上tag标识,并在请求完成后检查该标识符是否匹配当前最新的分页状态。如果不匹配,则忽略旧的响应。
- 取消不需要的请求。
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的区别
| 特性 | CommonJS | ES Module |
|---|---|---|
| 加载方式 | 动态、同步 | 静态、异步 |
| 值类型 | 导出值的拷贝 | 导出值的引用 |
| 语法 | require/module.exports | import/export |
| 循环依赖处理 | 可能不完整 | 通过引用解决 |
| 使用场景 | Node.js 传统项目 | 现代浏览器、Node.js v12+ |
esModule的具名导入导出和解构赋值的区别
| 特性 | 具名导入导出 | 解构赋值 |
|---|---|---|
| 作用范围 | 模块系统 | 非模块化的普通对象或数组 |
| 是否动态 | 静态分析,需在编译时确定 | 动态,可在运行时执行 |
| 绑定关系 | 动态绑定(引用) | 值的拷贝 |
| 语法位置 | 模块顶层 | 可以出现在任何地方 |
| 优化支持 | 支持 Tree Shaking | 不支持 |
| 扩展功能 | 支持默认导出和命名导出 | 支持默认值和重命名 |
vite运行的js静态资源类型有哪些?
| 类型 | 扩展名/语法 | 说明 |
|---|---|---|
| 标准 JS | .js, .mjs, .cjs | ESM 或 CommonJS(需插件) |
| TypeScript | .ts, .tsx | 原生编译支持 |
| JSX | .jsx, .tsx | 需框架插件(如 React) |
| 动态导入 | import() | 代码分割优化 |
| Web Workers | ?worker | 专用线程处理 |
| 原始文本/URL | ?raw, ?url | 获取字符串或资源路径 |
| Node.js 模块 | 需 @vitejs/plugin-commonjs | CommonJS 转 ESM |
template里面调用console.log会怎么样?
会被vue解析为字符串直接渲染