题目概览
- 对HTML5的拖放API的理解
- 手动写动画最小时间间隔是多少
- 对HTML5的
WebWork
的理解 - 对同构和SSR的理解
题目解答
对HTML5的拖放API的理解
-
图片默认自带拖拽功能,非图片元素设置draggable属性为true即可拖拽。
-
被拖拽元素的事件:
- ondragstart 拖拽的一瞬间触发
- ondrag 拖拽期间连续触发
- ondragend 拖拽结束触发
-
目标元素事件(将拖拽元素释放的地方):
- ondragenter 进入目标元素触发(鼠标光标进入)
- ondragover 进入离开目标元素连续触发
- ondragleave 离开目标元素触发
- ondrop 在目标元素上释放鼠标触发
-
默认状态下,一个元素不能放在另一个元素上面,需要在ondragover上阻止默认事件
<div class="box" draggable="true"></div> <div class="container"></div> <script> let box = document.querySelector(".box"); let container = document.querySelector(".container"); // 移动元素 box.addEventListener("dragstart", function (e) { console.log("我要移动了") e.dataTransfer.setData("box", e.target.className); }) // 目标元素 container.addEventListener("dragenter", function () { console.log("你每次进入我这里都会触发"); }) container.addEventListener("dragover", function (e) { // 要阻止浏览器默认行为,不然触发不了了下面的drop事件 e.preventDefault(); console.log("你每次在我里面都会不停地触发"); }) // drop 要阻止dragover才能触发 container.addEventListener('drop', function (e) { console.log("在我里面松开鼠标就会触发"); var data = e.dataTransfer.getData("box"); e.target.appendChild(document.getElementsByClassName(data)[0]); }) container.addEventListener("dragleave", function () { console.log("你离开我的时候就会触发"); }) </script>
手动写动画最小时间间隔是多少
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms
对HTML5的WebWork的理解
-
背景:Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了。一个浏览器至少存在三个线程:js引擎线程(处理js)、GUI渲染线程(渲染页面)、浏览器事件触发线程(控制交互)。
-
JavaScript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来然后加以处理,浏览器无论再什么时候都只有一个JS线程在运行JS程序。
-
GUI 渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
-
事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。
了解了浏览器的内核处理方式就不难理解浏览器为什么会进入假死状态了,当一段JS脚本长时间占用着处理机就会挂起浏览器的GUI更新,而后面的事件响应也被排在队列中得不到处理,从而造成了浏览器被锁定进入假死状态。另外JS脚本中进行了DOM操作,一旦JS调用结束就会马上进行一次GUI渲染,然后才开始执行下一个任务,所以JS中大量的DOM操作也会导致事件响应缓慢甚至真正卡死浏览器,如在IE6下一次插入大量的HTML。而如果真的弹出了“脚本运行时间过长“的提示框则说明你的JS脚本肯定有死循环或者进行过深的递归操作了。现在如果遇到了这种情况,我们可以做的不仅仅是优化代码,html5的webWorkers提供了js的后台处理线程的API,它允许将复杂耗时的单纯js逻辑处理放在浏览器后台线程中进行处理,让js线程不阻塞UI线程的渲染。这个线程不能和页面进行交互,如获取元素、alert等。多个线程间也是可以通过相同的方法进行数据传递
-
-
概念:当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行
-
检测 Web Worker 支持:在创建 web worker 之前,请检测用户的浏览器是否支持它:
if(typeof(Worker)!=="undefined"){ // Yes! Web worker support! // Some code..... }else{ // Sorry! No Web Worker support.. }
-
创建 web worker 文件:在一个外部 JavaScript 中创建 web worker。在这里,创建了计数脚本。该脚本存储于 "demo_workers.js" 文件中
var i=0; function timedCount(){ i=i+1; postMessage(i); setTimeout("timedCount()",500); } timedCount();
-
创建 Web Worker 对象:已经有了 web worker 文件,现在需要从 HTML 页面调用它。下面的代码检测是否存在 worker,如果不存在,- 它会创建一个新的 web worker 对象,然后运行 "demo_workers.js" 中的代码:
if(typeof(w)=="undefined"){ w=new Worker("demo_workers.js"); }
然后就可以从 web worker 发生和接收消息了。向 web worker 添加一个 "onmessage" 事件监听器:
w.onmessage=function(event){ document.getElementById("result").innerHTML=event.data; };
当 web worker 传递消息时,会执行事件监听器中的代码。event.data 中存有来自 event.data 的数据。
-
终止 Web Worker:当创建 web worker 对象后,它会继续监听消息(即使在外部脚本完成之后)直到其被终止为止。
如需终止 web worker,并释放浏览器/计算机资源,请使用 terminate() 方法
w.terminate();
对同构和SSR的理解
- Isomorphism, 同构,指一套代码既可以在server端工作,也可以在web 客户端运行,可以无缝在server端和client端渲染两种模式间切换。
- 因为HTML/CSS/JS本质就是可被浏览器解析并执行的字符串,所以服务端渲染的本质是在服务端将业务逻辑处理,将站点的代码和结构加工完成,将成品的字符串返回,这就是 SSR 服务端渲染。服务端渲染的优势很明显,因为在服务端完成了逻辑和业务,所以减少了请求,不需要先下载一堆 js 和 css 后才能看到页面,对首屏性能提升很大。