回流和重绘
先牢记这句话,回流必将引起重绘,而重绘不一定会引起回流。回流的代价要远大于重绘。
当你给一个元素更换颜色,这样的行为是不会影响页面布局的,DOM树不会变化,但颜色变了,渲染树得重新渲染页面,这就是重绘。
比如我们增删DOM节点,修改一个元素的宽高,页面布局发生变化,DOM树结构发生变化,那么肯定要重新构建DOM树,而DOM树与渲染树是紧密相连的,DOM树构建完,渲染树也会随之对页面进行再次渲染,这个过程就叫回流。
换句话说,你可以简单粗暴地理解为重绘只是改变了样式树。而回流改变了DOM树(引起DOM树结构变化,页面布局变化)。
浏览器拿到HTML文本后如何解析
html文件在没有写入html标签之前和txt文本是一个性质的,不含任何样式。只是单纯的文本预览文件。一旦加入了html标签,表示内容有了语义。浏览器的渲染引擎才会根据标签的语义开始解析。
解析一个文档意味着把它翻译成有意义的结构以供代码使用。解析的结果通常是一个表征文档的由节点组成的树,称为解析树或句法树。
解析器通常把工作分给两个组件——分词程序和解析程序。分词程序负责把输入切分成合法符号序列,解析程序负责按照句法规则分析文档结构和构建句法树。
【精选】你了解浏览器原理吗?说说浏览器解析html的过程_浏览器解析html过程_码上十七的博客-CSDN博客https://blog.csdn.net/m0_65335111/article/details/127400627
CSS树和DOM树怎么结合
eventLoop事件循环
var x = setTimeout(() => {console.log(1)},0)
var y = new Promise(function(resolve) {
console.log(2);
resolve();
console.log(3)
})
y.then(() => {
console.log(4)
})
console.log(5)
依次输出2 3 5 4 1
setTimeout产出宏任务,promise.then产出的是微任务。
JavaScript是单线程的,意味着任务只能一次执行一个任务。
宏任务(Macro Task)是指在当前任务队列中被调度的任务。例如:
- DOM事件处理
- setTimeout
- setInterval
- setImmediate(nodejs独有)
- requestAnimationFrame(浏览器独有)
- I/O操作(nodejs独有)
微任务(Micro Task)是指在当前任务执行结束后需要立即执行的任务。例如:
- Promise.then
- Promise.catch
- Promise.finally
- MutationObserver
Event Loop 翻译为事件循环,是JavaScript的一种执行机制。
Event Loop的执行过程如下:
- 执行全局Script同步代码,这些同步代码可能会产生宏任务或者微任务。
- 执行所有微任务,直到微任务队列为空。
- 取出一个宏任务执行,执行过程中产生的微任务会加入微任务队列。
- 重复步骤2-3,直到所有任务都执行完毕。
原型链的概念
就是实例对象和原型对象之间的链接,每一个对象都有原型,原型本身又是对象,原型又有原型,以此类推形成一个链式结构.称为原型链
什么是原型对象
在声明了一个函数之后,浏览器会自动按照一定的规则创建一个对象,这个对象就叫做原型对象
怎么判断NULL
val === null
或:
if(!val && typeof(val) != "undefined" && val!= 0) {
}
怎么中断请求
jquery
var ajaxGet = $.get('xxx',{id:1},function(data){...});
ajaxGet.abort()
axios
使用 CancelToken.souce 工厂方法创建一个 cancel token
const CancelToken = axios.CancelToken;
将token作为传参
const source = CancelToken.source();
axios.get('https://mdn.github.io/dom-examples/abort-api/sintel.mp4', {
cancelToken: source.token
}).catch(function (thrown) {
// 判断请求是否已中止
if (axios.isCancel(thrown)) {
// 参数 thrown 是自定义的信息
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
这里用axios来判断中止状态
主动取消:
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
方法二:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel('Operation canceled by the user.');
Fetch
fetch是ES6新出的,基于promise设计,没有进行封装,属于原生js,所以在vue中使用的时候也不需要进行import引入就可以直接使用。
fetch请求返回的是promise对象,需要进行json转换,所以需要两次.then()
fetch("/api/test/")
.then(res => {
return res.json();
})
.then(res => {
// 这里返回的数据就是我们想要请求的json数据
console.log(res);
上面是get下面是post
const requestBody = {
title: 'foo',
body: 'bar',
userId: 1
};
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify(requestBody),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(data => console.log(data))
如果要终止 fetch 请求,则可以使用 Web 提供的 AbortController 接口。
首先我们使用 AbortController() 构造函数创建一个控制器,然后使用 AbortController.signal 属性获取其关联 AbortSignal 对象的引用。当一个 fetch request 初始化时,我们把 AbortSignal 作为一个选项传递到请求对象 (如下:{signal}) 。这将信号和控制器与获取请求相关联,然后允许我们通过调用 AbortController.abort() 中止请求。
const controller = new AbortController();
let signal = controller.signal;
console.log('signal 的初始状态: ', signal);
const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');
downloadBtn.addEventListener('click', fetchVideo);
abortBtn.addEventListener('click', function() {
controller.abort();
console.log('signal 的中止状态: ', signal);
});
function fetchGetVideo() {
//...
fetch(url, {signal}).then(function(response) {
//...
}).catch(function(e) {
reports.textContent = 'Download error: ' + e.message;
})
}
function fetchPostVideo() {
//...
fetch(url,{
name: "张三.avi",
id: 18x
},{
signal: controller.signal // 传入signal
}).then(function(response) {
//...
}).catch(function(e) {
reports.textContent = 'Download error: ' + e.message;
})
}
手写题
实现一个handler,handler(arr)返回一个对象 o
要求:
1.调用o.next ().value 输出
2.继续调用o.next().value 输出 2
3.继续调用o.next().value 输出 3
function o(arr) {
this.data = arr;
this.index = 0;
}
o.prototype.next = function() {
this.index++;
return this.data[this.index-1]
}
function handler(arr) {
if (!Array.isArray(arr)) {return false}
return new o(arr)
}
var c = handler([1,2,3])
c.next()
c.next()
c.next()