就是让浏览器更好的读懂你写的代码,在进行 HTML 结构、表现、行为设计时,尽量使用语义化的标签,使程序代码简介明了,易于进行 Web 操作和网站 SEO,方便团队协作的一种标准,以图实现一种“无障碍”的 Web 开发。
①去掉或者丢失样式的时候能够让页面呈现出清晰的结构;
②有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
③方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
④便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化
所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。
(Q1) 浏览器:IE,Chrome,FireFox,Safari,Opera。
(Q2) 内核:Trident,Gecko,Presto,Webkit。
1. 浏览器兼容
版本兼容 私有前缀 (优雅降级/ 渐进增强)
2. CSS兼容
base文件 统一重新设置 默认字体大小等
3. JS兼容
事件方法不同
addEventListener
attachEvent
// 常见的兼容性问题:
1、不同浏览器的标签默认的外边距( margin )和内边距(padding)不同
解决方案: css 里增加通配符 * { margin: 0; padding: 0; }
2、IE6双边距问题;在 IE6中设置了float , 同时又设置margin , 就会出现边距问题
解决方案:设置display:inline;
3、当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度
解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度
4、图片默认有间距
解决方案:使用float 为img 布局
5、IE9一下浏览器不能使用opacity
解决方案:opacity: 0.5;filter: alpha(opacity = 50);filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);
6、边距重叠问题;当相邻两个元素都设置了margin 边距时,margin 将取最大值,舍弃最小值;
解决方案:为了不让边重叠,可以给子元素增加一个父级元素,并设置父级元素为overflow:hidden;
7、两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出;
解决方案:父级元素设置position:relative
// IE8兼容问题
1. H5与C3的东西 在IE8 都不能用
比如 H5的 canvas webSocket audio video localStorage sessionStorage
C3 的 圆角 阴影 transition animation transform 弹性布局
2. 阻止事件冒泡
- chrome firefox
- e.stopPropogation()
- IE8 之前
- e.cancelBubble = true
3. 事件名
- chrome Firefox
- 加on onclick
- IE8之前
- 是不加on的
兼容问题补充
兼容问题补充
1.减少http请求次数。比如说把多张图片做成精灵图,合并css js文件(打包工具),使用图片懒加载(lazyLoad)
2.控制资源文件加载优先级。由于js文件比css加载耗费时间,可以将css代码放js代码的前面。
3.可以利用网站的缓存来减少服务器请求 缓存ajax
4.懒加载,先把页面所需的最小内容集加载出来一个极端的做法,确保网页在不需要js的情况下将页面加载出来,再延迟加载出js
vue里路由懒加载 : (避免流量浪费)
改变router.js里路由的导入方式 const 路由名字 = ()=>import("路径")
这样打包的时候就不是一个js文件,而是会多一些js文件对应不同的页面
4.减少Reflow(重排),如果需要在DOM操作时添加样式,尽量使用增加class属性,而不是通过style操作样式。
5.减少dom操作
6.网站图标尽量使用iconfont字体图标
//提高网站性能
1.资源加载
css顶部,js底部
css,js文件压缩,使用精灵图
图片使用预加载,懒加载(总之就是减少资源的请求次数)
2.代码性能
- css:
减少css代码量,减少查询层级与范围
避免类与id跟标签同名
- html:
减少dom节点:加速页面渲染,减少页面重绘
- js:
少用全局变量
使用委托事件,利用body来代理
减少dom操作
减少对象查找,尽量使用变量查找
回流:当渲染树因为元素的规模尺寸,布局等改变而需要重新构建。(也就是重新布局)每个页面最少要进行一次回流,就是第一次加载。当我们通过渲染树获取节点的信息时会有回流。
重绘:当渲染树中的一些元素需要更新属性,而这些属性只影响元素的外观风格,不会影响布局,就叫重绘。(回流必引起重绘,重绘不一定会回流)
减少回流与重绘: 减少对dom树的操作。
1.使用translate代替top改变。
2.使用opacity代替visibility改变。
3.修改dom的classname。
4.将dom离线后修改。
1.标签选择器(如:div p ul li )
2.ID选择器(如: # box)
3.类选择器(如: . box)
4.全局选择器(如:*号)
5.复合选择器(交集、并集、子代、后代)
排序:!important > 行内样式 > ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
::first-letter:为某个元素中的文字的首字母或第一个字使用样式。
::first-line:为某个元素的第一行文字使用样式。
::before:在某个元素之前插入一些内容。
::after:在某个元素之后插入一些内容
::selection:匹配元素中被用户选中或处于高亮状态的部分。
1.magin负间距
绝对定位; left和top为50%; margin-left和margin-top为负自身的一半
2.transform变形
绝对定位; left和top为50%; transform:translate(-50%,-50%)
3.利用magin的auto
绝对定位; left, top ,right,bottom 都为0; margin:auto
4.弹性布局
display:flex; justify-content和align-items都为center
1,父级 div 定义 height
原理:父级 div 手动定义 height,就解决了父级 div 无法自动获取到高度的问题。
简单、代码少、 容易掌握 ,但只适合高度固定的布局.
2,结尾处加空 div 标签 clear:both
原理:在浮动元素的后面添加一个空 div 兄弟元素,利用 css 提高的 clear:both 清除浮动,让父级
div 能自动获取到高度 ,如果页面浮动布局多,就要增加很多空 div,让人感觉很不好 .
3,父级 div 定义 overflow:hidden
超出盒子部分会被隐藏,不推荐使用.
4,单伪元素法: 父级 div 定义 伪类:after 和 zoom
.clearfix:after{
content:"";
display:block;
visibility:hidden;
height:0;
line-height:0;
clear:both;
}
.clearfix {
*zoom:1; // 针对低版本浏览器做兼容
}
原理:IE8 以上和非 IE 浏览器才支持:after,原理和方法 2 有点类似,zoom(IE 转有属性)可解决
ie6,ie7 浮动问题 ,推荐使用,建议定义公共类,以减少 CSS 代码。
5, 双伪元素法:
.clearfix:before,
.clearfix:after {
content: "";
display: block;
clear: both;
}
.clearfix {
*zoom:1;
}
禁用用户自动缩放功能:
1) 百分比布局(流式布局)
流式布局其实就是宽度用百分比,高度用固定值的布局方式,宽度通过百分比来适配不同宽度的屏幕。
2) 弹性布局 (flex)
这种布局方式是通过css3新增的一些辅助布局的样式属性来制作布局的方式。
3) rem布局
rem是一种相对长度单位,通过这个长度单位可以实现元素宽高等比例缩放,从而完成不同宽度屏幕的适配。
4) 响应式布局 (媒体查询)
通过样式动态查询屏幕的宽度,动态切换样式来适配不同宽度屏幕的布局方式。
DNS 域名解析器 (字典) 把域名转成ip地址 …
简洁版:
浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
服务器交给后台处理完成后返回数据,浏览器接收文件(HTML、JS、CSS、图象等);
浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
载入解析到的资源文件,渲染页面,完成。
详细版:
1. 浏览器的地址栏输入URL并按下回车
2. 浏览器查找当前URL的DNS(域名解析器) 的缓存记录
3. DNS解析URL对应的IP地址
( DNS解析会先查找本地DNS解析器缓存,如果查到就返回
如果没有找到 就查找本地的DNS服务器
- 查找方式:迭代查询
* 以www.baidu.com为例
先从根域开始查找 .com
再查找 第二级域 baidu.com
再找子域 www.baidu.com 的顺序来查找ip地址 )
4. 根据ip地址建立TCP连接(三次握手)
DNS域名解析之后,获取到了服务器的ip地址,在获取到IP地址的时候就开始建立一次TCP连接
第一次握手: 客户端发送syn(请求连接)包到服务器 并进入syn_sent状态(发送状态)
等待服务器确认
第二次握手: 服务器收到syn包之后 确认客户端的syn包,同时给自己也发送了一个syn+ack包
服务器进入syn_recv状态(接受状态)
第三次握手: 客户端接收服务器发送的syn包 同时向服务器发送确认ack包
发送完毕之后 客户端和服务器进入established
(TCP连接成功)
5. 浏览器向服务器发送HTTP请求,服务器响应浏览器的HTTP请求
6. 浏览器解析HTML,CSS结构 , 构建DOM树和CSS树, 渲染页面,
解析js代码
(reflow:回流, 一般指元素的内容,结构,位置尺寸发生变化,需要重新计算和渲染树)
(repaint:重绘,一般只指颜色,背景颜色,边框颜色等发生外观变化)
7. 关闭TCP连接(四次挥手)
第一次挥手:浏览器发完数据后,请求FIN 断开连接
第二次挥手:服务器发送ACK表示同意,
第三次挥手:服务器可能还有数据要发送给浏览器 所以此时的服务器再发送一次FIN请求断开连接
第四次挥手:浏览器确认断开连接
简单数据类型:
数值(NaN)
字符串(string)
布尔值(Boolean)
undefined
Null
复杂数据类型:
new Object()
new Array()
new Function()
// 1.splice(); 删除数组中元素
// splice(index,number) 删除从index开始 number个元素 如果number不写 就是后面的全部删掉
var arr = ['路飞', '索隆', '乌索普', '娜美']
arr.splice(1,2) // ['路飞','娜美']
arr.splice(2,1); // ['路飞', '索隆', '娜美']
// 插入的话 就是在指定下标前插入 splice(index,number,插入的元素)
arr.splice(2, 0, '山治'); // ["路飞", "索隆", "山治", "乌索普", "娜美"]
arr.splice(2,1,'山治'); // ["路飞", "索隆", "山治", "娜美"]
console.log(arr);
// 2.slice() 截取数组的下标并返回新的数组 slice(index,index) 左闭右开
var arr = [0, 7, 4, 1, 2, 5, 8, 9, 3];
var arr2 = arr.slice(1, 4);// [7, 4, 1]
console.log(arr2);
// 3.concat() 数组的拼接 并返回一个新的数组
var arr1 = [1, 2, 3];
var arr2 = [7, 8, 9];
var arrnew = arr1.concat(arr2);
console.log(arrnew); // [1, 2, 3, 7, 8, 9]
// 4.join() 数组按照指定的形式来分割 并返回一个字符串
var arr = [1, 2, 3, 4, 5];
var arrnew = arr.join('-');
console.log(arrnew); // 1-2-3-4-5
// 5.sort() 排序 从小到大排序
var arr = [0,7,4,1,2,5,8,9,6,3]
arr.sort();
console.log(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 6.reverse() 数组翻转
var arr = [1,2,3];
arr.reverse();
console.log(arr); // [3,2,1]
// push() 向数组的末尾添加
// pop() 向数组的末尾删除
// unshift() 向数组的头部添加
// shift() 向数组的头部减少
相同点: 都是不能编辑文本 但是可以通过js来改变
不同点: disabled 不能获取焦点 并且不会提交表单
readonly 可以获取焦点 可以提交表单
// 1.slice() 截取字符串 slice(index,index) 左闭右开
// 2.substring() 截取字符串 str(index,index) 左闭右开
var str = '以前我没得选,现在我想做个好人,对不起,我是警察';
var strnew = str.slice(5, 9); // 选,现在
var strnew = str.substring(5, 9); // 选,现在
console.log(strnew);
// 3.substr() 截取字符串 str(index,numer) 返回新的字符串
var str = '123456789';
var strnew = str.substr(1, 6)
console.log(strnew); // 234567
// 4.charAt() 根据下标找字符 找不到 返回空
var str = '我于杀戮之中盛放';
var strnew = str.charAt(5) // 中
var strnew = str.charAt(15) //
console.log(strnew);
// 5.indexOf() 根据字符找下标 如果找不到 就返回-1
var str = '让我们来猎杀那些陷入黑暗中的人吧';
var index = str.indexOf('猎杀'); // 4
var index= str.indexOf('呵呵') // -1
console.log(index);
// 6.concat() 拼接两个字符串
var strnew = str1.concat(str2)
// 7.replace(); replace(old,new) old:想要替换的元素 , new: 新的元素
var str = '北京是首都,深圳是特区,深圳深圳深圳'
var strnew = str.replace('深圳','汕头') //但是只能换第一个
var strnew = str.replace(/深圳/g, '汕头');
console.log(strnew);
// toUpperCase() 把字符串转换成大写 返回一个新的字符串
// toLowerCase() 把字符串转换成小写 返回一个新的字符串
在普通函数中 this ==> window
在定时器中 this==> window
在构造函数中 this ==> 实例化的对象
在事件触发中 谁触发的这个事件 this就是指向谁
1. 箭头函数是匿名函数,不能作为构造函数,不能使用new
2. 箭头函数不能绑定arguments,取而代之用rest参数...解决
3. 箭头函数没有原型属性(prototype) , 所以本身没有this
4. 箭头函数不会创建自己的this,this永远指向其上下文的this,没有办法改变其指向; 普通函数的this指向调用它的对象
5. 箭头函数相对普通函数的语法更加简洁优雅
携带:
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage虽然也有存储大小的限制,但可以达到5M或更大。
有期时间:
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage 数据在当前浏览器窗口关闭后自动删除。
cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
共享:
localstorage和cookie会在所有同源窗口中共享,
sessionstorage不在不同的浏览器共享。
localStroage只能存字符串,我们看百度的那个历史记录看起来像存了数组,其实存的是JSON字符串
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。
特点:数据简单、易于读写、占用带宽小
// js中对应JSON的使用 2个方法
1. JSON.parse('JSON格式的字符串') -- 这个用的 最多
把JSON格式的字符串转化为对应的js对象(数组)
2. JSON.stringify(js对象或者数组) -- 了解即可
把js对象(数组)转化为对应的JSON格式的字符串
怎样添加、移除、移动、复制、创建和查找节点?
1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
cloneNode() // 创建节点
2)修改
appendChild() //将child追加到parent的子节点的最后面
removeChild() // 移除子节点
replaceChild() //替换
insertBefore() //将某个节点插入到另外一个节点的前面
3)查找
document.getElementsByTagName() //通过标签名称
document.getElementsByName() //通过元素的Name属性的值
document.getElemnetsByClassName() // 标签名
document.getElementById() //通过元素Id,唯一性
document.querySelector(); //传入css选择器,找到第一个匹配的元素,只返回元素
document.querySelectorAll(); //传入css选择器,选择器能找到几个,这方法就找到几个,返回伪数组
4) 属性型
元素.getAttribute(); 获取行内属性
元素.setAttribute(); 设置行内属性
元素.removeAttribute(); 删除行内属性
5) 修改元素样式
elem.style.color = "red";
...
1. html
text()、html() 以及 val()
2. css
addClass() ,removeClass() , toggleClass()
3.属性
attr(),removeAttr(),prop(),removeProp()
4.事件
原生去掉"on"
5.动画效果
hide(),show(),fadeIn(),slideDown(),
window document location screen history navigator
jQuery对象的本质其实就是JS中的伪数组,所以你取下标其实就取到了元素,而每个元素就是DOM对象
[外链图片转存失败(img-uR5hfzk0-1568132368089)(C:\Users\enidchan\AppData\Roaming\Typora\typora-user-images\1568120528584.png)]
通俗地讲,当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链。
1.当执行函数时,总是先从函数内部找寻局部变量
2.如果内部找不到(函数的局部作用域没有),则会向创建函数的作用域(声明函数的作用域)寻找,依次向上
3.内层作用域可以访问外层作用域,反之不行
闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。谈函数闭包要说两点:
1.作用域链,
2.垃圾回收机制
// 1.作用域链:由本身最前端的作用域链为起点,以全局作用域为终点的一个单向通道。
// 2.垃圾回收机制:当开辟完一个作用域并且把内部的代码都执行完毕后,没有变量的引用(在内存中失去了引用),就会自动的回收清除。
?闭包产生:
本身是是一个特殊对象,由两部分组成,一部分是执行化上下文(一个函数也可以创建一个执行化上下文),一个是执行化上下文A中创建的函数(B), 执行B时调用了A中对象的值,就会产生闭包。(chrome调试里面scope的closure是闭包)
执行化上下文
可以理解为一段代码的执行过程,会被保存在一个栈中,最先入栈的是全局的执行化上下文,在依次把执行的代码的上下文压入栈中。处理完一个就弹出一个。
// 闭包最大的作用:
可以访问其他作用域内的变量;
可以让这些变量的值始终保持在内存中,延长变量的生命周期。
闭包应用场景: 防抖 / 节流 (联想功能的节流)
优点:闭包可以形成独立的空间,永久的保存局部变量
缺点:保存中间值的状态缺点是造成内存泄漏,因为闭包中的局部变量永远不会被回收
所以少用闭包,并且记得如果这个闭包不用了就记得把闭包赋值为null
简单解释:
浅拷贝和深拷贝都只针对于引用数据类型.
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存;
但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象;
区别:
浅拷贝只复制对象的第一层属性,
深拷贝可以对对象的属性进行递归复制;
1)意外的全局变量引起的内存泄露
function leak(){
leak="xxx"; // leak成为一个全局变量,不会被回收
}
2)闭包引起的内存泄露
3)没有清理的DOM元素引用
4)被遗忘的定时器或者回调
5)子元素存在引起的内存泄露
1.事件捕获:
当一个事件触发后,从Window对象触发,不断经过下级节点,直到目标节点。在事件到达目标节点之前的过程就是捕获阶段。所有经过的节点,都会触发对应的事件(事件捕获默认看不到)
2.事件冒泡:
当一个元素的事件触发后,会依次一级一级往上调用父元素的同名事件,直到window,事件冒泡默认就存在(必须是在触发的元素开始往上)
当事件到达目标节点后,会沿着捕获阶段的路线原路返回。同样,所有经过的节点,都会触发对应的事件
3.事件委托的优点:
提高性能:每一个函数都会占用内存空间,只需添加一个事件处理程序代理所有事件,所占用的内存空间更少。
动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件
阻止冒泡/捕获:
通过e.stopPropagation()方式阻止事件的冒泡.阻止冒泡或捕获的继续执行,在需要停止的函数使用.在该函数使用时,该函数还是会执行,但是函数外之后的代码不会执行.
IE8只有事件没有捕获,
IE8不支持e.stopPropagation()
IE8支持e.cancelBubble = true;
在浏览器中,