大文件上传方案
- 计算文件hash
- 前端把文件hash传给后端,后端返回该文件是否存在,如果存在,直接秒传,不存在就进入分片上传流程
- 前端按固定大小切分文件,然后带上文件hash和分片序号上传,同时需要控制并发数
- 每次上传前,前端要查询已上传的分片,然后只上传剩余的分片
- 上传完成后,前端通知后端合并,后端按照分片序号拼接,返回文件地址
vite和webpack的区别
Vite 和 Webpack 最核心的区别:
- 启动和热更新速度不一样
- Webpack 是全量打包,启动时要把所有依赖打包成 bundle,热更新也要重新打包相关模块,项目越大越慢。
- Vite 在开发环境利用浏览器原生 ES Modules,按需加载,不打包,所以启动非常快,热更新只更新修改的模块,也很块。
- 底层构建工具不一样
- Webpack 自己一套完整打包流程。
- Vite 开发时不打包,生产用 Rollup 打包。
- 定位不同
- Webpack 生态成熟、配置复杂、适合大型复杂项目。
- Vite 开箱即用、配置简单、现代框架(Vue/React)首选。
Vite 快在开发体验,Webpack 强在生态和兼容性。
性能优化
- 网络上静态资源上CDN,使用缓存,合并请求
- 加载上做图片懒加载、组件和路由懒加载;
- 渲染上减少回流重绘,动画用 transform;
- 运行时对高频事件防抖节流,长列表用虚拟列表;
vue2和vue3响应式区别
1.vue2是通过数据劫持+发布订阅者模式去实现响应式的,是对data中的每个属性进行了递归遍历,把每个属性转换为setter和getter,不被使用的也会被转换。而vue3使用Proxy 直接拦截整个对象的操作。它采用了懒代理(Lazy Observation) 机制,只有当代码真正访问到嵌套对象时,这样渲染速度更快,内存占用更低。
ref reactive toRef的区别
ref:支持基本类型和对象,JS 中需通过.value访问。reactive:对象专用。仅支持对象/数组,直接访问属性toRef:将reactive对象的单个属性转换为ref,
原型和原型链
每个函数都有prototype属性,这个prototype就是原型对象,每个对象都有__proto__属性,它指向的是创建它的构造函数的原型对象,而这个原型对象的__proto__属性指向的是它自己的原型对象,当查找对象中的某个属性或者方法时,如果查找不到就沿着__proto__向上查找,直到找到或者为null为止
vue组件通信方式
- 父子组件通信: emit children v-model.sync 插槽
- 隔代通信: provide inject
- 任意组件:vuex pina
- 属性透传:$attrs
vue3和vue2的区别
- vue2都是选项式API,vue3都是组合式API,逻辑更加聚合
- vue2只支持单根节点,vue3可以是多个根节点
- vue3的setup替代了vue2的beforeCreated和created生命周期,其余周期需要在前面加on
- vue2相比vue3引入了静态提升和patchFlag,渲染速度更快
- vue2通过defineProperty实现的, 像对象增加属性、通过下标修改数组长度都是无法监听到的,而vue3通过proxy监听整个对象,弥补了这些缺陷
为什么要有key
key是列表中元素的唯一标识,Vue通过key来判断元素是否被修改、新增或删除。更新列表时,有key就能精准找到变化的元素,只更新它,不用重新渲染整个列表,这样性能更好。实际开发中建议用数据的唯一id做key,别用index,因为index会随列表排序、增删变化,可能导致key失效。
为什么会有nextTick
vue的的数据更新是异步的,数据更新之后不会立即更新DOM,而函数放在nextTick中执行,能确保在DOM更新之后执行函数
watch和watcheffect的区别
- watch需要手动指定依赖,依赖改变才执行
- watcheffect自动收集依赖,初始化的时候就会执行一次
事件循环
js是单线程的,为了避免任务阻塞,所以就有了事件循环机制。 js任务的执行顺序为:
- 先执行完所有的同步任务
- 再清空微任务,执行宏任务队列里第一个宏任务
- 再清空微任务
- 这样循环下去,直到执行结束
闭包
一个函数能够访问另一个函数内部变量的时候就会形成闭包 闭包的优点是可以私有化变量,避免全局污染 缺点:当外部函数执行完毕之后,内层函数仍保留着对外层函数作用域的引用,从而能继续访问外部变量,变量没有被回收,所以会占用内存导致内存泄漏。 解决办法:执行完闭包后,将外部函数赋值为Null
promise
promise是一种异步编程解决方案,用.then的链式调用解决了多层异步操作时的回调地狱问题 promise有三种状态:pending,resolved,rejected,,状态一旦发生改变就不会再变,状态的改变是通过resolve()和reject()方法来实现的。
async/await是promise的语法糖,写法更加简洁,逻辑更加清晰,易于调试,
数据类型
基本数据类型
undefined、null、string、boolean、number
复杂数据类型
对象、数组、函数
- typeof判断数组|对象|null结果都是object.判断其余基本数据类型和function都能正确判断
- instanceof能够正确判断引用数据类型。instanceof的运行机制是在数据的原型链中能否找到该类型的原型。
箭头函数和普通函数的区别
- 箭头函数写法更简洁
- 箭头函数没有自己的this,通过上下文确定自己的this
- 箭头函数没有自己的原型
- 箭头函数不能作为构造函数使用
- 函数体内没有arguments对象
改变this指向的方法
- 函数名.call(thisArg, arg1, arg2, ...)
- 函数名.apply(thisArg, [arg1, arg2, ...])
- 原函数.bind(thisArg, arg1, arg2, ...)
let cost var区别
作用域上,let和const是块级作用域,只在{}内有效,var是函数或全局作用域。变量提升方面,var会提升且初始化为undefined,let和const提升后在暂时性死区,不能提前用。赋值上,let可改,const声明基本类型不可改,对象属性能改。
CSS元素居中的方法
- flex布局
- 绝对定位+transform
- 子绝父相+上下左右0+margin:auto (固定宽高)