CSS
HTML
-
如何理解HTML语义化?
(使用div和ul都能实现列表,但更推荐使用ul)
增加代码可读性
让搜索引擎更容易读懂(SEO) -
默认情况下,哪些HTML标签是块级元素、哪些是内联元素?
display:block/table; 有 div h1 h2 ul ol li p table 等
display:inline; 有 a、big、br、em、i、span、strong等
/inline-block;有 img、input 、td 等
CSS
布局
-
盒子模型的宽度如何计算?
问:某 div 的 offsetWidth 是多少。
offsetWidth = (内容宽度 + 内边距 + 边框),无外边距
补充:如果让 offsetWidth 值固定,该如何做?
加 box-sizing: border-box; -
margin 纵向重叠的问题
相邻元素的 margin-top 和 margin-bottom 会发生重叠
空白内容的 <p> </p> 也会重叠
-
margin 负值的问题
margin-top 和 margin-left 负值,元素向上、向左移动
margin-right 负值,右侧元素左移,自身不受影响
margin-bottom 负值,下方元素上移,自身不受影响
BFC理解和应用
- Block Format context ,块级格式化上下文。是 CSS 布局的一个概念:一块独立渲染区域,内部元素的渲染不会影响边界以外的元素。
- 形成BFC的常见条件:[ float 不是 none(浮动元素);position 是 absolute 或 fixed(绝对定位元素);overflow 不是 visible 的块元素 (auto, scroll, hidden)];display 是flex inline-block 等
- BFC的常见应用:消除margin合并(父元素添加overflow:hidden);清除浮动;阻止元素被浮动元素覆盖。
BFC布局规则:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;
内部的块级元素会在垂直方向,一个接一个地放置;
块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并;
每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
BFC的区域不会与float box重叠;
计算BFC的高度时,浮动元素也参与计算。
.clearfix:after{
content:"";
display:block;
visibility:hidden;
clear:both;
}
- float 布局的问题,以及clearfix(手写)
~~- float 布局:圣杯布局和双飞翼布局
- 目的:
三栏布局,中间一栏最先加载和渲染(内容最重要)。
两侧内容固定,中间内容随着宽度自适应。
一般用于PC网页。
- 技术总结:
使用 float 布局
两侧使用margin负值,一遍和中间内容横向重叠
防止中间内容被两侧覆盖,一个用 padding 一个用 margin
- flex 画色子
- flex 实现一个三点的色子(代码)~~
定位
- absolute 和 relative 分别依据什么定位?
relative 依据自身定位
absolute 依据最近一层的定位元素定位
定位元素:absolute relative fixed body
- 居中对齐有哪些方式?
- 水平居中
inline行内元素:text-align: center
block元素:margin: auto
absolute元素:left: 50% + margin-left 自身宽度一半负值
- 垂直居中
inline元素:inlin-height 值 等于 height 值
absolute元素:top: 50% + margin-top 自身高度一半负值
absolute 元素:transform(-50%, -50%) css3,要考虑兼容性
absolute 元素:top, left, bottom, right = 0; margin: auto;(自动填充) [终极方案]
图文样式
line-height 的继承问题
- 写具体数值,如30px,则继承该值
- 写比例,如2/1.5,则继承该比例
- 写百分比,如200%,则继承计算出来的值(考点)
响应式
-
rem 是什么?
rem 是一个长度单位- px,绝对长度单位,最常用
- em,相对长度单位,相对于父元素,不常用
- rem,相对长度单位,相对于根元素,常用于响应式布局
-
响应式布局的常见方案?
- media-query,根据不同的屏幕宽度设置根元素font-size
- rem,基于根元素的相对单位
-
vw/vh
- rem的弊端
阶梯性。 - 网页视口尺寸
window.screen.height // 屏幕高度
window.innerHeight // 网页视口高度
document.body.clientHeight // body 高度 - vw/vh
vh 网页视口高度的1/100
vw 网页视口宽度的1/100
vmax 取两者最大值;vmin 取两者最小值
- rem的弊端
CSS3
关于CSS3动画(不是重点)
2. JS 基础
2.1 变量类型和计算
-
值类型和引用类型的区别(会用计算 某对象属性值 形式出)
- 值类型:undefined, string, number, boolean, Symbol()
- 引用类型:object、array、null、function(特殊,不用于数据存储),统称对象类型
-
对象类型又分为内置对象、宿主对象、自定义对象
- 宿主环境:一般宿主环境由外壳程序创建与维护。如:web浏览器,一些桌面应用系统等。
- 宿主对象:由JavaScript宿主环境提供的对象,可以理解为:浏览器提供的对象。所有的BOM和DOM都是宿主对象。
- 本地对象:独立于宿主环境的 ECMAScript 实现提供的对象。如Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError。就是 ECMA-262 定义的类(引用类型)
- 内置对象(built-in object):由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现。是本地对象的一种。Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在,但大家要清楚,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。类似于isNaN()、parseInt()和parseFloat()方法等,看起来都是函数,而实际上,它们都是Global对象的方法。
const 定义变量必须要赋值,否则会报错。(let a; 是有效的,a 的值是 undefined )
null 是特殊的引用类型(typeof null === 'object',但书上写是值类型),意思为 指针指向空地址,
null == undefined,
函数式特殊引用类型,但不用于存储数据,所以没有“拷贝、赋值函数”这一说
-
typeof 能判断哪些类型
识别所有值类型、识别函数、判断是否是引用类型(不可再细分)- instanceOf,判断 A 是否为 B 的实例
- object.property.toString.call()。对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
- constructor。(当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F)
-
手写深拷贝(代码)
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
console.log(key, result[key], '--------------');
}
}
// 返回结果
return result
}
变量计算-类型转换
- 字符串拼接
const b = 100 + '10'; // ''10010
const b = 100 + parseInt('10');
const c = true + '10'; // 'true10'
- == 运算符
会发生类型转换:
100 == '100' //true
0 == false // true
'' == '0' // false
0 == '' // true
0 == '0' // true
false == '' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
什么时候用==:
// 除了 == null 之外,其他一律用 === ,例:
const obj = { x: 100 }
if(obj.a == null) {}
// 相当于:
// if (obj.a === null || obj.a === undefined) {}
// 在比较相等性之前,null和undefined不能被转化为其他任何值。
- if 语句和逻辑运算
truly 变量:!!a === true 的变量
falsely 变量:!!a === false 的变量
// 以下是 falsely 变量。除此之外都是 truly 变量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === false
!!false === false
逻辑判断:
console.log(10 && 0) // 0
console.log('' || 'abc') // 'abc'
console.log(!window.abc) // true
2.3 作用域和闭包(重要)
题目
1、this 的不同应用场景,如何取值?
多记
2、手写bind函数
代码见js-demo -> bind-demo
3、实际开发中闭包的应用场景,举例说明
隐藏数据;(set 和 get)
如做一个简单的cache缓存工具
知识点
1、作用域和自由变量
自由变量:一个变量在当前作用域没有定义,但被使用了。从函数被定义的地方,不是在执行的地方
向上级作用域,一层一层依次寻找,直至找到为止。如果到全局作用域都没找到,则报错xX is not defined。
2、闭包
本质是作用域应用的特殊情况,有两种表现:函数作为参数被传递;函数作为返回值被返回。
自由变量 从它定义的地方开始寻找,而不是执行的地方。
常见的:防抖和节流函数。
隐藏数据,只提供API
私有变量
闭包定义局部变量(自执行函数)
var Pclass = (function(){
const a = Symbol('a');
const m = Symbol('m');
class Pclass {
constructor(){
this[a] = 'a这是私有变量';
this.b = '变量B-外部可访问';
this[m] = function(){
console.log('私有方法');
}
}
getA(){
console.log(this[a]);
}
getM(){
console.log(this[m]);
}
}
return Pclass
}())
let pc = new Pclass()
console.log(pc) //打印 Pclass {b: "变量B-外部可访问", Symbol(a): "这是私有变量", Symbol(m): ƒ}
3、this
this 取值是在函数执行的时候确认的。
箭头函数永远取它上级作用域的this.
这里的function() {console.log(this)} 是被当做普通函数执行的,并不是因为setTimeout属于window。
作为普通函数 :直接返回window
使用call apply bind
作为对象方法被调用
在class方法中调用
箭头函数
4.4 ajax
题目:
- 手写一个简易的ajax
const xhr = new XMLHttpRequest()
xhr.open('GET', '/data/test.json', true) // true 代表异步,默认。
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// console.log(
// JSON.parse(xhr.responseText)
// )
alert(xhr.responseText)
} else if (xhr.status === 404) {
console.log('404 not found')
}
}
}
xhr.send(null)
- 跨域的常用实现方式
JSONP , CORS
4.4.1 XMLHttpRequest
4.4.2 同源策略
ajax请求时,浏览器要求当前网页和server必须同源(安全)
同源:协议、域名、端口,三者必须–致
加载图片css js可无视同源策略:
<img src=跨域的图片地址/>
<link href=跨域的css地址/>
<script src=跨域的js地址> </script>
<img />可用于统计打点,可使用第三E方统计服务
<link /> <script> 可使用CDN,CDN-般都是外域
<script>可实现JSONP
所有的跨域,都必须经过server端允许和配合
未经server端允许就实现跨域,说明浏览器有漏洞,危险信号
前端发送跨域请求,可能会额外发送一次OPTIONS请求(可用于检测服务器允许的http方法),也就是预检请求(preflight request)。服务器若接受该跨域请求,浏览器才继续发起正式请求。
在请求中,会分为 简单请求 和 复杂请求 。
触发条件:
- (使用了PUT、DELETE等http方法)使用了下面任一HTTP 方法:
PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH - (人为设置了额外的首部字段)人为设置了以下集合之外首部字段:
Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width - (Content-Type 不包含于指定的范围)Content-Type 的值不属于下列之一:
application/x-www-form-urlencoded、multipart/form-data、text/plain
Access-Control-Max-Age这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存的最长时间,单位是秒。如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用OPTIONS请求进行检测。(MDN)
简单请求:
请求方法为:GET、POST、HEAD
请求头:Accept、Accept-Language、Content-Language、Content-Type
4.4.3 跨域:同源策略,跨域解决方案
JSONP
访问https://imooc.com/ , 服务端一定返回一个 html 文件吗?
服务器可以任意动态拼接数据返回,只要符合html格式要求
同理于<script src= "https://imooc.com/getData.js” >
<script>可绕过跨域限制
服务器可以任意动态拼接数据返回
所以, <script>就可以获得跨域的数据,只要服务端愿意返回
注意。!!服务端要在返回的数据外层包裹一个客户端已经定义好的函数!! 如果不加,会报错 语法错误。
详细见 笔记
CORS - 服务器设置 http header
spring 4.2 以上支持了跨域接口
跨域请求中携带cookie
- 同域名下发送ajax请求,请求中默认会携带cookie
- ajax在发送跨域请求时,默认情况下是不会携带cookie的
- 前端设置
- ajax在发送跨域请求时如果想携带cookie,必须将请求对象的withCredentials属性设置为true。
- 后端设置
- 此时服务端的响应头Access-Control-Allow-Origin不能为*(星号)了,必须是白名单样式,也就是必须设置允许哪些url才能访问,如:
Access-Control-Allow-Origin: http://api.bob.com - 除了对响应头Access-Control-Allow-Origin的设置,还必须设置另外一个响应头:Access-Control-Allow-Credentials:true。
- 此时服务端的响应头Access-Control-Allow-Origin不能为*(星号)了,必须是白名单样式,也就是必须设置允许哪些url才能访问,如:
webpack 配置devserver 代理也可实现跨域
仅开发环境
devServer: {
port: 8080,
progress: true, // 显示打包的进度条
contentBase: distPath, // 根目录
open: true, // 自动打开浏览器
compress: true, // 启动 gzip 压缩
// 设置代理
proxy: {
// 将本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 将本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
}
Nginx 反向代理
反向代理代理的是服务端,可以隐藏真实数据。在这里充当一个代理服务器的角色,它会根据不同请求和配置规则,做相应的转发,然后将服务端返回的数据递交给客户端,来解决跨域的问题。
server {
listen 80;
server_name localhost;
## 用户访问 localhost,则反向代理到https://api.shanbay.com
location / {
root html;
index index.html index.htm;
proxy_pass https://api.shanbay.com;
}
location /api { // 前端就不需要再加http://...了
root html;
proxy_pass http://localhost:8101/;
index index.html;
}
}
location 匹配规则:
location 支持的语法location [=|~|~*|^~|@] pattern { ... }
- 「=」 修饰符:要求路径完全匹配
- 「~」修饰符:区分大小写的正则匹配
- 「~*」不区分大小写的正则匹配
- 「^~」修饰符:最大前缀匹配 如果该 location 是最佳的匹配,那么对于匹配这个 location 的字符串, 该修饰符不再进行正则表达式检测。注意,这不是一个正则表达式匹配,它的目的是优先于正则表达式的匹配。如location /a/{},location /a/b/ {},请求 http://a/b/c.html 匹配的是 location /a/b/ {}
匹配规则:
- 先普通,再正则
- 普通location之间的匹配顺序:按最大前缀匹配
如location /a/{},location /a/b/ {},请求 http://a/b/c.html 匹配的是 location /a/b/ {} - 正则location之间的匹配顺序:按配置文件中的物理顺序匹配,只要匹配到一条正则,就不再考虑后面的
- 若普通location匹配到 精确匹配= 或 非正则匹配 ^~, 则不再进行后续的正则匹配
- 普通location与正则location之间的匹配结果选择
- 普通location先匹配,匹配到了结果,只是一个临时结果;
- 会继续正则location的匹配,
- 如果匹配到正则,则用匹配到的正则结果;
- 如果没有匹配到正则,则继续用普通匹配的那个结果
综上,常规的顺序是匹配完普通location,还要继续匹配正则location,但是,也可以告诉nginx,匹配到了普通location,就不要再搜索匹配正则location了,通过在普通location前面加上~符号,表示非,表示正则,^就是表示不要继续匹配正则。
除了~,=也可阻止nginx继续匹配正则,区别在于~依然遵循最大前缀匹配规则,而=是严格匹配
postMessage
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
message: 将要发送到其他 window的数据。
targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
transfer(可选):是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
// a.html
<iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe> //等它加载完触发一个事件
//内嵌在http://localhost:3000/a.html
<script>
function load() {
let frame = document.getElementById('frame')
frame.contentWindow.postMessage('我爱你', 'http://localhost:4000') //发送数据
window.onmessage = function(e) { //接受返回数据
console.log(e.data) //我不爱你
}
}
</script>
// b.html
window.onmessage = function(e) {
console.log(e.data) //我爱你
e.source.postMessage('我不爱你', e.origin)
}
4.4.4 ajax 常用插件
Jquery(基于回调函数,没有promise) , fetch(promise 出错不报错,cookie) , axios(框架中用的多)
4.5 存储
4.5.1 题目
描述cookie localStorage sessionStorage区别:
容量
API易用性
是否跟随http请求发送出去
4.5.2 知识点
cookie
字符串,;分割
本身用于浏览器和server通讯
被“借用”到本地存储来
前端可用document.cookie = ‘…’ 来修改(同一个key会修改,不同的会追加),后端在HttpResponse响应中追加Set-Cookie的头部
缺点:
存储大小,最大4KB
http请求时需要发送到服务端,增加请求数据量
只能用document.cookie = ‘…’ 来修改,太过简陋
localStorage和sessionStorage
HTML5专门为存储而设计,最大可存5M
API简单易用setItem getItem
不会随着http 请求被发送出去
localStorage数据会永久存储,除非代码或手动删除
sessionStorage数据只存在于当前会话,浏览器关闭则清空
般用localStorage会更多- -些
cookie 和 session 区别
客户端第一次请求,服务端会在响应的时候在客户端种下一个cookie,下次请求时,客户端会自动带上这个cookie,服务端会根据这个cookie从服务端的session中取出登录状态和用户信息返回客户端或者用来用户认证,session本质上是服务端的一块数据可以存储在服务器或者redis中,所以说session登录验证方案基于cookie实现
关闭浏览器自动清除缓存
后来才猛然想起,如果我在后台添加cookie到响应头时,就不指定过期时间,那么这个cookie就是一个会话型cookie,当浏览器关闭时,这个cookie就会被浏览器自动删除。
但当时我就想不明白为什么使用js删除就不行,于是就跑到网上去问。终于有大神给出了答案,原来在后台添加cookie时,设置了cookie的HttpOnly属性为true,这样当前cookie就不能通过客户端浏览器的脚本来访问。我后来自己去试了一下,果然如此。当然js删除cookie失败的可能原因并不只于此,具体参考以下博文:http://www.cnblogs.com/gossip/archive/2011/12/06/2278282.html
https://blog.csdn.net/weixin_34252090/article/details/92142809
5. http
题目:
1、http常见的状态码有哪些?
2、http常见的header有哪些?
3、什么是Restful API
4、描述一下http的缓存机制(important)
5.1 http 状态码
5.1.1 状态码分类
1xx 服务器收到请求 ,接收的请求正在处理
2xx 请求成功,如200
3xx 重定向, 需要进行附加操作以完成请求,如302
4xx 客户端错误,如404 (客户端请求了一个服务端根本不存在的地址)
5xx 服务端错误,如500 (出bug)
5.1.2 常见状态码
- 200 成功
- 204 请求已成功处理,但在返回的响应报文中不含实体数据。一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。
- 301 永久重定向(配合location , 浏览器自动处理。不会再访问老的地址)。表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。也就是说,如果已经把资源对应的URI保存为书签了,这时应该按Location 首部字段提示的URI重新保存。比较常用的场景是使用域名跳转,比如,访问 http://www.baidu.com 会跳转到 https://www.baidu.com,发送请求之后,就会返回301状态码,然后返回一个location,提示新的地址,浏览器就会拿着这个新的地址去访问。
- 302 临时重定向(配合location ,浏览器自动处理)。比如未登陆的用户访问用户中心重定向到登录页面。
- 304 资源未被修改(缓存还有效)
- 400 badRequest,请求报文存在语法错误。比如要填的表单项指定是number类型,但是用户填了string类型
- 401 UnauthorizedError,认证失败,如请求头里没有携带指定的token,或者token失效
- 403 没有权限
- 404 资源未找到
- 500 服务端执行请求时发生了错误
- 503 服务器超载或正在停机维护
- 504 网关超时(比如服务器在连接数据库时超时)
5.1.3 关于协议和规范
一个约定,跟着约定执行。
5.2 http methods
-
传统的methods:get获取服务器的数据,post向服务器提交数据,简单的网页功能,就这两个操作
-
现在的methods:
get获取数据
post新建数据
patch/put更新数据
delete删除数据
5.2.1 Restiful-API
一种新的 API设计方法(早已推广使用)
传统API设计:把每个url当做一个功能;
Restful API设计:把每个url当做一个唯一 的资源
如何设计成一个资源?
- 尽量不用url参数
传统API设计: /api/list?pageIndex=2
Restful API设计: /api/list/2 - 用method表示操作类型
传统:
post请求:/api/create-blog
post请求:/api/update-blog?id=100 更新
get请求:/api/get-blog?id=100
RestifulAPI:
post请求:/api/blog
patch请求:/api/blog/100 更新
get请求:/api/blog/100
5.3 http headers
5.3.1 常见的Request Headers
- Accept浏览器可接收的数据格式
- Accept-Encoding浏览器可接收的压缩算法,如gzip
- Accept-Languange浏览器可接收的语言,如zh-CN
- Connection: keep-alive 一次TCP连接重复使用
- cookie:服务器将会受到的cookie信息
- Host 请求的域名~~+端口号~~
- User-Agent (简称UA )浏览器信息
- Content-type发送数据的格式,一般用于设置 post 的参数格式。如application/json(json数据格式),application/x-www-form-urlencoded(表单默认的提数据格式),multipart/form-data(一般用于文件上传)
5.3.2 常见的Response Headers
- Content-type 返回数据的格式,
- text开头,text/html: HTML格式;text/plain:纯文本格式;text/xml: XML格式
- application开头,application/json:JSON 数据格式;application/pdf:pdf 格式;application/xml:XML 数据格式
Content-length返回数据的大小,多少字节 - 图片格式,image/gif :gif 图片格式;image/jpeg :jpg 图片格式;image/png:png 图片格式
- Content-Encoding返回数据的压缩算法,如gzip
- Set-cookie 服务端需要改cookie
- cache-Control 强制缓存
5.3.3 自定义header
5.4 http 缓存
5.4.1 关于缓存的介绍
14-6~最后 webpack 学完来看
目的是 减少网络请求的数量
哪些资源可以被缓存?-静态资源( js CSS img )
5.4.2 http缓存策略(强制缓存+协商缓存)
5.4.3 刷新操作方式,对缓存的影响
正常操作:地址栏输入url , 跳转链接,前进后退等
手动刷新: F5 ,点击刷新按钮,右击菜单刷新
强制刷新: ctrl + F5
7. 运行环境
运行环境即浏览器( server端有nodejs )
负责:下载网页代码,渲染出页面,期间会执行若干JS
要保证代码在浏览器中:稳定且高效
7.2 性能优化
是一个综合性问题,没有标准答案,但要求尽量全面
某些细节问题可能会单独提问:手写防抖、节流.
性能优化原则:
多使用内存、缓存或其他方法.
减少CPU计算量,减少网络加载耗时
(适用于所有编程的性能优化一空间换时间 )
从何入手:
-
让加载更快:
1、减少资源体积:压缩代码;
2、减少访问次数:合并代码, SSR服务器端渲染(服务端把页面及页面要显示的内容一并发出),缓存;
3、使用更快的网络:CDN -
让渲染更快:
1、CSS放在head,JS放在body最下面;
2、尽早开始执行JS ,用DOMContentLoaded触发;
3、懒加载(图片懒加载,上滑加载更多)。
4、对DOM查询进行缓存
5、频繁DOM操作,合并到一起插入DOM结构
6、节流throttle 防抖debounce
16-6 跳过,学过webpack再来看
7.2.1 防抖
监听一个输入框的,文字变化后触发change事件
直接用keyup事件,则会频发触发change事件
防抖:用户输入结束或暂停时,才会触发change事件
// 防抖
function debounce(fn, delay = 500) {
// timer 是闭包中的
let timer = null
return function() {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
console.log('this', this); // input1
fn.apply(this, arguments)
timer = null
}, delay)
}
}
input1.addEventListener('keyup', debounce(function(e) {
console.log(e.target)
console.log(input1.value)
}, 600))
7.2.2 节流
拖拽一个元素时,要随时拿到该元素被拖拽的位置
直接用drag事件,则会频发触发,很容易导致卡顿
节流:无论拖拽速度多快,都会每隔100ms触发一次
// 节流
function throttle(fn, delay = 100) {
let timer = null
return function() {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments) // 箭头函数没有arguments,这里的arguments是上层作用域的。
timer = null
}, delay)
}
}
div1.addEventListener('drag', throttle(function(e) {
console.log(e.offsetX, e.offsetY)
}))