HTML
HTML5新增了哪些内容或API,使用过哪些
语义
,连通性
,离线存储
,多媒体
,2D/3D 绘图和效果
,性能集成
,设备访问 Device Access
,样式设计
HTML5修改的目标:
- 将互联网语义化
- 提供更好地支持各种媒体的嵌入
新增应用程序接口API
- HTML Geolocation - 地理位置
- HTML Drag and Drop - 拖放
- HTML Local Storage - (本地存储)
- HTML Application Cache - 应用程序缓存
- HTML Web Workers - Web Workers
- HTML Canvas/WebGL - Canvas WebGL
- HTML Audio/Video - Audio Video
元素与属性
- 文件类型声明:
。
- 新的解析顺序:不再基于SGML解析。
- 新增常用元素:
section
(写文章的时候会经常用到,w3school中说:文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。),video/audio
,nav
,aside
,canvas
,footer
,header
,mark
(标记高亮)新增标签MDN - input元素的新type:
date
,email
,url
- 新的属性: charset(用于meta), async(用于script)
- 新的全域属性:
contenteditable
(元素是否可被用户编辑),contextmenu
(上下文菜单是指在用户交互(例如右键点击)时出现的菜单),draggable
(用于标识元素是否允许使用 拖放操作API 拖动),dropzone
,hidden
,spellcheck
input和textarea的区别
input
- 需要
type
值 - value属性指定初始值,maxlength属性指定输入最长的长度,size属性指定显示字符长度
- 宽高只能通过CSS样式指定
textarea
- 使用标签对,且内容在标签对中:
- 使用row、col指定大小
区别:input单行文本框, textarea多行文本框
移动设备忽略将页面中的数字识别为电话号码的方法
设置mate
doctype的作用是什么
激活不同浏览器渲染模式
label的标签的作用是
属性: for
和accesskey
for的作用:为哪个控件服务.
accesskey的作用:访问这个控件的热键.
作用:用户界面中项目的标题
png8、24的区别是
根本区别:存储方式不同.
png8有1位的布尔透明通道(要么完全透明,要么完全不透明)
png24有8位(256阶)的布尔透明通道(半透明)
特点:
png8和gif又一些相似之处,模式都是索引颜色,只支持像素级的纯透明,不支持alpha透明。
"IE6 不支持PNG透明",是指不支持PNG-24的透明,但是IE6支持PNG8的透明,就像支持gif的透明一样。
请说下移动端常见的适配不同屏幕大小的方法
- Rem布局
- 流式布局
- Felx布局
移动端布局
移动端H5页面适配问题研究
移动web适配利器-rem
html标签语义化的好处
- 利于SEO优化。
- 在样式丢失的时候,还可以比较好的呈现结构。
- 更好的支持各种终端,例如无障碍阅读和有声小说等。
- 利于团队开发和维护,遵循W3C规范,减少代码差异,提高效率。
页面DOM节点太多,会出现什么问题?如何优化?
问题:
页面卡顿,帧率下降
优化:
- 采用Virtual DOM, virtual-dom
- 多次操作DOM,改为批量一次操作DOM
- 及时移走页面不用的DOM
- 避免不必要的DIV嵌套
页面的渲染过程
- 解析整个HTML,得到DOM树和样式树
- DOM树和样式树,经过渲染,得到一棵渲染树
- 根据渲染树,开始布局,计算各个节点宽度,位置,高度等。
- 然后开始绘制整个页面并显示
- 在渲染过程中如果使用GPU,还可以进行GPU渲染
高性能DOM
一个网站,在页面上承载最多的内容就是DOM。而且无论是通过加载JS,加载Image,也都是通过HTML标签来实现的。
DOM性能优化:
- 站点的网络消耗
- DOM初始化过程(浏览器)
- DOM结构以及动态操作(人为)
- JS执行过程(浏览器 - V8)
- JS逻辑组织(人为)
站点的网络消耗基本上没法控制,复杂的网络,在一个下行的终端实际上选择不了会接触什么样的网络环境。
DOM的初始化过程无法控制,浏览器内部有DOM解析引擎,它的解析快慢改变不了。
DOM的操作以及动态操作,一个页面的DOM结构是在制作页面的时候定义下来的,可以采用各种方式,比如:多层嵌套,底层嵌套,绝对定位,相对定位。
动态操作就是DOM在运行到一定阶段之后发生。
JS执行过程跟浏览器内核相关,依靠JS引擎执行。它的执行快慢无法改变,能够优化的是JS逻辑组织部分。
回流Reflow:对于DOM结构的各个元素都有自己的盒子模型,这些都需要浏览器根据各个样式(浏览器的默认,开发人员定义的)来计算,并根据计算结果将元素放到它该出现的位置
重绘Repaint:当各个盒子的位置,大小以及其它属性,例如:颜色,字体大小等都确定下来后,浏览器于是便把这些元素都按照各自的特性绘制一遍,于是页面的内容出现了。
什么情况触发回流或者重绘?
DOM元素的添加,修改(内容),删除(回流+重绘),仅修改DOM的元素的字体颜色(只有重绘,因此不需要调整布局),回流一定会触发重绘,但是重绘不一定触发回流
避免触发回流和重绘,提高DOM的性能:display
的值会影响布局,从而影响整个页面元素的位置发生变化,所以会更改DOM-Tree
,需要重新render-Tree
的结构,先将元素从document
中删除,完成修改后再把元素放回原来的位置,如果需要创建多个DOM结构,可以使用documentFragment
创建完成后一次性添加到document
资料
CSS
左右布局:左边定宽、右边自适应,不少于3种方法
absolute + padding
left
right
flex
left
right
float
left
right
CSS3用过哪些新特性
- Selector
-
@font-face
字体 -
border-radius
圆角 -
box-shadow
text-shadow
文本和框的阴影 -
Word-wrap
样式 -
多列布局(multi-column layout)
-
transform
转换2D 转换 rotate 旋转,图片转个90或180度 translate 位置移动 scale, skew, matrix 等 3D 转换 rotate(XYZ) 根据x,y,z轴旋转 translate(XYZ), scale(XYZ) perspective 透视, 景深,这个很多3D效果都要设置一下,不然3D还是会”2D”的效果
-
transition
: 过渡,好多简单的动画,移个位置,变个长短. -
animation
: 动画,3D可以调用硬件渲染。 -
@media
媒体查询,适用于一些响应式布局中 -
flex
: flex布局,cssreference -
word-wrap
,background-size
,background-origin
,border-image
,box-sizing
,calc
,linear-gradient
,radial-gradient
-
will-change
: 改善渲染性能,使用CSS3 will-change提高页面滚动、动画等渲染性能
BFC、IFC
盒模型布局的CSS渲染模式
BFC:Black Formatting Context
,块级格式上下文。 BFC表现原则:内部子元素再怎么折腾,都不会影响外部的元素,自成一方天地.
深入理解BFC
BFC形成(一条或多条都可以形成BFC):
- float 的值不为 none
- position 的值不为 static 或 relative
- display属性为inline-boxs、table-cells、table-captions的不是块盒的块容器(除非这个值已经被传播到视口),
- overflow不为visible的块盒才会为它的内容创建新的BFC。
- body元素
IFC:Inline Formatting Context
, 直译"内联格式化上下文",理解成行内盒子模型. 高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)
对栅格的理解
基础就是float
和 width:百分比
以规则的网格阵列来规范网页中的版面布局以及信息分布。
盒子模型 加了box-sizing 之后怎样
- IE5.x 以及Quirks(怪异)模式的IE6,IE7中,border和padding都包含在width和height中。
- 标准浏览器中width和height仅仅包含content, 不包含border和padding。
- CSS3定义了box-sizing属性:box-sizing: content-box | border-box | inherit;
content-box: 该属性维持CSS2.1盒模型的组成方式。border-box:该属性将重新定义CSS2.1盒模型组成模式(与IE6解析相同)
样式权重的排序
!important > id > class > tag[name=val] > tag
display有哪些属性值,有什么作用?
- none:元素不会显示,而且改变元素现实的空间也不会保留
- inline:将元素显示为内联元素,元素前后没有换行符
- block:将元素显示为块级元素,元素前后会带有换行符
- inline-block:行内块元素
- list-item:此元素会作为列表显示
- table: 会作为会计表格来显示(类似table),表格前后带有换行符.
- inherit: 应该从父级继承display属性的值
- box: 弹性盒子模型(CSS3新增)
- flex: flex布局(CSS3新增)
- grid: 栅格盒模型值(CSS3新增)
1像素边框问题
原因:由于移动端一般都会设置视口(屏幕宽度为设备宽度),width=device-width,initial-scale=1
,而有些屏幕是2倍屏,导致在移动端上设置1px就是看上去的2px
解决方法:
- 通过
transform
将宽度缩小一半,transform:scaleY(0.5) - 通过@media媒体查询,查询当前设置的屏幕倍率,统一设置transform 移动端(手机)1像素边框真正实现
-
模仿淘宝的设置,将屏幕宽度为设计师的设计尺寸(一般为750)。
-
动态设置content
(function(e){if(!e["_med"])e["_med"]={};var t=e["_med"];t.cookie=function(e,t,a){if(t!==undefined){a=a||{};if(typeof a.expires==="number"){var o=a.expires,l=a.expires=new Date;l.setTime(+l+o*864e5)}return document.cookie=[e,"=",String(t),a.expires?"; expires="+a.expires.toUTCString():"",a.path?"; path="+a.path:"",a.domain?"; domain="+a.domain:"",a.secure?"; secure":""].join("")}var r=e?undefined:{};var i=document.cookie?document.cookie.split("; "):[];for(var n=0,s=i.length;n
(水平)居中有哪些实现方式
-
margin
margintext-align
text-alignposition+transform
transformflex
flextable+margin
table + margin移动端的常见问题
- 点透事件 zepto的tap事件的点透问题的几种解决方案
- 长时间按住页面出现闪退问题
- 旋转屏幕时,字体调整问题
- 上下拉动滚动条时卡顿,慢的问题
长时间按住页面出现闪退问题
element { -webkit-touch-callout: none; }
上下拉动滚动条时卡顿,慢的问题
body { -webkit-overflow-scrolling: touch; overflow-scrolling: touch; }
旋转时字体大小调整
/* 旋转屏幕时,字体大小调整的问题 */ html, body, p, div { -webkit-text-size-adjust:100%; }
忽略页面中的电话号码
资料
JavaScript
跨域解决方式
JSONP
,domain
,window.name
,ifrome
,反向代理(nginx)
什么是闭包?闭包有什么作用?
闭包:函数里面套函数,外层函数无法访问里面函数中的变量,里面函数可以访问外层函数中的私有变量。
作用:防止全局变量如何实现浏览器内多个标签之间的通信
localStorage
,cookie
HTML5的存储方式有哪些?有何区别?
存储方式:
localStorage
,sessionStorage
区别:存储时间不一样,localStorage
本地永久存储,sessionStroage页面关闭,ctrl+f5存储的值清空(f5刷新值存在).内存溢出
- 请求数据过大
- 死循环
- 引用对象,使用完不释放
- 全局变量过多
表现:
- 意外的全局变量
- 被遗忘的计时器或回调函数
- 脱离 DOM 的引用
- 闭包
图片懒加载
原理:访问一个页面的时候,把
img
或者background
相关属性的加载默认图(或者其它节约资源的图片),当图片在可可视区域内时,才设置图片的真正路径.优点:减轻服务器的压力,用户体验好(加载好的页面更快呈现在用户面前)
function elementInViewport(el) { var rect = el.getBoundingClientRect() // For invisible element. if (rect.top + rect.bottom + rect.left + rect.right + rect.height + rect.width === 0) { return false; } return ( rect.top >= 0 // Pre load. && rect.top <= ((window.innerHeight || document.documentElement.clientHeight) + 100) && rect.left >= 0 // Hide carousel except the first image. Do not add equal sign. && rect.left < (window.innerWidth || document.documentElement.clientWidth) ) }
实现页面加载进度条
实现插件:PACE
- AJAX (监控所有AJAX请求)
- Elements (检查页面上的特定元素存在)
- Document (document 的
readyState
事件) - Event Lag (检查正在执行JavaScript的事件循环)
事件委托
利用
事件冒泡
和e.target
来确定事件和元素。在jQuery中有$.delegate
方法去代理事件。事件委托原理:
- 需要绑定事件的元素很多,且处理逻辑类似。
- 元素都是动态创建,或频繁增加,删除,导致元素绑定事件过于复杂。
// https://github.com/zenorocha/delegate/blob/master/src/delegate.js const delegate = (element, selector, type, callback) => { element.addEventListener(type, (e) => { let target = e.path.find(ele => ele.matches(selector)) if (target) { callback.call(element, e); } }); };
实现 extend 函数
浅拷贝使用ES6的
Object.assign()
深拷贝:zepto extend直接克隆一个
Nested Object
的简便方法:var origin = {a: 'a'} var copy = JSON.parse(JSON.stringify(origin));
为什么会有跨域的问题以及解决方式
前端解决跨域问题的8种方案, HTTP访问控制(CORS),浏览器的同源策略
产生原因:
- 处于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求。 例如,
XMLHttpRequset
和Fetch
都需要遵循同源策略 - 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。 这是一个用于隔离潜在恶意文件的关键的安全机制。
解决方式:
- JSONP(JSON with Padding): 利用加载 JS 文件不需要遵循同源策略的原理。
- CORS(Cross-Origin Resource Sharing): 在服务器端返回允许跨域访问的头。
- WebSockt:利用 WebSocket 不需要遵循同源策略的原理。
JSONP原理、postMessage原理
can-anyone-explain-what-jsonp-is-in-layman-terms
JSONP 原理:加载一个 script,并执行一段回调 JS ,因为加载 JS 不需要遵循同源策略。
- 无法发送特定的头部
- 只能是GET请求
- 无法发送 body
动画:setTimeout何时执行,requestAnimationFrame的优点
setTimeout 何时执行:
tasks-microtasks-queues-and-schedules
requestAnimationFrame的优点
window.requestAnimationFrame()
方法告知浏览器执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画。该方法将在重绘之前调用的回调作为参数。优点:
- 在浏览器重绘前调用,保证浏览器渲染效率和性能
- 可以精准地控制动画的每一帧
主要在游戏,动画方面使用。用这个方法可以保持较高帧频率和效率。 比如一个60帧率的动画,
requestAnimationFrame
一般会以16ms的间隔调用一次手写parseInt的实现:要求简单一些,把字符串型的数字转化为真正的数字即可,但不能使用JS原生的字符串转数字的API,比如Number()
const parseInt = str => str - 0; const parseInt = str => str / 1; const parseInt = str => str * 1; const parseInt = str => +str;
复杂写法:
const parseInt = str => { let n = 0; let i = 1; str.split('').reverse().map(s => { n += i * (s.charCodeAt(0) - 48); i *= 10; }); return n; }
编写分页器组件的时候,点击“下一页”怎样能确保还有数据可以加载(请求数据不会为空)?
服务器需要返回总数,当前偏移量,根据总数和偏移量判断是否是最后一页。
ES6新增了哪些特性
require.js的实现原理(如果使用过webpack,进一步会问,两者打包的异同及优缺点)
相同点:都以模块化方式组织代码
不同点:- requirejs 只能加载JS文件
- webpack 可以打包JS,CSS,甚至是图片
promise的实现原理,进一步会问async、await是否使用过
使用框架 ( vue / react 等)带来好处( 相对jQuery )
- MVVC架构,数据驱动视图,数据绑定,减少DOM操作。
- 组件化组织页面,效率更高,维护更简便。
-
Virtual Dom
带来性能上的提升 - 路由控制,单页应用更为简便
vue双向数据绑定的实现
实现双向数据绑定的关键是
Observer
. 即用户改变了数据,框架如何知晓,并及时更新视图。Observer
实现包括:
参考:observerObject.defineProperty
var obj = {} Object.defineProperty(obj, 'key', { enumerable: true, set(x) { console.log(`set key: ${x}`); obj.__ob__ = obj.__ob__ || {}; obj.__ob__.key = x; }, get() { return obj.__ob__.key; } }) obj.key = 'value'; /** * 输出: * set key: value */
Proxy
var ele = { data: null }; var handler = { get: function(target, key) { if (typeof target[key] === 'object' && target[key] !== null) { return new Proxy(target[key], handler) } else { return target[key]; } }, set: function(target, key, value) { console.log('set ' + key) target[key] = value; return value; } } ele = new Proxy(ele, handler); ele.data = {a: 'a', b: {bb: 'bb'}} ele.data.a = 'aa'; ele.data.b.bb = 'bb1'; ele.data.c = 'cc'; /* * 输出: * set data * set a * set bb * set c */
其他的数据操作,如:数组的push等,只需要在原生上加Hook就行了
var arr = []; var __push = Array.prototype.push; Array.prototype.push = function (...items) { console.log(`push: ${items}`); return __push.apply(this, items); } arr.push('value') /** * 输出: * push: value */
从视图反向把数据流过来,稍微简单些,只需要记录对应的key值,然后在输入框触发change, keypress事件的时候,更新对应key的数据即可。
单页应用,如何实现其路由功能
Hash
// https://github.com/zhoukekestar/modules/blob/master/src/views/views.js window.addEventListener('hashchange', () => { // 隐藏其他页面 Array.from(document.querySelectorAll('.page')).map(page => { page.style.display = 'none'; }); // 根据hash值显示对应的页面 document.querySelector(location.hash).style.display = 'block'; });
使用HASH实现的简单路由 测试:在线测试
History
// https://github.com/zhoukekestar/modules/blob/master/src/loadpage/loadpage.js // push 页面 history.pushState('', '', url); // pop 页面 window.onpopstate = (e) => { };
使用History实现的简单路由,在线测试
项目中使用过哪些优化方法
- 页面静态化,(Pug在静态编译后部署)
-
CDN
加速, 多地缓存 -
前端渲染 (Data + View) / 后端渲染( SSR, SEO 等), 视具体情况选择,如:
前端渲染,适合大流量的场景 后端渲染,适合SEO优化,用户体验提升等场景
-
缩减域名,以减少DNS解析时间,(可采用
进行优化)
如果遇到域名解析的问题,可尝试HTTPDNS方案
- Combo服务器合并CSS,JS请求, 减少第一屏网络请求。(如果采用HTTP2.0方案,资源合并可省略)
- 异步加载非核心业务和逻辑资源
-
资源和请求缓存,可参考缓存的答案
Cache-Control/Expires 前端缓存 Last-Modified/Etag 服务器端缓存,304
- 如果是和Native混合开发的,还可以使用Native缓存
- DNS就近解析应用服务器,需要和CDN配合使用
资料
网络
静态资源或者接口等如何做缓存优化
-
redis
/memcache
做数据缓存 - SQL 查询做缓存
- 指定 Cache-Control/Expires 缓存时间
- Last-Modified/Etag 缓存 ( 304 ) 方案
- 网关服务器做缓存,需要更新时,再回源到应用服务器
- CDN多机房,多网关缓存
输入一个URL,Enter之后发生了什么
具体步骤:
- 把URL地址通过DNS解析为具体的服务器主机
- 浏览器封装HTTP请求 (window.navigator.userAgent)
- 浏览器创建与服务器的TCP连接
- 浏览器发出HTTP请求
- 服务器收到请求后交给相应的进程处理
- 服务器把处理后的结果发送给浏览器
- 浏览器生成渲染树和DOM树渲染页面
- 浏览器处理页面中嵌入的资源和异步请求
-
浏览器解析URL,如:
https://www.google.co.jp/?gfe_rd=cr&ei=NPJtWZTXJabEXoKjqOAP&gws_rd=ssl
包括协议:`http`,`https`等 域名:`www.google.co.jp` 资源路径:`/` 参数查询:`gfe_rd=cr`,关键词`cr`
-
DNS
浏览器DNS缓存 HOSTS查询 DNS服务器查询 ARP查询
- TCP握手,TLS握手
-
HTTP(s),(或SPDY,或HTTP2.0)
Header Domain Body
-
Gateway/Nginx,网关和负载均衡服务器
查询本地缓存 请求上游应用服务器
-
浏览器解析HTML,并请求资源
CSS JS 图片
- 生成DOM-Tree,结合CSS进行渲染
更为完整详细:what-happens-when-zh_CN
前端的安全
前端的安全问题有哪些,如何解决
- sql注入
- shell注入
- xss
- csrf
- 对数据加密
- 对关键字进行处理
sql注入
思路:发现SQL注入位置(URL地址和Input输入框),判断服务器类型和后台数据库类型.
解决方法:
URL地址防注入
// 过滤URL非法SQL字符 var sUrl = location.search.toLowerCase(); var sQuery = sUrl.substring(sUrl.indexOf('=') + 1); // 获取查询参数key // SQL关键字 reg = /select|update|delete|truncate|join|union|exec|insert|drop|count|'|"|;|>|<|%/i; if (reg.test(sQuery)) { console.log('输入非法字符'); location.href = sUrl.replace(sQuery, ''); // 重新跳转 }
输入文本框防注入
// 防止SQL注入 function AntiSqlValid(context) { reg = /select|update|delete|truncate|join|union|exec|insert|drop|count|'|"|;|>|<|%/i; if (reg.test(context.value)) { // 提示信息,其它操作 } return; }
shell注入
常见的Shell注入资源有
system()
,StartProcess()
,java.lang.Runtime.exec()
,System.Diagnostics.Process.Start()
以及类似的应用程序接口在请求地址上置换用户提交的许多其他单字。
处理特殊字符:
$
,;
,|
,&&
,||
,>
,<
XSS
英语:Cross-site scripting
,通常简称为:XSS
网站应用程序的安全漏洞攻击,是代码注入的一种.造成的结果:可能得到更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
检测方法
测试网站是否有正确处理特殊字符>
='>
">
涉及到的知识:HTTP,Cookie,Ajax等。
XSS原理:
XSS:JavaScript代码
DDOS
Server Limit DOS: HTTP头超长,导致域名无法访问。- 获取Cookie中的信息
- 破坏正常的页面结构,插入恶意内容
XSS类型:
-
反射型
发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码。该过程像一次反射,称之为:反射型XSS
-
存储型
存储型XSS和放射型XSS的差别仅在于,提交的代码会存储在服务器端(数据库,内存,文件系统等),下次请求目标页面时不用再提交XSS代码
响应头:
// express框架 res.set('X-XSS-Protection', 0) // 默认是浏览器拦截,设置为0之后,XSS代码就生效
XSS预防措施:
-
编码
对用户输入的数据进行HTML Entity编码
-
过滤
移除用户上传的DOM属性,如onerror,与事件相关等 移除用户上传的Style节点,Script节点,Iframe节点等
-
校正
避免直接对HTML Entity解码 使用DOM Parse转换,校正不配对的DOM标签
csrf
中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
理解成:攻击者盗用了你的身份,以你的名义发送恶意请求.
CSRF攻击是源于WEB的隐式身份验证机制。WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户发送的。CSRF的前端防御:
在每次POST,GET请求时,添加X-CSRFToken请求头。
- 用户操作限制,比如验证码;
- 请求来源限制,比如限制HTTP Referer才能完成操作;
- token验证机制,比如请求数据字段中添加一个token,响应请求时校验其有效性;
npm
暂时指定代理
// npm install mongoose --registry 内网ip npm install mongoose --registry http://172.18.0.199
永久指定代理
// npm config set registry 内网ip npm config set registry "http://172.18.0.199"
使用nrm动态切换代理
npm install -g nrm
测试代理最快
nrm test