阅读 35

重绘、回流(重排)

重绘、回流(重排)

当render tree(DOM tree和样式结构体cssom结合后构建呈现树render tree)中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就成为回流。每个也没面至少需要一次回流,就是在页面第一次加载的时候。

当reder trr中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不会影响布局的,比如background-color,则就成为重绘

重绘

只改变自身样式,不会影响其他元素

元素样式的改变(宽高、大小、位置不变)

如visibily、color、background-color等

回流

元素的大小或者位置发生改变,触发了重新布局导致渲染树重新计算布局和渲染

如添加和删除可见的DOM元素

元素的位置、尺寸发生改变

内容发生变化(如文本变化或图片被另一个不同尺寸的图片所代替)

页面一开始渲染的时候(无法避免)

回流是根据视口大小来计算元素的位置和大小的,所以浏览器窗口尺寸变化也会引起回流

造成回流的条件:

1,页面初始渲染

2,改变字体,改变元素尺寸(宽、高、内边距、边框、改变元素位置等),注意:修改属性不影响布局则不会发生回流

3,改变元素内容(文本或图片等或比如用户在input中输入文字)

4,添加、删除可见的DOM元素

5,fixed定位的元素,在拖动滚动条的时候会一直回流

6,调整窗口大小

7,计算offsetWidth、offsetHeight属性

注:回流一定会触发重绘,重绘不一定会回流

2, 预解析常见面试题

1,首先把函数声明和变量声明,提升到当前作用域最前面,因为JS是一个解释执行的脚本语言,从上到下执行,如果函数调用出现在函数定义之前,就会导致失败

2,变量提升的是声明并不是赋值,函数只提升声明并不调用

3,函数在JS里属于一级公民,如果变量名和函数冲突,则会优先执行函数

1,alert(a)
  console.log(a)  // a is not defined

2,console.log(a)  // undefined
  var a = 0
  console.log(a)  // 0

3,console.log(a)  // a() {console.log('我是函数')} 函数和带var的变量重名,var变量被忽略
  var a = '我是变量'
  function a() {
    console.log('我是函数')
  }
  console.log(a)  // 我是变量

4,console.log(a)  // a () {console.log('我是函数')}
  a++
  console.log(a)  // NaN
  var a = '我是变量'

  function a() {
    console.log('我是函数')
  }
  console.log(a) // 我是变量

5,console.log(a)  // undefined
  var a = 0
  console.log(a)  // 0

  function fn() {
    console.log(a)  // undefined
    var a = 1
    console.log(a)  // 1
  }
  fn()
  console.log(a)  // 0 因为函数中的a带var,所以没有影响外面的a,如果函数里的a没有带var,运行结果就不一样了

6,console.log(a) // undefined
  var a = 0;
  console.log(a)  // 0

  function fn() {
    console.log(a) // 0 不带var没有提升,函数内没有a,沿着作用域链向上找,找到全局里的a
    a = 1;
    console.log(a) // 1 
  }
  fn()
  console.log(a)  // 1 函数里的a没有带var,此时先看有没有形参,如果有,相当于在函数里var一个a,如果没有,看全局有没有a,如果有就是修改全局的a,如果全局没有a,就在全局增加一个a,这里就是修改全局的a
  
  
7,console.log(a) // undefined
  var a = 0
  console.log(a) // 0
  function fn () {
    console.log(a)
    a = 1
    console.log(a)
  } // 函数在预解析提升时,如果函数重名,下面的会覆盖上面的,所以这函数失效
  fn()
  
  function fn () {
    console.log(a) // undefined
    var a = 2
    console.log(a++) // 2 ++在前,先赋值后运算。++在后,先运算再赋值
    // i++和++i都等同于 i = i + 1
    // 但是一般情况下他们都跟赋值联系在一起,比如
    // var a 
    // a = i++  将i赋值给a,即a = i,之后再执行 i = i + 1
    // a = ++i 将i + 1赋值给a, 即 a = i + 1,再执行 i = i + 1
    // 总结:
    // 后置++,是将自身的值赋值给变量,再自身加1
    // 前置++,是将自身+1后的值赋值给变量,同时自身加1
  }
  console.log(a)  // 0 函数里的a带var,不影响全局的
  
8,console.log(a) // undefined
  var a = 1
  console.log(a) // 1
  function a () {
    console.log(2)
  } // 函数重名,此函数失效
  console.log(a) // 1
  var a = 3  // 预解析时,变量名和函数名重名,预解析时的var a = undefined会被忽略,执行时的 a = 3不受影响
  console.log(a) // 3
  function a () {
    console.log(4) // 函数始终没有被调用,这里应该是一个幌子
  }
  console.log(a) // 3
  
9, f1()
  console.log(c) // 10
  console.log(b) // 10
  console.log(a) // a is not defined 
  function f1 () {
    var a = b = c = 10
    console.log(a)
    console.log(b)
    console.log(c)
  }
10,f1()
  console.log(a) // a is not defined 由于JS报错,后面的代码都不执行,导致bc都没有打印
  console.log(b)
  console.log(c)
  function f1 () {
    var a = b = c = 10
    console.log(a)  // 10
    console.log(b)  // 10
    console.log(c)  // 10
  }

11,myFun(10, 20) // myFun is not a function
    var myFun = function (a, b) {
      return a + b
    } 
    // 这个函数定义的方式是:函数表达式定义,在预解析时这个函数不会整体提升,只是提升了var myFun = undefined,此时当函数调用,肯定就会报错
    
12,var i = 1
    i = i++ // 本来i在运算之后应该变为2的,但是=左边是给i本身赋值,所以i = 1
    var j = i++ // ++在后,先运算,j=1,后赋值 i = 2
    var k = i + ++i * i++  // k = 2 + 3 * 3, 此时i = 4
    console.log(i, j, k) // 4 1 11
    var k = i++ + i++ * i++ // k = 4 + 5 * 6, 此时i变成7
    console.log(i, j, k) // 7 1 34
复制代码
文章分类
前端
文章标签