30道大概率会考到的题( 16-18题)
本章内容
- 16,页面重排(回流)、重绘,及如何避免
- 17,IIFE是什么?作用是什么?
- 18,vue导航守卫
16,页面重排(回流)、重绘,及如何避免
当Render tree(Dom tree和css tree结合)因为元素的尺寸、布局、隐藏等改变而需要重新渲染。就会涉及重绘和重排。重排一定触发重绘,重绘不一定触发重排。每个页面至少需要一次重排,就是页面第一次渲染的时候。
重绘
只改变自身样式,不会影响其他元素,元素样式改变(宽高、大小、位置不变),比如:background-color
重排
元素的宽高、大小、位置发生改变,触发重新布局导致Render tree重新计算布局和渲染,比如:页面初次渲染时、浏览器窗口尺寸变化(重排是根据视口大小计算元素的大小位置的)等
常见的会触发重排的情况:
1,页面初次渲染
2,元素的显示隐藏
3,元素内容的改变(文本变化、图片被另一个不同尺寸的图片代替、input输入文字等)
4,浏览器窗口变化
5,元素大小、位置的改变(宽高、内边距、边框、fixed定位的元素在拖动滚动条时一直触发重排、计算offsetWidth、offsetHeight等)
如何避免重排
1,多次样式的修改合并为一次
2,让元素脱离文档流
// 1,隐藏元素进行修改后再显示
let dom = document.getElementById('div')
dom.style.display = 'none'
dom.style.width = '100px'
dom.style.padding = '5px'
dom.style.display = 'block'
// 2,使用createDocumentFragment创建一个子元素,然后再拷贝到文档中
let dom = document.getElementById('dom')
let ele = document.createDocumentFragment().appendChild(document.createElement('p'))
ele.style.width = '100px'
ele.style.padding = '5px'
dom.appendChild(ele)
// 3,将原元素拷贝出一个独立的节点,操作这个节点,再覆盖原元素
let dom = document.getElementById('dom')
let cloneDom = dom.cloneNode(true)
cloneDom.style.width = '100px'
cloneDom.style.padding = '5px'
dom.parentNode.replaceChild(cloneDom, dom)
3,缓存布局信息
尽量减少对布局信息的查询次数,可将其fu赋值给局部变量,使用局部变量参与计算
// 错误写法
div.style.left = div.offsetLeft + 1 + 'px'
// 正确写法
let curLeft = div.offsetLeft
div.style.left = ++curLeft + 1 + 'px'
4,使用虚拟DOM的框架vue/react
5,使用window.requestAnimationFrame()或window.reqeustIdleCallback()来优化渲染
文章参考:https://segmentfault.com/a/1190000016990089
17,IIFE是什么?作用是什么?
IIFE:立即调用的函数表达式。语法:(function (){})()
(function () {
return 'iii'
})()
// iii
IIFE作用:隔离作用域,避免与全局作用域内的变量命名冲突或污染全局命名空间
18,vue导航守卫
- 全局守卫
- 路由独享守卫
- 路由组件内的守卫
1,全局守卫
vue-router全局有三个守卫:
1,router.beforeEach 全局前置守卫 进入路由之前
2,router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
3,router.afterEach 全局后置钩子 进入路由之后
// main.js
import router from './router' // 引入路由
router.beforeEach((to, from, next) => {
next()
})
router.beforeResolve((to, from, next) => {
next()
})
router.afterEach((to, from) => {
console.log('afterEach 全局后置钩子')
})
// to: Route: 将要进入的路由对象
// from: Route: 当前导航正要离开的路由
// next: Function: 一定要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参数。
2,路由独享守卫
{
path: '/home',
component: resolve => require(['../views/Home.vue'], resolve),
meta: {
title: '首页'
},
beforeEnter: (to, from, next) => {
// 会在全局前置守卫后面调用,所以不会被全局守卫覆盖
},
beforeLeave: (to, from, next) => {
}
}
3,路由组件内的守卫
1, beforeRouteEnter 进入路由前, 在路由独享守卫后调用, 不能获取组件实例this,组件实例还没被创建
2,beforeRouteUpdate路由复用同一个组件时, 在当前路由改变,但是该组件被复用时调用,可以访问组件实例this
3,beforeRouteLeave离开当前路由时,导航离开该组件的对应路由时调用,可以访问组件实例this
beforeRouteLeave(to, from, next) {
next()
},
beforeRouteEnter(to, from, next) {
next()
},
beforeRouteUpdate(to, from, next) {
next()
},
computed: {},
method: {}
网友评论