jacktown

jacktown 查看完整档案

眉山编辑  |  填写毕业院校  |  填写所在公司/组织 jacktown11.github.io/ 编辑
编辑

自强不息,厚德载物

个人动态

jacktown 赞了回答 · 2020-03-26

解决vscode 在vue文件中写 less 报语法错误

<!-- 是 lang,不是 language -->
<style lang="less" scoped>
</style>

image.png

image.png

关注 2 回答 1

jacktown 收藏了文章 · 2020-03-26

那些年读过的前端书籍资源分享(超赞!)

那些年读过的前端书籍资源分享(超赞!)

欢迎转载,但请著明转载来源:https://github.com/ZhengMaste...

1. JavaScript的必看的经典书籍

  • 《JavaScript高级程序设计》(第三版) 传说中的红宝书

    图片无法显示

    内容简介:

    本书是JavaScript 超级畅销书的最新版。ECMAScript 5 和HTML5 在标准之争中双双胜出,使大量专有实现和客户端扩展正式进入规范,同时也为JavaScript 增添了很多适应未来发展的新特性。本书这一版除增加5章全新内容外,其他章节也有较大幅度的增补和修订,新内容篇幅约占三分之一。全书从JavaScript语言实现的各个组成部分——语言核心、DOM、BOM、事件模型讲起,深入浅出地探讨了面向对象编程、Ajax 与Comet 服务器端通信,HTML5 表单、媒体、Canvas(包括WebGL)及WebWorkers、地理定位、跨文档传递消息、客户端存储(包括IndexedDB)等新API,还介绍了离线应用和与维护、性能、部署相关的最佳开发实践。本书附录展望了未来的API 和ECMAScript Harmony 规范。

    本书适合有一定编程经验的Web 应用开发人员阅读,也可作为高校及社会实用技术培训相关专业课程的教材。

    PDF文件下载链接: https://pan.baidu.com/s/1Rx9N...

    提取码: i47r

  • 《JavaScript权威指南》 (第六版) 传说中的js圣经

图片无法显示

PDF文件下载链接: https://pan.baidu.com/s/1FYua...

提取码: arbt

图片无法显示

PDF文件下载链接: https://pan.baidu.com/s/1dvC4... 提取码: 76yk

图片无法显示

PDF文档下载:

链接: https://pan.baidu.com/s/1Fkj4... 提取码: yqhn

### 2. HTML与CSS的入门到放弃的书籍

    • 《CSS权威指南》第四版

    图片无法显示

    PDF文档下载链接:https://pan.baidu.com/s/1idTA...

    提取码:6mzf

    • 《HTML5与CSS3权威指南》

      图片无法显示

    PDF文档下载链接: https://pan.baidu.com/s/16ou7...

    提取码: fpej

    • 《图解CSS3》

      图片无法显示

      内容简介:本书是CSS3领域的标准性著作,由资深Web前端工程师根据CSS3的最新技术标准撰写。内容极为全面、丰富和翔实,由浅入深地讲解了CSS3新特性的语法、功能和使用技巧,涵盖选择器、边框、背景、文本、颜色、UI、动画、新型盒模型、媒体查询、响应式设计等各种模块;写作方式创新,有趣且易懂,用图解的方式来描述CSS3的每一个特性甚至每一个步骤都配有实战效果图;包含大量案例,实战性强,每个特性都有作者从实践中精心归纳和挑选出来的案例辅助讲解,同时还包含一个综合性的大案例。无论你是完全没有经验的准前端工程师,还是已经有一定经验的前端工程师,如果你想系统学习CSS3,那么本书将会是你的最佳选择;如果你是一位成熟的前端开发工程师,但时常为如何合理地使用某些特性而费时去查阅相关资料,那么本书也是你的不二选择。

      PDF文档下载链接:https://pan.baidu.com/s/1jGUpKb0

    3. js火爆的前端框架Vue与React深入学习书籍

    图片无法显示

    链接:https://pan.baidu.com/s/1IjiW...

    提取码:wsss

    4. 后端与数据库学习

    5. 网络与性能优化相关书籍

    • 《图解HTTP》

      图片无法显示

      内容简介:
      本书对互联网基盘——HTTP协议进行了全面系统的介绍。作者由HTTP协议的发展历史娓娓道来,严谨细致地剖析了HTTP协议的结构,列举诸多常见通信场景及实战案例,最后延伸到Web安全、最新技术动向等方面。本书的特色为在讲解的同时,辅以大量生动形象的通信图例,更好地帮助读者深刻理解HTTP通信过程中客户端与服务器之间的交互情况。读者可通过本书快速了解并掌握HTTP协议的基础,前端工程师分析抓包数据,后端工程师实现REST API、实现自己的HTTP服务器等过程中所需的HTTP相关知识点本书均有介绍。

      本书适合Web开发工程师,以及对HTTP协议感兴趣的各层次读者。

      PDF文档下载

      链接: https://pan.baidu.com/s/16HN0...

      提取码: km23

    • 《HTTP权威指南》

      图片无法显示

      内容简介:

      ​ 超文本传输协议(Hypertext Transfer Protocol,HTTP)是在万维网上进行通信时所使用的协议方案。HTTP有很多应用,但最著名的是用于web浏览器和web服务器之间的双工通信。

      ​ HTTP起初是一个简单的协议,因此你可能会认为关于这个协议没有太多好说的。但现在,你手上拿着的是却一本两磅重 的书。如果你对我们怎么会写出一本650页 的关于HTTP的书感到奇怪的话,可以去看一下目录。本书不仅仅是一本HTTP首部的参考手册;它是一本名副其实的web结构圣经。

      ​ 本书中,我们尝试着将HTTP中一些互相关联且常被误解的规则梳理清楚,并编写了一系列基于各种主题的章节,对HTTP各方面的特性进行了介绍。纵观全书,我们对HTTP“为什么”这样做进行了详细的解释,而不仅仅停留在它是“怎么做”的。而且,为了节省大家寻找参考文献的时间,我们还对很多HTTP应用程序正常工作所必须的、重要的非HTTP技术进行了介绍。在组织得便于使用的附录中,可以找到按照字母排序的首部参考(这些首部构成了最常见的HTTP文本的基础)。我们希望这种概念性的设计有助于读者对HTTP的使用。

      ​ 本书是为所有希望理解HTTP以及Web底层结构的人编写的。软硬件工程师也可以将本书作为HTTP及相关web技术的条理清楚的参考书使用。系统架构师和网络管理员可以通过本书更好地了解如何设计、实现并管理复杂的网络架构。性能工程师和分析人员可以从高速缓存和性能优化的相关章节中获益。市场营销和咨询专家可以通过概念的介绍更好地理解web技术的前景。

      ​ 本书对一些常见的误解进行了说明,推荐了“各种使用诀窍”,提供了便捷的参考资料,并且对枯燥且令人费解的标准规范进行了可读性很强的介绍。在这本书里,我们对Web正常工作所必须且互相关联的技术进行了详细的介绍。

      本书是很多对因特网技术充满热情的人经过大量工作写成的。希望对你有所帮助。

      PDF文档下载:

      链接: https://pan.baidu.com/s/1hXn5...

      提取码: khap

    • 《高性能网站建设进阶指南》前端工程师精髓

      图片无法显示

      内容简介:
      本书结合Web 2.0以来Web开发领域的最新形势和特点,介绍了网站性能问题的现状、产生的原因,以及改善或解决性能问题的原则、技术技巧和最佳实践。重点关注网页的行为特征,阐释优化Ajax、CSS、JavaScript、Flash和图片处理等要素的技术,全面涵盖浏览器端性能问题的方方面面。在《高性能网站建设指南》中,作者给出了14条具体的优化原则,每一条原则都配以范例佐证,并提供了在线支持。《高性能网站建设指南》内容丰富,主要包括减少HTTP请求、Edge Computing技术、Expires Header技术、Gzip组件、CSS和JavaScript最佳实践、主页内联、Domain最小化、JavaScript优化、避免重定向的技巧、删除重复JavaScript的技巧、关闭ETags的技巧、Ajax缓存技术和最小化技术等。《高性能网站建设指南》适合Web架构师、信息架构师、Web开发人员及产品经理阅读和参考。

      PDF文档下载:

      链接: https://pan.baidu.com/s/1IEsG...

      提取码: nadd

    • 《Web性能权威指南》

      图片无法显示

      内容简介:

      本书是谷歌公司高性能团队核心成员的权威之作,堪称实战经验与规范解读完美结合的产物。本书目标是涵盖Web 开发者技术体系中应该掌握的所有网络及性能优化知识。全书以性能优化为主线,从TCP、UDP 和TLS 协议讲起,解释了如何针对这几种协议和基础设施来优化应用。然后深入探讨了无线和移动网络的工作机制。最后,揭示了HTTP 协议的底层细节,同时详细介绍了HTTP 2.0、 XHR、SSE、WebSocket、WebRTC 和DataChannel 等现代浏览器新增的具有革命性的新能力。

      本书适合所有Web 应用及站点开发人员阅读,包括但不限于前端、后端、运维、大数据分析、

      UI/UX、存储、视频、实时消息,以及性能工程师。

      Ilya Grigorik 是谷歌“Web加速”(Make The Web Fast)团队的性能工程师、开发大使。他每天的主要工作就是琢磨怎么让Web应用速度更快,总结并推广能够提升应用性能的最佳实践

      PDF文档下载

      链接: https://pan.baidu.com/s/1o2hO...

      提取码: nbva

    6. 前端工程化所需要读的书籍

    • [图灵程序设计丛书].《GitHub入门与实践》

    图片无法显示

    内容简介:

    本书从Git的基本知识和操作方法入手,详细介绍了GitHub的各种功能,GitHub与其他工具或服务的协作,使用GitHub的开发流程以及如何将GitHub引入到企业中。在讲解GitHub的代表功能Pull Request时,本书专门搭建了供各位读者实践的仓库,邀请各位读者进行Pull Request并共同维护。

    工作中Git常用命令:https://github.com/ZhengMaster2020/blogs/issues/5

    PDF 文档下载:

    链接: https://pan.baidu.com/s/1HC0E...

    提取码: cyvs

    • 《深入浅出webpack》

      图片无法显示

      内容简介:

      随着Web开发技术的发展,Webpack凭借其便于使用和涵盖面广的优势,成为目前非常流行的前端构建工具,是每位前端工程师的必备技能之一。

      《深入浅出Webpack》对Webpack进行了全面讲解,涵盖了Webpack入门、配置、实战、优化、原理等方面的内容。其中,第1章讲解Webpack入门所涉及的知识;第2章详细讲解Webpack提供的常用配置项;第3章结合实际项目中的常见场景进行实践;第4章给出优化Webpack的优秀方案;第5章剖析了Webpack的原理,并讲解如何开发Plugin和Loader;附录汇总了常见的Loader、Plugin和Webpack的其他学习资源。除了深入讲解Webpack,本书还介绍了ES6、TypeScript、PostCSS、Prepack、离线缓存、单页应用、CDN等Web开发相关的技能。

      无论是对 Webpack一无所知的初学者,还是经验丰富的前端工程师,相信都能够通过《深入浅出Webpack》进一步提升对Webpack的理解,并在Web开发中更熟练地运用Webpack。

      PDF文档下载

      链接: https://pan.baidu.com/s/1Ezdr...

      提取码: hdmr

    持续更新中。。。


    温馨提示:本文所有书籍均来源于网络,本篇内容不存在任何非法传播盗版书籍,

    如若有侵权请发邮件:e-mail: zhengmaster668@163.com

    Github: https://github.com/ZhengMaste...

    我会及时删除侵权内容。 欢迎star

    查看原文

    jacktown 提出了问题 · 2020-03-22

    解决vscode 在vue文件中写 less 报语法错误

    vscode 中用 less.vue文件中写样式,编辑器会报语法错误,已经安装了 vetur, prettier,左下角也显示正确识别为 vue 文件。

    这样写出来的代码可以实时运行,报错的样式有的能起作用,有的不能起作用,不知如何解决

    捕获.PNG

    关注 2 回答 1

    jacktown 赞了文章 · 2019-01-29

    一文掌握前端面试浏览器相关知识点

    事件机制

    事件触发三阶段

    事件触发有三个阶段

    • window 往事件触发处传播,遇到注册的捕获事件会触发
    • 传播到事件触发处时触发注册的事件
    • 从事件触发处往 window 传播,遇到注册的冒泡事件会触发

    事件触发一般来说会按照上面的顺序进行,但是也有特例,如果给一个目标节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行。

    // 以下会先打印冒泡然后是捕获
    node.addEventListener('click',(event) =>{
        console.log('冒泡')
    },false);
    node.addEventListener('click',(event) =>{
        console.log('捕获 ')
    },true)

    注册事件

    通常我们使用 addEventListener 注册事件,该函数的第三个参数可以是布尔值,也可以是对象。对于布尔值 useCapture 参数来说,该参数默认值为 falseuseCapture 决定了注册的事件是捕获事件还是冒泡事件。对于对象参数来说,可以使用以下几个属性

    • capture,布尔值,和 useCapture 作用一样
    • once,布尔值,值为 true 表示该回调只会调用一次,调用后会移除监听
    • passive,布尔值,表示永远不会调用 preventDefault

    一般来说,我们只希望事件只触发在目标上,这时候可以使用 stopPropagation 来阻止事件的进一步传播。通常我们认为 stopPropagation 是用来阻止事件冒泡的,其实该函数也可以阻止捕获事件。stopImmediatePropagation 同样也能实现阻止事件,但是还能阻止该事件目标执行别的注册事件。

    node.addEventListener('click',(event) =>{
        event.stopImmediatePropagation()
        console.log('冒泡')
    },false);
    // 点击 node 只会执行上面的函数,该函数不会执行
    node.addEventListener('click',(event) => {
        console.log('捕获 ')
    },true)

    事件代理

    如果一个节点中的子节点是动态生成的,那么子节点需要注册事件的话应该注册在父节点上

    <ul id="ul">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        let ul = document.querySelector('#ul')
        ul.addEventListener('click', (event) => {
            console.log(event.target);
        })
    </script>

    事件代理的方式相对于直接给目标注册事件来说,有以下优点

    • 节省内存
    • 不需要给子节点注销事件

    跨域

    因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。

    我们可以通过以下几种常用方法解决跨域的问题

    JSONP

    JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制的漏洞。通过 <script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。

    <script data-original="http://domain/api?param1=a&param2=b&callback=jsonp"></script>
    <script>
        function jsonp(data) {
            console.log(data)
        }
    </script>    

    JSONP 使用简单且兼容性不错,但是只限于 get 请求。

    在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要自己封装一个 JSONP,以下是简单实现

    function jsonp(url, jsonpCallback, success) {
      let script = document.createElement("script");
      script.src = url;
      script.async = true;
      script.type = "text/javascript";
      window[jsonpCallback] = function(data) {
        success && success(data);
      };
      document.body.appendChild(script);
    }
    jsonp(
      "http://xxx",
      "callback",
      function(value) {
        console.log(value);
      }
    );

    CORS

    CORS需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。

    浏览器会自动进行 CORS 通信,实现CORS通信的关键是后端。只要后端实现了 CORS,就实现了跨域。

    服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

    document.domain

    该方式只能用于二级域名相同的情况下,比如 a.test.comb.test.com 适用于该方式。

    只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域

    postMessage

    这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息

    // 发送消息端
    window.parent.postMessage('message', 'http://test.com');
    // 接收消息端
    var mc = new MessageChannel();
    mc.addEventListener('message', (event) => {
        var origin = event.origin || event.originalEvent.origin; 
        if (origin === 'http://test.com') {
            console.log('验证通过')
        }
    });

    Event loop

    众所周知 JS 是门非阻塞单线程语言,因为在最初 JS 就是为了和浏览器交互而诞生的。如果 JS 是门多线程的语言话,我们在多个线程中处理 DOM 就可能会发生问题(一个线程中新加节点,另一个线程中删除节点),当然可以引入读写锁解决这个问题。

    JS 在执行的过程中会产生执行环境,这些执行环境会被顺序的加入到执行栈中。如果遇到异步的代码,会被挂起并加入到 Task(有多种 task) 队列中。一旦执行栈为空,Event Loop 就会从 Task 队列中拿出需要执行的代码并放入执行栈中执行,所以本质上来说 JS 中的异步还是同步行为。

    console.log('script start');
    
    setTimeout(function() {
      console.log('setTimeout');
    }, 0);
    
    console.log('script end');

    以上代码虽然 setTimeout 延时为 0,其实还是异步。这是因为 HTML5 标准规定这个函数第二个参数不得小于 4 毫秒,不足会自动增加。所以 setTimeout 还是会在 script end 之后打印。

    不同的任务源会被分配到不同的 Task 队列中,任务源可以分为 微任务(microtask) 和 宏任务(macrotask)。在 ES6 规范中,microtask 称为 jobs,macrotask 称为 task

    console.log('script start');
    
    setTimeout(function() {
      console.log('setTimeout');
    }, 0);
    
    new Promise((resolve) => {
        console.log('Promise')
        resolve()
    }).then(function() {
      console.log('promise1');
    }).then(function() {
      console.log('promise2');
    });
    
    console.log('script end');
    // script start => Promise => script end => promise1 => promise2 => setTimeout

    以上代码虽然 setTimeout 写在 Promise 之前,但是因为 Promise 属于微任务而 setTimeout 属于宏任务,所以会有以上的打印。

    微任务包括 process.nextTickpromiseObject.observeMutationObserver

    宏任务包括 scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering

    很多人有个误区,认为微任务快于宏任务,其实是错误的。因为宏任务中包括了 script ,浏览器会先执行一个宏任务,接下来有异步代码的话就先执行微任务。

    所以正确的一次 Event loop 顺序是这样的

    1. 执行同步代码,这属于宏任务
    2. 执行栈为空,查询是否有微任务需要执行
    3. 执行所有微任务
    4. 必要的话渲染 UI
    5. 然后开始下一轮 Event loop,执行宏任务中的异步代码

    通过上述的 Event loop 顺序可知,如果宏任务中的异步代码有大量的计算并且需要操作 DOM 的话,为了更快的 界面响应,我们可以把操作 DOM 放入微任务中。

    Node 中的 Event loop

    Node 中的 Event loop 和浏览器中的不相同。

    Node 的 Event loop 分为6个阶段,它们会按照顺序反复运行

    ┌───────────────────────┐
    ┌─>│        timers         │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     I/O callbacks     │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     idle, prepare     │
    │  └──────────┬────────────┘      ┌───────────────┐
    │  ┌──────────┴────────────┐      │   incoming:   │
    │  │         poll          │<──connections───     │
    │  └──────────┬────────────┘      │   data, etc.  │
    │  ┌──────────┴────────────┐      └───────────────┘
    │  │        check          │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    └──┤    close callbacks    │
       └───────────────────────┘

    timer

    timers 阶段会执行 setTimeoutsetInterval

    一个 timer 指定的时间并不是准确时间,而是在达到这个时间后尽快执行回调,可能会因为系统正在执行别的事务而延迟。

    下限的时间有一个范围:[1, 2147483647] ,如果设定的时间不在这个范围,将被设置为1。

    I/O

    I/O 阶段会执行除了 close 事件,定时器和 setImmediate 的回调

    idle, prepare

    idle, prepare 阶段内部实现

    poll

    poll 阶段很重要,这一阶段中,系统会做两件事情

    1. 执行到点的定时器
    2. 执行 poll 队列中的事件

    并且当 poll 中没有定时器的情况下,会发现以下两件事情

    • 如果 poll 队列不为空,会遍历回调队列并同步执行,直到队列为空或者系统限制
    • 如果 poll 队列为空,会有两件事发生

      • 如果有 setImmediate 需要执行,poll 阶段会停止并且进入到 check 阶段执行 setImmediate
      • 如果没有 setImmediate 需要执行,会等待回调被加入到队列中并立即执行回调

    如果有别的定时器需要被执行,会回到 timer 阶段执行回调。

    check

    check 阶段执行 setImmediate

    close callbacks

    close callbacks 阶段执行 close 事件

    并且在 Node 中,有些情况下的定时器执行顺序是随机的

    setTimeout(() => {
        console.log('setTimeout');
    }, 0);
    setImmediate(() => {
        console.log('setImmediate');
    })
    // 这里可能会输出 setTimeout,setImmediate
    // 可能也会相反的输出,这取决于性能
    // 因为可能进入 event loop 用了不到 1 毫秒,这时候会执行 setImmediate
    // 否则会执行 setTimeout

    当然在这种情况下,执行顺序是相同的

    var fs = require('fs')
    
    fs.readFile(__filename, () => {
        setTimeout(() => {
            console.log('timeout');
        }, 0);
        setImmediate(() => {
            console.log('immediate');
        });
    });
    // 因为 readFile 的回调在 poll 中执行
    // 发现有 setImmediate ,所以会立即跳到 check 阶段执行回调
    // 再去 timer 阶段执行 setTimeout
    // 所以以上输出一定是 setImmediate,setTimeout

    上面介绍的都是 macrotask 的执行情况,microtask 会在以上每个阶段完成后立即执行。

    setTimeout(()=>{
        console.log('timer1')
    
        Promise.resolve().then(function() {
            console.log('promise1')
        })
    }, 0)
    
    setTimeout(()=>{
        console.log('timer2')
    
        Promise.resolve().then(function() {
            console.log('promise2')
        })
    }, 0)
    
    // 以上代码在浏览器和 node 中打印情况是不同的
    // 浏览器中一定打印 timer1, promise1, timer2, promise2
    // node 中可能打印 timer1, timer2, promise1, promise2
    // 也可能打印 timer1, promise1, timer2, promise2

    Node 中的 process.nextTick 会先于其他 microtask 执行。

    setTimeout(() => {
      console.log("timer1");
    
      Promise.resolve().then(function() {
        console.log("promise1");
      });
    }, 0);
    
    process.nextTick(() => {
      console.log("nextTick");
    });
    // nextTick, timer1, promise1

    存储

    cookie,localStorage,sessionStorage,indexDB

    特性cookielocalStoragesessionStorageindexDB
    数据生命周期一般由服务器生成,可以设置过期时间除非被清理,否则一直存在页面关闭就清理除非被清理,否则一直存在
    数据存储大小4K5M5M无限
    与服务端通信每次都会携带在 header 中,对于请求性能影响不参与不参与不参与

    从上表可以看到,cookie 已经不建议用于存储。如果没有大量数据存储需求的话,可以使用 localStoragesessionStorage 。对于不怎么改变的数据尽量使用 localStorage 存储,否则可以用 sessionStorage 存储。

    对于 cookie,我们还需要注意安全性。

    属性作用
    value如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识
    http-only不能通过 JS 访问 Cookie,减少 XSS 攻击
    secure只能在协议为 HTTPS 的请求中携带
    same-site规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击

    Service Worker

    Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。

    目前该技术通常用来做缓存文件,提高首屏速度,可以试着来实现这个功能。

    // index.js
    if (navigator.serviceWorker) {
      navigator.serviceWorker
        .register("sw.js")
        .then(function(registration) {
          console.log("service worker 注册成功");
        })
        .catch(function(err) {
          console.log("servcie worker 注册失败");
        });
    }
    // sw.js
    // 监听 `install` 事件,回调中缓存所需文件
    self.addEventListener("install", e => {
      e.waitUntil(
        caches.open("my-cache").then(function(cache) {
          return cache.addAll(["./index.html", "./index.js"]);
        })
      );
    });
    
    // 拦截所有请求事件
    // 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
    self.addEventListener("fetch", e => {
      e.respondWith(
        caches.match(e.request).then(function(response) {
          if (response) {
            return response;
          }
          console.log("fetch source");
        })
      );
    });

    打开页面,可以在开发者工具中的 Application 看到 Service Worker 已经启动了

    在 Cache 中也可以发现我们所需的文件已被缓存

    当我们重新刷新页面可以发现我们缓存的数据是从 Service Worker 中读取的

    渲染机制

    浏览器的渲染机制一般分为以下几个步骤

    1. 处理 HTML 并构建 DOM 树。
    2. 处理 CSS 构建 CSSOM 树。
    3. 将 DOM 与 CSSOM 合并成一个渲染树。
    4. 根据渲染树来布局,计算每个节点的位置。
    5. 调用 GPU 绘制,合成图层,显示在屏幕上。

    在构建 CSSOM 树时,会阻塞渲染,直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选择器,执行速度越慢。

    当 HTML 解析到 script 标签时,会暂停构建 DOM,完成后才会从暂停的地方重新开始。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件。并且 CSS 也会影响 JS 的执行,只有当解析完样式表才会执行 JS,所以也可以认为这种情况下,CSS 也会暂停构建 DOM。

    Load 和 DOMContentLoaded 区别

    Load 事件触发代表页面中的 DOM,CSS,JS,图片已经全部加载完毕。

    DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载。

    图层

    一般来说,可以把普通文档流看成一个图层。特定的属性可以生成一个新的图层。不同的图层渲染互不影响,所以对于某些频繁需要渲染的建议单独生成一个新图层,提高性能。但也不能生成过多的图层,会引起反作用。

    通过以下几个常用属性可以生成新图层

    • 3D 变换:translate3dtranslateZ
    • will-change
    • videoiframe 标签
    • 通过动画实现的 opacity 动画转换
    • position: fixed

    重绘(Repaint)和回流(Reflow)

    重绘和回流是渲染步骤中的一小节,但是这两个步骤对于性能影响很大。

    • 重绘是当节点需要更改外观而不会影响布局的,比如改变 color 就叫称为重绘
    • 回流是布局或者几何属性需要改变就称为回流。

    回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。

    所以以下几个动作可能会导致性能问题:

    • 改变 window 大小
    • 改变字体
    • 添加或删除样式
    • 文字改变
    • 定位或者浮动
    • 盒模型

    很多人不知道的是,重绘和回流其实和 Event loop 有关。

    1. 当 Event loop 执行完 Microtasks 后,会判断 document 是否需要更新。因为浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
    2. 然后判断是否有 resize 或者 scroll ,有的话会去触发事件,所以 resizescroll 事件也是至少 16ms 才会触发一次,并且自带节流功能。
    3. 判断是否触发了 media query
    4. 更新动画并且发送事件
    5. 判断是否有全屏操作事件
    6. 执行 requestAnimationFrame 回调
    7. 执行 IntersectionObserver 回调,该方法用于判断元素是否可见,可以用于懒加载上,但是兼容性不好
    8. 更新界面
    9. 以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行 requestIdleCallback 回调。

    以上内容来自于 HTML 文档

    减少重绘和回流

    • 使用 translate 替代 top

      <div class="test"></div>
      <style>
          .test {
              position: absolute;
              top: 10px;
              width: 100px;
              height: 100px;
              background: red;
          }
      </style>
      <script>
          setTimeout(() => {
              // 引起回流
              document.querySelector('.test').style.top = '100px'
          }, 1000)
      </script>
    • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)
    • 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改100次,然后再把它显示出来
    • 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量

      for(let i = 0; i < 1000; i++) {
          // 获取 offsetTop 会导致回流,因为需要去获取正确的值
          console.log(document.querySelector('.test').style.offsetTop)
      }
    • 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
    • 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrame
    • CSS 选择符从右往左匹配查找,避免 DOM 深度过深
    • 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video 标签,浏览器会自动将该节点变为图层。

    文章来源:
    https://github.com/InterviewMap/CS-Interview-Knowledge-Map/blob/master/Browser/browser-ch.md

    查看原文

    赞 68 收藏 54 评论 0

    jacktown 回答了问题 · 2019-01-25

    怎么解决React项目"多余"的&&?

    定义一个对象,用方括号访问应该可以:

    let o = {
    'name1': (...),
    'name2': (...),
    ...
    };
    o[obj.type]
    

    关注 4 回答 3

    jacktown 回答了问题 · 2019-01-12

    解决vue中list循环v-for内部根据不同状态显示,切换比较频繁,使用v-if还是v-show?

    最好使用计算属性进行过滤,可以参考官方文档:避免 v-if 和 v-for 用在一起

    关注 2 回答 1

    jacktown 回答了问题 · 2019-01-10

    vscode 有没有办法生成js的循环代码?

    安几个代码片段插件就好了

    图片描述

    关注 2 回答 1

    jacktown 回答了问题 · 2019-01-10

    解决两个盒子分别监听scroll事件的问题

    写了一个 demojs代码如下:

    let left = document.getElementById('left'),
        right = document.getElementById('right');
    
    // 每次触发滚动事件时标记上相应元素的激活状态,50毫秒后清除
    // 这50毫秒内,另一个元素的滚动事件不会被真正执行
    // 同时,如果这50毫秒内该元素再次触发了滚动事件,那么将状态清除函数的执行时间继续往后推迟
    
    let isLeftActive = false,
        isRightActive = false,
        timerId = null;
    left.addEventListener('scroll', (e)=>{
      if(!isRightActive){
        isLeftActive = true;
        right.scrollTop = e.target.scrollTop; 
        clearTimeout(timerId);
        timerId = setTimeout(
          () => isLeftActive = false,
          50
        );
      }
    });
    right.addEventListener('scroll', (e) => {
      if(!isLeftActive){
        isRightActive = true;
        left.scrollTop = e.target.scrollTop;
        clearTimeout(timerId);
        timerId = setTimeout(
          () => isRightActive = false, 
          50
        );
      }
    });
    

    关注 6 回答 4

    jacktown 回答了问题 · 2019-01-10

    解决正则的一些问题js?

    图片描述

    参考:《 javascript 高级程序设计》中文第三版,P103

    关注 4 回答 3

    jacktown 回答了问题 · 2019-01-03

    解决Java的SimpleDateFormat的解析问题

    看样子,它好像认为这是符合规范的输入了,63 = 5 * 12 + 3

    也许你可以看看有没有更严格的格式规范方法

    关注 3 回答 3

    认证与成就

    • 获得 30 次点赞
    • 获得 16 枚徽章 获得 1 枚金徽章, 获得 2 枚银徽章, 获得 13 枚铜徽章

    擅长技能
    编辑

    开源项目 & 著作
    编辑

    (゚∀゚ )
    暂时没有

    注册于 2017-07-10
    个人主页被 627 人浏览