回答问题的原则: 能用量词, 尽可能用量词, 注意: 不要一直然后然后, 要有条理
推荐: 总分总结构 / 第一, 第二, 第三, 第四 ...0. 事件冒泡和捕获?事件冒泡:当子元素(事件源)事件触发,事件会沿着包含关系,依次往上级传递,每一级都可以感知到事件,直到触发根元素(根源)阻止冒泡:在相应的函数中加上event.stopPropagation()不让事件向document上蔓延事件捕获:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)阻止捕获:stopImmediatePropagation()方法来阻止事件捕获或冒泡事件委托:也叫事件代理,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡优点:减少事件注册减少内存 在table上代理所有的td点击事件 在ul上代理所有的li点击事件缺点:对不冒泡短的事件不支持 层级过多 冒泡过程可能会被某层阻止 可能会出现事件误判 单击变双击1. 前端有哪几种本地存储方式?  5种(1)cookie (过期时间expires)        请求时自动携带, 4k, 原生操作麻烦 (插件: js-cookie)生命周期: 默认是会话级别, 关闭浏览器就销毁 => 但是可以设置过期时间(2)localStorage永久存储, 5M(3)sessionStorage会话级别, 页面关闭就销毁, 临时暂存数据 5M-----------------------------------------------------------------(4)websql          已废弃(5)indexedDB       基于键值对存储, 可以存大量的数据, 至少可以存几百M2. JS 的参数是以什么方式进行传递的?考你值类型 和 引用类型的传值JS中的数据类型 2种:- 简单数据类型(基本数据类型)  string boolean number undefined null (symbol)简单数据存储于变量中, 存的是值本身, 赋值之后的修改, 互不影响- 引用数据类型(复杂数据类型)引用数据类型存储于变量中, 存的是地址, 赋值之后赋值的是地址, 地址相同, 修改就会互相影响3. JS垃圾回收机制的理解?JS中内存的分配 和 回收, 都是自动完成的, 内存在不使用时, 会被垃圾回收机制自动回收function fn () {let num = 1let obj = {}}fn 函数调用时, 开辟内存空间, 调用完, 内存空间会自动被释放注意: 不是所有的空间都会被立刻回收, 回收机制有两种, 引用计数, 标记清除, 满足回收策略, 确定是垃圾了, 才会回收回收机制的两种: 回收机制会有策略, 判断内存是否是垃圾1. 引用计数 (IE) => 引用为 0, 就需要释放看一个对象是否有指向它的引用, 如果没有任何变量指向它, 说明对象已经不需要了, 该被释放对象空间的引用计数, 引用为 0, 就需要释放致命缺点: 引用计数存在 循环引用 的问题, 造成了内存泄露2. 标记清除 (主流浏览器, chrome 火狐 ...) => 无法到达的对象要回收回收策略: 将不再使用的对象 定义为 无法到达的对象, 无法到达的对象要回收1. 从根部(JS中全局对象)出发, 定时扫描内存中的对象2. 凡是从根部能到达的对象, 都是还要使用的, 如果无法从根部出发, 触及到, 就会被标记为不再使用!4 . 作用域链的理解?作用域: 全局作用域 局部作用域 块级作用域 3种平时开发中, 作用域存在嵌套的情况, 变量访问的链式作用域结构, 就称之为是作用域链变量访问的原则: 就近 => 优先访问自己作用域的变量, 如果没有, 就往外部作用找5. 闭包的理解闭包概念: 函数 和 声明该函数的 词法环境的组合简单点: 内层函数 引用 外层函数的变量, 就可以形成闭包理解: 内层函数被缓存时, 外部作用域所访问到的变量, 也会被缓存下来闭包应用(优点): 缓存数据 hooks, 实现数据私有闭包的缺点: 滥用闭包, 如果不及时释放, 会造成内存泄露(global vaiiables)应用场景: 点击事件,需要用到外部的局部变量,有了闭包在数据传递上更为灵活。匿名自执行函数----------------------------------------------------------------------react中hooks闭包的问题const [count, setCount] = useState(0)useEffect(function() {setInterval(() => {console.log(count)  // 永远是0// 实时拿最新的值?参数传递setCount(count => {console.log(count)return count})}, 1000)}, []) // 只会在dom解析完成, componentDidMount 之后执行一次----------------------------------------------------------------------6. 原型 和 原型链为什么要有原型 => 如果每个实例都自己构造自己的方法, 太浪费内存, 其实方法是可以共享的原型意义: 给实例 "共享方法" , 节约内存的一个对象原型的三角关系图: 构造函数  原型   实例 原型链: 实例对象, 有着原型, 而原型有着原型的原型, 这样一层一层的链式原型结构, 就是原型链属性访问原则: 访问 实例.属性, 先访问自己, 如果自己没有, 往原型链上就近查找 ...7. 继承分类: 三大类, 原型继承, 组合式继承, 寄生组合式继承(1) 原型继承: 原型替换, 继承方法Student 继承自 Person, Person 有的方法, Student 都应该有Student.prototype = new Person()(2) 组合式继承: 将构造函数借调 + 原型替换组合1 原型替换 => 继承方法   子构造函数.prototype = new 父构造函数()2 构造函数借调 => 继承实例属性父构造函数.call(this, xx, xx)(3) 寄生组合式继承: 将构造函数借调 + 原型替换组合 + Object.create 优化1 原型替换 => 继承方法   子构造函数.prototype = new 父构造函数()2 构造函数借调 => 继承实例属性父构造函数.call(this, xx, xx)3 对原型替换做了优化Object.create基于传入的对象, 创建一个新对象, 让新对象的__proto__ 直接指向传入的对象子构造函数.prototype = Object.create(Person.prototype)相比于, 原来的原型替换, 替换成父构造函数的实例 => 寄生式好处, 省了一个 new 的过程, 直接形成原型关系es6 新增的继承 => extends8. 判断是否是数组Object.prototype.toString.call(数组)    '[object Array]'Array.isArray(数组)                     trueObject.prototype.toString.call(数据)    '[object 类型]'9. 数组去重let arr = [1, 3, 6, 6, 3, 1]let newArr = [...new Set(arr)]  // newArr 就是去重完的数组10. this的理解this的5种情况1. 默认绑定  fn()            指向window  定时器 / 延时器2. 隐式绑定  obj.fn()        指向调用者3. new绑定   new Person()    指向实例  (new会让构造函数的this, 指向创建出来的实例)4. 显示绑定  call(接受多个参数) apply(接受一个包含多个数组) bind(返回函数) 想让他指向谁, 就指向谁5. 箭头函数  () => { ... }   上一层作用域的 this11. async和awaitasync 是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象因此对async函数可以直接then,返回值就是then方法传入的函数。await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待await 修饰的如果是Promise对象:可以获取Promise中返回的参数(resolve或reject)取到值后语句才会往下执行11. PromisePromise几个状态? 3个状态  pending等待   fulfilled成功   rejected失败new Promise((resolve, reject) => {// 一帮封装异步操作 xhr, fs ...// 成功的时候, 调用 resolve 将promise(同步执行)的状态修改成成功fulfilled  将来执行 then(异步执行)  // 失败的时候, 调用 reject  将promise的状态修改成失败rejected   将来执行 catch})状态凝固, 一旦promise的状态被修改了, 就会状态凝固, 不能再更新状态了resolve(100)  成功了reject(200)   再去失败  无意义的promise.all(成功失败都可调用)12. 如何手写实现Promise.all 和 Promise.race?  Promise的四个静态方法: 1. Promise.resolve(200)  得到一个成功的promise对象new Promise((resolve, reject) => {resolve(200)})2. Promise.reject(500)      得到一个失败的promise对象new Promise((resolve, reject) => {reject(500)})3. Promise.all([p1, p2, p3]).then(values => { ... })等待原则: 会等待所有的promise都满足条件, 才算成功Promise.myall = function(arr) {let count = 0 // 计数器, 统计已经成功的个数let resultsArr = [] // 数组, 用于统计所有的成功的结果return new Promise((resolve, reject) => {// 等待所有的promise都满足条件// 遍历 arrarr.forEach((item, index) => {item.then(res => {resultsArr[index] = rescount++ // 每成功一个, 就让count++// 每成功完一个, 也要判断一下, 是否达到了目标个数if (count === arr.length) {resolve(resultsArr)}}).catch(err => {reject(err)})})})}4. Promise.race([p1, p2, p3]).then(value => { ... })竞速原则: 所有的promise中, 第一个满足条件的, 就会触发 race 的 .thenPromise.myrace = function(arr) {// 遍历arr 去.then 只要第一个 .then 了, 直接整个promise就成功return new Promise((resolve, reject) => {arr.forEach(item => {item.then(res => {resolve(res)})})})}13. 深拷贝 浅拷贝浅拷贝: 只拷贝一层1. for in2. ... 展开运算符深拷贝: 拷贝多层, 递归拷贝1. 递归2. JSON.stringify / JSON.parse深拷贝如果遇到循环引用怎么办? (了解)核心思路: 拷贝时, 准备一个数组, 存储拷贝了的所有的复杂类型的引用地址,每一次进行递归拷贝之时, 遍历数组, 判断这个对象, 是否曾经拷贝过, 如果拷贝过, 直接用这样创建出来的新的对象, 也是一个存在着循环引用关系的新对象--------------------------- HTTP 协议 Start ------------------------------14. HTTP有哪些⽅法?get获取  post新增  put修改  patch修改  delete删除15. HTTP请求报文和响应报文请求报文: 请求行  请求头  请求体响应报文: 响应行  响应头  响应体16. http状态码? 200 成功         201 新建      301/302 重定向   304 协商缓存400 接口传参错误401 权限认证未通过403 请求资源拒绝404 找不到5xx 服务器错误17. https? https是如何保证安全?https 相比于 http 更安全https 在数据传输时, 进行数据的加密处理, 所以更安全如何保证安全?(1) https 加密方案: 非对称加密 + 对称加密结合了两种加密方式, 实际传输信息过程, 以对称加密为主如何保证约定的密钥的传输的安全性? => 利用非对称加密传输密钥1. 先使用非对称加密, 传输对称加密的密钥   =>  密钥的传输安全性2. 再经过对称加密的密钥, 来进行信息的传输 =>  传输的效率高(2) 数字证书: 加密签发公钥      (类似于, 你要往码云上ssh提交信息, 得把公钥给到码云)访问一个网站时, 你要和网站交流, 传输对称加密的密钥, 就需要网站将公钥给你客户端 和 服务器, 初步互通消息, 客户端发送请求, 可以拿到数字证书数字证书: 一般由权威机构颁发, 包含网站基本信息, 到期时间, 公钥, ...当用户端, 拿到数字证书, 也就是拿到的公钥, 就可以基于公钥 和 服务端, 传输对称加密的密钥, 进行数据通信(3) 数字签名: 防证书篡改数字证书网站: xxx.xxx.xxx公钥: xxxu12u3ufyy213到期时间: 2050年10月02日签发机构: CA机构签名摘要: 上面证书信息的hash加密结果 12ueifusy2y4yuysu123----------------------------------------------------------------有哪些加密方案? 不同的加密方案有什么区别?1. 对称加密: 相同密钥加密解密, 可逆优点: 计算量小, 加密速度快, 加密效率高缺点: 如果一开始密钥就泄露了, 没有任何安全性可言了我(密钥)          =>         他(密钥)我(密钥)          <=         他(密钥)2. 非对称加密: 有两把钥匙, 公钥, 私钥, 可逆优点: 非对称加密 相比于 对称加密, 更安全缺点: 加密 和 解密花费的时间会更长, 速度会慢, 只适合对少量的数据来加密ssh 需要本地生成两把钥匙 - 互相配对的两把钥匙: 公钥, 私钥 => 公钥给到 码云我电脑(私钥)       =>         码云(公钥)我电脑(私钥)       <=         码云(公钥)3. Hash算法加密: 不可逆的, 根据一段内容, 生成一段唯一标识, 一般用于验证数据是否被篡改abc               =>          idsufyu3hrhfhewf后台数据库, 对于密码的存储, 一般情况会用 Hash 算法比较老的hash算法, 容易被撞库, 造成泄露  => md5  / sha25618. http2.x 优势1. http2.x 二进制传输数据,  http1.x文本传输, 二进制解析更高效2. http2.x 头部压缩技术, 减少请求和响应头中重复携带的数据, 降低网络负担  (老样子)3. http2.x 服务器推送方式, 可以主动向客户端推送资源, 提高页面加载效率4. http2.x 多路复用机制, 少创建一些连接, 降低资源占用 和 资源损耗单个连接可以承载任意数量的双向数据流 19. 缓存控制大类: 数据库缓存  服务端缓存  浏览器缓存浏览器端缓存:  HTTP 缓存  / 本地存储 (localStorage sessionStorage cookie websql indexedDB) - 前端HTTP缓存: 优化页面加载效率, 如果没有缓存, 所有的信息资源都要重新加载, 会非常慢(1)强缓存: 从服务器获取得到一个资源, 图片资源会在响应时标记有效期 (过期时间), 将来使用资源前, 会判断资源是否在有效期内, 如果在有效期内, 直接读缓存即可  => 强缓存 cache关键标识符:- Expires: 指定一个具体的日期  Mon, 19 Apr 2032 16:00:00 GMT (服务器给你的) 到了这个时间, 缓存过期- Cache-Control: 指定一个过期时间(相对时间) 315360000s 十年, 从你拿到这个资源开始计时, 十年后, 过期以Cache-Control为主, Expires辅助(2)协商缓存: 若未命中强缓存(强缓存过期了), 则浏览器就需要发请求到服务器状态: 本地有 xx.png 的图片资源缓存, 但是过期了, 肯定要问服务发请求, 要资源 (携带缓存的图片资源信息)服务器: 接收到请求, 判断该图片, 是否更新过, 如果没有更新过, 还是原来的图片, 此时不需要响应图片资源客户端: 经过了服务器端确认, 直接从缓存中读取, 并且更新新的过期时间协商缓存: 哥们, 我手里有一张过期的图片, 这个图片还能不能用了? 服务器瞅了眼, 没啥变化, 还能用十年好的, 那我直接从缓存中读, 更新过期时间十年, 十年后我再来问你协商缓存的两个状态码:304: 协商缓存成功, 协商成功, 询问过期图片是否有变化, 无变化, 直接从缓存中读, 更新新的过期时间服务器不会响应图片资源, 会响应新的过期时间200: 协商缓存失败, 服务器立刻将更新后的图片, 响应给客户端服务器会响应图片资源, 新的图片资源也会有过期时间协商缓存, 如何判断图片是否有变化?  (1: 看最后修改时间, 有没有变化   2: 看校验码有没有变化)关键表示符:- Last-Modify: 后台返回的该资源最新的更新时间, 精确到秒  Tue, 19 Apr 2022 06:18:56 GMT协商请求时, 拿着Last-Modify, 在请求时的If-Modify-Since字段中传给后台, 后台会判断修改时间是否相同, 如果相同, 协商成功! 304 直接从缓存中读缺点: 修改时间的记录, 最高精确到秒, 如果同一秒修改了多次, 就有可能缓存错文件了- Etag: 后台返回的该资源的校验码, 保证每一个资源是唯一的,资源变化都会导致ETag变化 (内容变化了)协商请求时, 拿着Etag请求服务器, 在请求时的If-None-Match字段中传递Etag, 后台判断校验码是否相同,如果相同, 协商成功! 304 直接从缓存中读强缓存 和 协商缓存一般一起配合使用, 用于缓存资源 (图片 / html / css / js)--------------------------- HTTP 协议 End --------------------------------------------------------- TCP 协议 Start ------------------------------20. 一次完整的HTTP服务过程是什么? 在地址栏, 输入 www.baidu.com 具体发生了什么?21. 对www.baidu.com进行网址DNS域名解析, 将域名解析得到ip的过程 (计算机只认IP)DNS解析: 优先找本机hosts, 如果本机hosts没有配置, 会去公网找DNS解析服务器, 解析到IPwww.baidu.com  => 112.80.248.7522. 根据这个ip找到对应的服务器, 想要建立TCP连接, 发起TCP的三次握手------------------- S 开始服务 ----------------23. 建立成功TCP连接后, 进行 HTTP 请求24. 服务器响应 HTTP 请求, 浏览器就会得到 html 代码25. 浏览器解析 html, 根据link script img/src 加载更多的资源 (js/css/图片)26. 浏览器将完整的页面渲染给用户------------------- E 结束服务 ----------------27. 服务完成, 关闭TCP连接, TCP四次挥手21. 三次握手? 四次挥手?三次握手 还有 四次挥手, 都能够体现, TCP连接建立断开的谨慎性, 节约服务器资源(1) 要建立TCP连接?  => 三次握手  本质是确认通信双方收发数据的能力理解: 打电话双方需要, 确定收发消息的能力, 才会进行信息交谈 => 0707能否收到? 0707收到, 请讲? 1. 第一次握手, 客户端往服务器发消息    hello, 能听到么?本质上服务器确定: 服务器能收消息, 客户端能发消息02. 第二次握手, 服务器给客户端回消息    好的,好的, 能听到! 你能听到我说话么?本质上客户端确定: 客户端能发消息, 服务器能收消息,  服务器能发消息, 客户端能收消息3. 第三次握手, 客户端要给服务器回消息  好的, 好的, 我也能听到你!本质上服务器确定: 客户端能发消息, 服务器能收消息,  服务器能发消息, 客户端能收消息经过了三次握手, 确实实现了, 收发能力的确认, 进而进行消息的传递(2) 要断开TCP连接?  => 四次挥手  本质不能轻易直接断开连接, 保证数据传输的安全性服务已经完成, 我想要断开连接1. 第一次挥手, 客户端主动发起, 断开连接       领导, 你刚和我说的说完了么, 说完了, 我要挂了?2. 第二次挥手, 服务器回应, 我知道了, 你给我等会, 我检查检查有没有什么没传输完的a few moments ago3. 第三次挥手, 服务器回应, 兄弟, 确实没有啥要补充的了, 可以断开连接了4. 第四次挥手, 客户端回应, 好嘞哥, 那我真断开了--------------------------- TCP 协议 End ------------------------------22. 浏览器是如何解析CSS选择器的?div span a   我们的想法, 先找到所有的 div, 遍历, 判断后代有没有 span, 记录下来, 再判断, 后代有没有 a, 如果有就命中div span a   实际浏览器解析, 先找到所有的 a, 遍历, 看这个 a 没有 span 的祖辈, 看 span 有没有 div 的祖辈, 如果有就命中实际浏览器解析css选择器: 右侧往左解析 (目的: 效率更高)1. 从左往右?  遍历子孙后代20000个元素 => 找所有的div  找20000次   找第一层没有任何区别某个div下, 有8000个元素 => 找所有的span  找8000次    第二层某个一个元素需要遍历子孙后代, 树形结构2. 从右往左?  需要遍历祖辈20000个元素 => 找所有的a    找20000次   找第一层没有任何区别某个a, 是否有一个祖辈, 是span, 祖辈40个 => 尝试找所有的祖辈  找40次     第二层某个一个元素  量级差了很多需要遍历祖辈, 线性结构, 一共就那么多祖辈23.  浏览器底层渲染流程24.  解析 HTML, 生成 dom树25.  解析 CSS, 生成 样式规则26.  将 dom 树 和 样式规则结合, 生成渲染树27.  基于渲染树, 进行布局渲染 => Layout (重排/回流)   搭架子28.  基于渲染树, 进行绘制    => Paint (重绘)         上色24. 重绘重排25. 结构层面, 布局层面变化 => 触发重排, 重新Layout => Layout之后必然需要重新Paint26. 样式层面, 颜色等等变化 => 触发重绘, 重新Paint即可重排必将触发重绘, 重绘不一定重排 实际工作: 尽可能避免 批量的 重排, 容易影响性能优化策略:- 1 集中修改样式 (这样可以尽可能利用浏览器的优化机制, 一次重排重绘就完成渲染)- 2 尽量避免在遍历循环中, 进行元素 off set Top 等样式值的获取操作, 会强制浏览器刷新队列, 进行渲染- 3 利用 transform 实现动画变化效果, 去代替 left top 的变换 (轮播图等)transform变换, 只是视觉效果! 不会影响到其他盒子,  只触发了自己的重绘- 4 使用文档碎片(DocumentFragment)可以用于批量处理, 创建元素25. 工作场景 git 的应用实际工作git => gitlab => 支持自己的服务器搭建 (自建的git服务器, 不依赖于第三方, 更稳定更安全)常见第三方git服务器: github 码云但是操作流程gitlab 和 github/码云完全一致 (包括配置ssh) 本地生成公钥和私钥, 把公钥给到gitlab以码云为例, 演示基本操作:1. 不常见, 远程没有仓库, 需要自建仓库, 建一个空仓库本地:git initgit add .git commit -m '初次提交'git remote add origin 远程仓库地址git push origin master新建2. 常见, 远程已有仓库, 需要拉取代码, 你老大会给你一个地址, 让你去拉代码 (拉代码之前必须先配ssh)不配ssh, 没有权限拉代码!!! 且这个仓库会有多个分支 master主分支  dev开发  test测试详见工作流程.txt----------------------------------- Vue相关 Start -------------------------------26. 什么是MVVM ?是一种设计模式, Model(数据层)  View(视图层)  ViewModel(视图数据控制层)数据变化 => ViewModel监听到 => 更新视图视图变化 => ViewModel监听到 => 更新数据双向数据绑定27. 双向数据绑定的原理数据变化的监听? Vue2 Object.defineProperty  Vue3 proxy视图变化的监听? 给元素注册事件监听 @change @input ...问: Object.defineProperty 和 proxy的差异?Object.defineProperty:(1) Object.defineProperty 是对于对象属性的劫持, 需要一个个递归劫持, 效率低(2) Object.defineProperty 对于数组的更新检测, 比较麻烦prxoy:proxy对于整个对象的劫持, 对象内部的任何属性的修改, 都会先经过外层proxy, 无需递归, 效率高proxy也可以直接监听数组的变化28. Vue的响应式系统 => 观察者模式   监听到, 更新谁? 如何运作的?Vue采用的是观察者模式, 以Vue2为例, 通过 Object.defineProperty 完成对于数据的劫持通过观察者模式, 完成对于节点的数据更新观察者模式: 是一种 一对多的 设计模式, 一个对象变化了, 其他所有依赖的, 跟着变一上来 vue 解析渲染, 会进行依赖收集, 会将渲染watcher, 计算属性watcher, 侦听器watcher, 都会收集到对应 dep 中 (依赖收集完成)当 Object.defineProperty 监听到数据变化, 就会根据依赖关系, 派发更新, 每个watcher侦听器都是一个对象, 都有着callback回调, 执行回调 (调用函数, 派发更新)https://vue-js.com/learn-vue/start/#_1-%E5%89%8D%E8%A8%80vue2 响应式的缺点是:无法监听到对象属性的动态添加和删除 无法监听到数组下班和length长度的变化 我们可以用以下方法解决: this.$set  this.$delete29. Vue生命周期1. 开始构建2. 初始化数据3. 编译模板4. 挂载dom5. 渲染 / 更新6. 卸载全了, 11个钩子 (8个基本 + 2个配合keep-alive + 1不常用的)8大钩子 Vue2                                             Vue3beforeCreate 创建前  数据不可用                     setupcreated    创建后  数据可请求                           setupbeforeMount  挂载前 方法没解析                     onBeforeMountmounted  已挂载dom  可解析                                             onMountedbeforeUpdate 更新前 数据更新 页面没有              onBeforeUpdateupdated  更新  页面发生变化才触发                                               onUpdatedbeforeDestroy  销毁前                                     onBeforeUnmountdestroyed  被销毁                                            onUnmounted30. Vue组件通信 7种31. 父传子 子传父(1) 通过 props 父传子, 给组件添加属性传值- <Jack money="100" :age="age"></Jack>- 组件内部props接收(2) 子传父, 利用 $emit 和 @ 注册事件, 实现数据传递- 子组件: this.$emit('事件名', 参数)- 父组件: @事件名="处理函数"2. 事件总线  (Vue3被移除)通过EventBus进行信息的发布和订阅更新(1) 创建事件总线const eventBus = new Vue()export default eventBus(2) 在A组件中, 监听, 订阅变化eventBus.$on('事件名', function() {...})(3) 在B组件中, 触发 bus 的事件eventBus.$emit('事件名', 参数)3. provide inject  (Vue3被增强)用于父组件向子孙后代组件共享传递数据Vue2, 其实也有 provide 和 inject, 但是不太好用Vue3, 大大的增强了 provide 和 inject, 广泛应用Vue3:(1) provide('共享的键名', '值')provide('共享的方法名', function() {...})(2) let result = inject('共享的键名' , 默认值)let fn = inject('共享的方法名') // 子孙后代, 调用祖辈的方法, 传参更新数据4. $children $parent $refs$children: 用于获取模板中的子组件集合    $children[0] 第一个组件$parent:   用于获取父组件$refs: 用于配合ref, 获取具体哪一个组件5. $attrs  $listeners组件二次封装用到 => 需要进行 批量 的跨层级数据传递  (使用起来, 就像父传子, 子传父一样)v-bind="$attrs"   批量获取props, 批量往下传递v-on="$listeners" 批量监听事件, 批量向上触发6. Vuex5个核心概念:(1) state: 存放数据(2) mutations: 存放操作数据的方法(3) actions: 存放一些异步操作, 注意: actions 不可以直接操作state, 需要提交mutation(4) getters: 计算属性(5) modules: 分模块同步情况:  页面中    commit('模块名/某mutation', '参数')异步情况:  页面中    dispatch('模块名/某action', '参数')action中  commit('模块名/某mutation', '参数')7. pinia (Vue3)  官方推荐的状态库   将来Vuex5的语法, 就会和pinia的语法类似核心概念:(1) state: 存数据        datastate () {return {count: 100,money: 1000}}(2) actions: 存放方法, 既可以同步, 也可以异步, 且可以直接操作状态   methodsactions: {addCount () {this.count++},addCountAsync () {setTimeout(() => {this.count++}, 1000)},async getMoney () {const res = await xxApi()this.money = res.data.money}}(3) getters: 计算属性--------------------------------------------------------------完整 pinia仓 库写法: store/count.js 一个文件, 就是一个仓库export const useCounterStore = defineStore('counter', {state() {return { count: 0 }},actions: {add() {this.count++},},})页面中, 无论同步还是异步, 直接导入对应的仓库, 直接调用方法即可1. 导入仓库import { useCounterStore } from '@/store/count.js'const counter = useCounterStore()2. 直接访问使用仓库的数据, 获取调用仓库的方法<div>{{ counter.count }}<button @click="counter.add">按钮</button></div>31. Vue中key的作用? / React中key的作用?作用: 给虚拟dom添加标识, 优化复用对比策略, 优化渲染性能考察点:32. Vue/React的更新机制: 差异化更新, 对比新旧虚拟dom, 找出新旧dom不同的部分, 进行更新视图33. 为什么对比虚拟dom? 不对比真实dom?真实dom的结构, 太复杂, 有着很多无用的属性, 无需对比, 如果对比了浪费性能虚拟dom, 是一个js对象, 通过js对象, 描述真实的dom, 只记录关键属性, 对比起来性能更高34. 就算是进行了虚拟dom的优化, 但是dom树, 是树形结构! 虚拟dom树, 也是树形结构, 树形结构的对比? => diff算法diff算法策略:(1) tree diff 同层比较, 同层对比, 如果发现根级别的元素类型不同, 直接整棵树销毁重建(2) component diff 同层级别元素类型相同, 按照策略, 对比差异, 记录差异(3) element diff  子节点列表, 同层兄弟节点, 默认按照下标进行对比, 如果加上key, 就相当于给虚拟dom加上了标识对比策略: 就是对相同key的元素, 进行比较子节点列表, 顺序下标, 会发生变化时, 推荐都加上key, 便于正确复用! (列表 v-for 往列表前面加, 中间加)32. Vue 跳转路由时的传参方式   (Vue2 / Vue3)  ---- 必答 ----3种 => query传参, params传参, 动态路由传参1. query传参: 会在地址栏显示, 刷新不会丢失router.push('/login?username=zs&age=18')router.push({path: '/login',query: {username: 'zs'age: 18}})获取: route.query.username33. params传参: 内存中传递, 不显示地址栏, 刷新会丢失, 必须配合命名路由使用如果要处理刷新会丢失的问题, 需要配合 localStorage{ path: '/login', name: 'login', component: () => import('@/views/login/index.vue') }router.push({name: 'login',params: {car: '小车车'}})获取: route.params.car34. 动态路由传参: 地址栏传递, 显示在地址栏, 刷新不会丢失, 必须配动态路由{ path: '/user/:id', component: () => import('@/views/user/index.vue') }router.push({path: '/user/92377447',})获取: route.params.id33. Vue权限控制  RBAC: role based access control 基于角色的权限控制给用户分配角色, 给角色分配权限核心点:1. 按钮权限控制 / 表单 / 表格登录成功时, 获取用户的权限相关信息, 角色roles: [{ xx }, { xx }]  按钮规则btnRules: [{ xx }, { xx }]根据返回的权限信息, 调用封装好的函数, 判断按钮, 是否需要禁用启用 / 显示隐藏2. 菜单权限控制(1) 登录成功时, 获取用户的权限相关信息, menus: ['xx', 'xx', 'xx'][{"moduleGroupId": 1001,"moduleGroupName": "部署管理","requestMapping": "deploy-manage",},{"moduleGroupId": 1100,"moduleGroupName": "系统管理","requestMapping": "sys-manage","moduleList": [{"moduleId": 1101,"moduleName": "系统日志","requestMapping": "system-log","moduleGroupId": 1100,},{"moduleId": 1102,"moduleName": "系统告警","requestMapping": "sys-alert","moduleGroupId": 1100,},],}](2) 将路由拆分成, 动态路由和静态路由, 动态路由需要权限才能访问的路由, 静态路由默认即可访问的路由(3) 用户一登录成功, 会动态的新增一些动态路由 addRoutes, 此时不同用户的路由已经不一样了(4) 但是为了菜单的响应式展示, 动态使用 vuex 维护路由数组3. api接口url权限控制: 后端控制多一点34. 首屏渲染优化网站性能优化实战——从12.67s到1.06s的故事    (首屏优化)     量化数据, 更有说服力https://juejin.cn/post/6844903613790175240移动spa商城优化记(一)---首屏优化篇   (首屏优化)https://juejin.cn/post/6844903577815613453前端黑科技:美团网页首帧优化实践   (白屏问题优化)35. git工作流程编码环节:36. 刚进公司, 拉取公司已有代码37. 基于 dev 开自己的分支,  shuaipeng38. 分支上写代码, 将该分支, 发布往远程39. 写完了, 老大, 切到你的分支, 看代码有无问题, 看改了什么, 没啥问题, 合并到dev, 提交发布测试环节:将代码从dev分支, 合并到test分支, 让测试去测如果测试无问题上线环节:将代码从test分支, 合并到master, 上线编码环节:1. 先配ssh => 本地生成公钥私钥, 将公钥给到git服务器 (码云/gitlab/github)(1)命令行执行: ssh-keygen -t ed25519 -C "xxxxx@xxxxx.com"  (2)三次回车, 生成公私钥(3)找密钥目录: c/Users/用户名/.ssh/  => .pub 结尾的公钥(4)将公钥用记事本打开, CV 到 git服务器 ssh 配置中即可2. git clone 远程仓库地址      克隆远程仓库代码  (注意: 必须先配ssh, 否则没权限)微信: git@gitee.com:jepsonpp/test_git_demo.git  去拉代码吧我:   好的!(1) git clone git@gitee.com:jepsonpp/test_git_demo.git(2) 如果有提示, 就 yes 即可, 首次连接3. 切换到 dev 分支, 基于 dev 开新的分支(1) 左下角, 分支点开, 选择 origin/dev, 就会切换到 dev 分支(2) 左下角, 确定是dev, 点开, 创建新分支, 输入分支名 shuaipeng 回车4. 在你的分支下, 写功能, 写代码, 在你的分支下提交(1) 确定左下角是shuaipeng, 再写代码(2) 点开左边源代码管理器, 提交代码(3) 点击发布按钮, 发布远程      =>  git push origin shuaipeng5. 写完了, 老大, 切到分支, 检查代码, 最终合并一下代码, 往dev合并(1) 左下角点开, 点击 origin/shuaipeng, 本地拉取最新的 shuaipeng(2) 确认代码, 无误后, 切换到 dev 分支(3) 合并 git merge 分支名(4) 推送 dev 的更新测试环节:将代码从dev分支, 合并到test分支, 让测试去测(1) 切换到 test(2) 将dev的代码合并过来(3) 推送 test 的更新上线环节:将代码从test分支, 合并到master, 上线(1) 切换到 master(2) 将test的代码合并过来(3) 推送 master 的更新36. nextTick和$nextTick区别1.nextTick(callback):当数据发生变化,更新后执行回调,在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。2.$nextTick(callback):(异步执行)当dom发生变化,更新后执行的回调。将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。37.单页面应用程序的特点:单页面应用程序将所有的功能局限于一个web 页面中,仅在该web 页面初始化时加载相应的资源(HTML、 JavaScript 和CSS)。一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转。而是利用JavaScript 动态地变换HTML 的内容,从而实现页面与用户的交互。1-1.单页面的优点:1.良好的交互体验:单页应用的内容的改变不需要重新加载整个页面获取数据也是通过Ajax 异步获取没有页面之间的跳转,不会出现“白屏现象”2.良好的前后端工作分离模式后端专注于提供API 接口,更易实现API 接口的复用前端专注于页面的渲染,更利于前端工程化的发展3.减轻服务器的压力服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍但是任何一种技术都有自己的局限性1-2.单页面的缺点:1.首屏加载慢,路由懒加载代码压缩,CDN 加速网络, 传输压缩2.不利于SEO,SSR 服务器端渲染38.flex布局:justify-content:center垂直居中align-items:center水平居中justify-content:flex-end尾部开始justify-content:flex-Start头部开始justify-content:space-around平分甚于空间flex-wrap:wrap换行flex-grow:1平均比例(子盒子)flex-shrink属性指定了flex元素的收缩规则(子盒子)flex-basis属性指定了flex元素在主轴方向上的初始大小(子盒子)

个人总结  仅供参考

前端面试基础题总结 (必会)相关推荐

  1. java面试基础题整理(二)

    java面试基础题整理 文章目录 java面试基础题整理 前端技术(HTML.CSS.JS.JQuery等) 在js中怎么样验证数字? js中如何给string这个类型加方法? 谈谈js的定时器? 请 ...

  2. java gui中文变方块_150道Java面试基础题(含答案)

    1)Java 中能创建 volatile 数组吗? 能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组.我的意思是,如果改变引用指向的数组,将会受到 vo ...

  3. 前端面试真题系列(一)-李游Leo-专题视频课程

    前端面试真题系列(一)-49人已学习 课程介绍         在鱼龙混杂的前端行业中,面试一直是一门非常重要的课程,尤其是笔试题. 而真实的面试题意味着你已经得到了面试邀请,在进入这家公司之前的第一 ...

  4. 12 道腾讯前端面试真题及答案整理

    年底了,又到了跳槽季啦,该刷题走起了.这里总结了一些被问到可能会懵逼的面试真题,有需要的可以看下- 1. 谈谈你对 dns-prefetch 的理解 DNS 是什么-- Domain Name Sys ...

  5. 2017年阿里Java面试基础题

    前言 这是我大概回忆整理的Java基础题,里面有很多知识点,主要还是在于Java基础,当然数据结构跟算法最好也要懂,是加分项,如果不会,果断说,否则,面试官深入问,问到你愣住了,这样浪费了自己的面试题 ...

  6. androID程序!BAT大厂面试基础题集合,附带学习经验

    没有稳定的工作,只有稳定的能力. 又到了万物复苏的季节,在程序猿这个行当里,作为 Android 开发出生的,在经历了八年的脱发生涯后,有了越来越多的想法和感触 趋势 随着各类移动跨平台的兴起,在 R ...

  7. 前端面试 100 题:能搞懂80%的请把简历给我

    引言 半年时间,几千人参与,精选大厂前端面试高频 100 题,这就是「壹题」. 在 2019 年 1 月 21 日这天,「壹题」项目正式开始,在这之后每个工作日都会出一道高频面试题,主要涵盖阿里.腾讯 ...

  8. 金三银四面试真题(必看)

    前两个月,公司java岗位面了50+候选人,面试下来发现几类过不了的情况,分享大家防止踩坑: 新技术倒是掌握得挺多,基础的却一塌糊涂. 工作多年,从未学习过工作之外的技术栈,也没有对技术有任何的兴趣, ...

  9. offer收割攻略,Web前端面试真题JavaScript系列(带详解)

    临近秋招,不少小伙伴开始了求职之路,面试是十分重要的考验,其次也离不开面试题.网上的面试题零零散散,十分混乱,正好我抽时间帮助大家总结一下.难易程度肯定是从简到难,今天是第一篇的续集--基础篇中的Ja ...

最新文章

  1. IOS设计模式的六大设计原则之开放-关闭原则(OCP,Open-Close Principle)
  2. 微信OPENID授权方法
  3. 点聚WebOffice 控件 使用LoadOriginalFile 打开服务器文件
  4. 6年Python开发,教你一天入门 Python
  5. mysql事务隔离级别详解_高性能MySQL-详解事务与隔离级别
  6. 设计模式——代理模式与装饰模式的异同
  7. C# list使用方法
  8. hadoop安装教程
  9. web安全详解(渗透测试基础)
  10. Day04_Manuals for Python@lisongye - list列表
  11. 【小程序云开发】不用后端也能构建完整的微信小程序
  12. 【KNIME经验】兼容读取多种日期格式数据
  13. 如何从Photoshop中提取笔刷到优动漫
  14. linux 内存 内核参数详解,linux系统内核参数说明
  15. 美团“封杀”支付宝遭反垄断诉讼,下一个会是谁?
  16. Forter宣布推出Trusted Identities解决方案 用于简化电子商务交互的身份验证
  17. Discuz! - 6.1 ~ 7.0 - 安装SupeSite后导致安全漏洞
  18. object冻结与解冻_脑冻结? 如何用思维导图解冻你的思想
  19. 酷开会员丨酷开系统亲子频道,用心陪伴孩子成长!
  20. 财务建模完整指南第七讲——第五届CVA估值建模

热门文章

  1. java3d载入obj_Threejs大型obj文件的秒加载实现
  2. Linux - 第11节 - 网络入门
  3. matlab用ode23解决参数方程,matlab变参量微分方程处理
  4. 渗透测试学习笔记(metasploit)
  5. 计算机三种校验方式,三种校验码
  6. 第五人格维修服务器中要不要玩,第五人格:匹配制度辣鸡!服务器还是崩!第五真的要凉了吗?...
  7. 期货反跟单-侃侃人工反跟单那些事儿
  8. 入职开发很少写代码_如何简化开发人员入职:将开发环境作为代码
  9. 亲身经历!4个月写完硕士毕业论文一稿过,我是如何做到的?
  10. 任正非:为什么华为选择与西工大合作,而没选清华北大