HTML
1、你是如何理解web语义化的?
Web语义化是指使用恰当语义的html标签、class类名等内容,让页面具有良好的结构与含义,从而让人和机器都能快速理解网页内容。语义化的web页面一方面可以让机器在更快读懂网页的内容,然后将收集汇总的信息进行分析,结果为人类所用;另一方面它可以让开发人员读懂结构和用户以及屏幕阅读器(如果访客有视障)能够读懂内容。 简单来说就是利于 SEO,便于阅读维护理解。
总结起来就是:
正确的标签做正确的事情
页面内容结构化
无CSS样子时也容易阅读,便于阅读维护和理解
便于浏览器、搜索引擎解析。 利于爬虫标记、利于SEO
HTML语义化让机器读懂网页内容,CSS语义化是让人读懂网页内容。
HTML语义化
对于HTML体系而言,Web语义化是指使用语义恰当的标签,使页面有良好的结构,让页面元素有含义,便于被浏览器、搜索引擎解析、利于SEO。
HTML语义化是反对大篇幅使用无语义化的div+span+class,而鼓励使用HTML定义好的语义化标签。
比如用
你好,我是这边文章的标题
你好,我是文章的内容
CSS语义化
CSS语义就是class和ID命名的语义。指用易于理解的名称对html标签附加的class或id命名。如果说HTML语义化标签是给机器看的,那么CSS命名的语义化就是给人看的。
URL语义化
url语义化,可以使得搜索引擎或者爬虫更好地理解当前url所在目录所需要表达的内容;而对于用户来说,通过url也可以判断上一级目录或者下一级目录想要表示的内容,可以提高用户体验。
https://mall.midea.com/index.php/category?id=10049&addr_code=440000,440100,440103
https://mall.midea.com/category?id=10049&addr_code=440000,440100,440103
这两个url指向的是同一个资源,但是显然第二个url对于用户和搜索引擎更加友好。
url语义化可以从以下标准来衡量:
- url简化,规范化:url里的名词如果包含两个单词,那么就用下划线_ 连接。
- 结构化,语义化:此处的品类搜索我们用语义化单词category表示
- 采用技术无关的url:第一个链接中的index.php这种就不应该出现在用户侧的url里。
参考链接:https://juejin.im/entry/5ab5f229518825558a069304
meta viewport 是做什么用的,怎么写?
这段代码的意思是,让viewport的宽度等于物理设备上的真实分辨率,不允许用户缩放。
width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
maximum-scale:允许用户缩放到的最大比例。
minimum-scale:允许用户缩放到的最小比例。
user-scalable:用户是否可以手动缩放
click在ios上有300ms延迟,原因及如何解决?
(1)粗暴型,禁用缩放
(2)利用FastClick,其原理是:
检测到touchend事件后,立刻出发模拟click事件,并且把浏览器300毫秒之后真正出发的事件给阻断掉
你用过哪些 HTML 5 标签?
参考:https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/HTML5/HTML5_element_list
首先html5为了更好的实践web语义化,增加了header,footer,nav,aside,section等语义化标签,在表单方面,为了增强表单,为input增加了color,emial,data ,range等类型,在存储方面,提供了sessionStorage,localStorage,和离线存储(已废弃),通过这些存储方式方便数据在客户端的存储和获取,在多媒体方面规定了音频和视频元素audio和vedio,另外还有地理定位,canvas画布,拖放,多线程编程的web worker和websocket协议
响应式布局常用解决方案
参考:https://github.com/forthealllight/blog/issues/13
CSS
link标签和@import标签的区别
link属于html标签,而@import是css提供的
页面被加载时,link会同时被加载,而@import引用的css会等到页面加载结束后加载。
link是html标签,因此没有兼容性,而@import只有IE5以上才能识别。
link方式样式的权重高于@import的。
两种盒模型分别说一下
IE模型和标准模型唯一的区别是内容计算方式的不同:
通过css3新增的属性 box-sizing: content-box | border-box分别设置盒模型为标准模型(content-box)和IE模型(border-box)。
.content-box {
box-sizing:content-box;
width: 100px;
height: 50px;
padding: 10px;
border: 5px solid red;
margin: 15px;
}
.border-box {
box-sizing: border-box;
width: 100px;
height: 50px;
padding: 10px;
border: 5px solid red;
margin: 15px;
}
总之:IE模型border-box你在css中width和height设置了多大,这个盒子宽高就有多大,这其中已经包括了padding和border。所以这里盒子的宽度是70+10+10+5+5=100,content+2个padding+2个border
而标准模型content-box你在css中width和height设置的只是content的大小,不包括padding和border。所以这里盒子的宽度是100+10+10+5+5=130,content+2个padding+2个border
就是表示width的方式不一样,标准盒子width表示的就是content,不包括padding和border;IE盒子width表示了整个盒子的宽度,这其中已经包括了padding和border
BFC
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干
BFC规则:
1、内部的Box会在垂直方向,一个接一个地放置。
2、Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
3、每个元素的左外边缘(margin-left), 与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。
4、BFC的区域不会与float box重叠。
5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
6、计算BFC的高度时,浮动元素也参与计算
怎样才能形成BFC
1、根元素或其它包含它的元素
2、浮动 (元素的 float 不是 none)
3、绝对定位的元素 (元素具有 position 为 absolute 或 fixed)
4、非块级元素具有 display: inline-block,table-cell, table-caption, flex, inline-flex
5、块级元素具有overflow ,且值不是 visible
BFC作用
1.清除浮动
1
2
.wrap {
border: 2px solid yellow;
width: 250px;
}
section {
background-color: pink;
float: left;
width: 100px;
height: 100px;
}
可以看到,由于子元素都是浮动的,受浮动影响,边框为黄色的父元素的高度塌陷了。
解决方案:为 .wrap 加上 overflow: hidden;使其形成BFC,根据BFC规则第六条,计算高度时就会计算float的元素的高度,达到清除浮动影响的效果。
2.布局:自适应两栏布局
我是好多好多文字会换行的那种蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤
div {width: 200px;}
aside {
background-color: yellow;
float: left;
width: 100px;
height: 50px;
}
main {
background-color: pink;
}
可以看到右侧元素的一部分跑到了左侧元素下方。
解决方案:为main设置 overflow: hidden; 触发main元素的BFC,根据规则第4、5条,BFC的区域是独立的,不会与页面其他元素相互影响,且不会与float元素重叠,因此就可以形成两列自适应布局
- 防止垂直margin合并(外边距折叠)
1
2
section {
background-color: pink;
margin-bottom: 100px;
width: 100px;
height: 100px;
}
.bottom {
margin-top: 100px;
}
可以看到,明明.top和.bottom中间加起来有200px的margin值,但是我们只能看到100px。这是因为他们的外边距相遇发生了合并。
怎样解决:为其中一个元素的外面包裹一层元素。并为这个外层元素设置 overflow: hidden;,使其形成BFC。因为BFC内部是一个独立的容器,所以不会与外部相互影响,可以防止margin合并。
1
2
.wrap {
overflow: hidden;
}
参考:https://segmentfault.com/a/1190000009545742
https://juejin.im/post/59b73d5bf265da064618731d
css3动画
https://juejin.im/post/5a424a796fb9a045023be66c
清除浮动
.clearfix:after{
content: '';
display: block; /*或者 table*/
clear: both;
}
.clearfix{
zoom: 1; /* IE 兼容*/
}
/* slightly enhanced, universal clearfix hack */
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.clearfix { display: inline-block; }
/* start commented backslash hack \*/
* html .clearfix { height: 1%; }
.clearfix { display: block; }
/* close commented backslash hack */
inline-block、inline和block的区别;为什么img是inline还可以设置宽高
block元素会独占一行,多个block元素会各自新起一行。默认情况下,block元素宽度自动填满其父元素宽度。
block元素可以设置width,height属性。块级元素即使设置了宽度,仍然是独占一行。
block元素可以设置margin和padding属性。
inline元素不会独占一行,多个相邻的行内元素会排列在同一行里,直到一行排列不下,才会新换一行,其宽度随元素的内容而变化。
inline元素设置width,height属性无效。
inline元素的margin和padding属性,水平方向的padding-left, padding-right, margin-left, margin-right都产生边距效果;但竖直方向的padding-top, padding-bottom, margin-top, margin-bottom不会产生边距效果。
inline-block:简单来说就是将对象呈现为inline对象,但是对象的内容作为block对象呈现。之后的内联对象会被排列在同一行内。比如我们可以给一个link(a元素)inline-block属性值,使其既具有block的宽度高度特性又具有inline的同行特性。
垂直居中
一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字一串文字
1、flex
.parent{
height: 600px;
border: 3px solid red;
display: flex;
justify-content: center;
align-items: center;
}
.child{
border: 3px solid green;
width: 300px;
}
2、块级元素知道高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px; /* account for padding and border if not using box-sizing: border-box; */
}
3、块级元素不知道高度
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
4、absolute margin auto
.parent{
height: 600px;
border: 1px solid red;
position: relative;
}
.child{
border: 1px solid green;
position: absolute;
width: 300px;
height: 200px;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
参考:https://css-tricks.com/centering-css-complete-guide/
圣杯布局和双飞翼布局
参考:https://www.jianshu.com/p/81ef7e7094e8
flex怎么用
参考:https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb
CSS 选择器优先级
!impotant>行内样式>id样式>class样式
class样式中最越靠下的优先级越高,和class="i1 i2 i3"这里顺序没关系
JS
ES 6 语法知道哪些,分别怎么用?
https://fangyinghang.com/es-6-tutorials/
https://es6.ruanyifeng.com/#docs/let
DOM
事件级别
DOM0 element.onclick=function(){}
DOM2 element.addEventListener('click',function(){},false)
true:捕获事件 false:冒泡事件
DOM3 element.addEventListener('keyup',function(){},false)
事件委托
简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。
事件模型
捕获和冒泡
事件流
点击一个目标元素,响应的顺序是从window到document到html....最后从到目标元素
时间捕获过程:
var ev = document.getElementById('ev')
window.addEventListener('click', function() {
console.log('windown')
}, true) //true是捕获,false是冒泡
document.addEventListener('click', function() {
console.log('document')
}, true)
document.documentElement.addEventListener('click', function() {
console.log('html')
}, true)
document.body.addEventListener('click', function() {
console.log('body')
}, true)
ev.addEventListener('click', function () {
console.log('ev')
},true)
事件冒泡
当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window ,冒泡过程把上面true改成false
阻止事件冒泡:
function preventBubble(event){
var e=arguments.callee.caller.arguments[0]||event; //若省略此句,下面的e改为event,IE运行可以,但是其他浏览器就不兼容
if (e && e.stopPropagation) {
e.stopPropagation();
} else if (window.event) {
window.event.cancelBubble = true;
}
}
DOM事件类
Event对象常见应用
event.preventDefault() 阻止默认事件
event.stopPropagation 阻止冒泡
event.stopImmediatePropagation() 事件响应优先级,优先触发哪个事件
event.currentTarget 获取到的是发起事件的标签元素
event.target 当前被点击的元素
自定义事件
var eve = new Event('custome');
ev.addEventListener('custome',function(){
console.log('custome');
});
ev.dispatchEvent(eve);
mouseover和mouseenter的区别
mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡的过程。对应的移除事件是mouseout
mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave
JS中的垃圾回收机制
https://segmentfault.com/a/1190000018605776?utm_source=tag-newest
Promise、Promise.all、Promise.race 分别怎么用
Promise用法
function fn(){
return new Promise((resolve, reject)=>{
成功时调用 resolve(数据)
失败时调用 reject(错误)
})
}
fn().then(success, fail).then(success2, fail2)
Promise.all 用法
Promise.all([promise1, promise2]).then(success1, fail1)
promise1和promise2都成功才会调用success1
Promise.race 用法
Promise.race([promise1, promise2]).then(success1, fail1)
promise1和promise2只要有一个成功就会调用success1
函数防抖和函数节流
防抖
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。等于就是动作操作完再执行回调
function debounce(fn, delay) {
let timer; // 维护一个 timer
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments); // 用apply指向调用debounce的对象,相当于this.fn(arguments);
}, delay)
}
}
//测试用例
// test
function testDebounce(e, content) {
console.log(e, content);
}
let testDebounceFn = debounce(testDebounce, 1000); // 防抖函数
document.onmousemove = function (e) {
testDebounceFn(e, 'debounce'); // 给防抖函数传参
}
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
搜索框搜索输入。只需用户最后一次输入完,再发送请求
手机号、邮箱验证输入检测
窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流
每隔一段时间,只执行一次函数。
function throttle(fn, delay) {
let timer;
return function () {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
}, delay)
}
}
//测试用例
function testThrottle(e, content) {
console.log(e, content);
}
let testThrottleFn = throttle(testThrottle, 1000); // 节流函数
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 给节流函数传参
}
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
滚动加载,加载更多或滚到底部监听
谷歌搜索框,搜索联想功能
高频点击提交,表单重复提交
参考:https://segmentfault.com/a/1190000018445196
手写ajax
function ajax(url, successFn){
const xhr= new XMLHttpRequest()
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200) {
successFn(xhr.responseText);
}
}
xhr.send();
}
// 结合Promise
function ajax(url) {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText));
} else if (xhr.status === 404) {
reject(new Error("404 NOT FOUND"));
}
}
}
xhr.send(null)
})
return p
}
这段代码里的 this 是什么
fn()
this => window/global
obj.fn()
this => obj
fn.call(xx)
this => xx
fn.apply(xx)
this => xx
fn.bind(xx)
this => xx
new Fn()
this => 新的对象
fn = ()=> {}
this => 外面的 this
有参数的this就是参数
func(p1, p2) 等价于
func.call(undefined, p1, p2)
调用函数用func.call(context, p1, p2)
里面的context就是this
function func(){
console.log(this)
}
func()
按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:
如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
因此上面的打印结果是 window。
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() // 转换为 obj.foo.call(obj),this 就是 obj
bar()
// 转换为 bar.call()
// 由于没有传 context
// 所以 this 就是 undefined
// 最后浏览器给你一个默认的 this —— window 对象
参考:https://zhuanlan.zhihu.com/p/23804247
闭包
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
闭包就是能够读取其他函数内部变量的函数。
var f1 = (function(){
var n=999;
function f2(){
alert(n);
}
return f2;
})()
f1();//999
var Conf = (function () {
var conf = {
NAME: 'iwen',
AGE: 18
}
return {
get: function (name) {
return conf[name] ? conf[name] : null;
}
}
})();
console.log(Conf.get('NAME'));
var Ftr = (() =>{
var conf = {
NAME: 'iwen',
AGE: 18
}
return {
get: (name) => {
return conf[name] ? conf[name] : null;
}
}
})()
console.log(Ftr.get('NAME'));
立即执行函数
(function(){
alert('这是匿名函数!')
})()
立即执行函数作用就是创建一个独立作用域,不污染全局变量
什么是JSONP,什么是CORS,什么是跨域
同源:协议、域名、端口,三者必须一致
JSONP
请求方:frank.com 的前端程序员(浏览器)
响应方:jack.com 的后端程序员(服务器)
1、请求方创建 script,src 指向响应方,同时传一个查询参数 ?callbackName=yyy
2、响应方根据查询参数callbackName,构造形如
yyy.call(undefined, '你要的数据')
yyy('你要的数据')
这样的响应
3、浏览器接收到响应,就会执行 yyy.call(undefined, '你要的数据')
4、那么请求方就知道了他要的数据
这就是 JSONP
因为