JavaScript中的盒模型

341 阅读7分钟

JS中的盒模型

1、高度问题:

● 内容的宽度和高度:我们设置的width/heigth这两个样式就是内容的宽和高,如果没有设置height值,容器的高度会更具里面内容自己进行适应,这样获取的值就是真实内容的高;如果设置固定的高度了,不管内容是多了还是少了,其实我们内容的高度指的都是设定的那个值得
● 真实内容的宽度和高度:这个代指的是实际内容的宽高(和我们设置的height没有必然的联系),例如:设置高度为200px,如果内容有溢出,那么真实内容的高度是要把溢出内容的高度也要加进来的

1、client系列(当前元素的几个私有的属性)

 //->clientWidth/clientHeight:内容的宽度/高度+左右/上下填充(和内容溢出没有关系)
 //->clientLeft:左边框的宽度  clientTop:上边框的高度(border[left/Top]Width)

2、 offset系列

    //-> offsetWidth/offsetHeight:clientWidth/clientHeight+左右/上下边框(和内容是否溢出也是没有任何关系)
    //-> offsetParent:当前元素的父级参照物
    //-> offsetLeft/offsetTop:当前元素的外边框距离父级参照物的内边框的偏移量

3、 scroll系列

    //-> scrollWidth/scrollHeight:和我们的clientWidth/clientHeight一模一样(前提是:容器中的内容没有溢出的情况下)
    //-> 如果容器中的内容有溢出,我们获取的结果是如下规则:
    //scrollWidth:真实内容的宽度(包含溢出)+左填充
    //scrollHeight:真实内容的高度(包含溢出)+上填充
    //->获取到的结果都是约等于的值,因为:同一个浏览器,我们是否设置overflow='hidden'对于最终的结果是由影响的;在不同的浏览器中我们获取到的结果也是不想同的
    //scrollLeft/scrollTop:滚动条卷去的宽度和高度

2、关于JS盒子模型属性取值的问题

● 通过上面这13个属性值获取的结果永远不可能出现小数,都是整数;浏览器在获取结果的时候,在原来真实结果的基础上进行四舍五入

3、关于操作浏览器本身的盒子模型信息

● clientWidth/clientHeight是当前浏览器可视窗口的(一屏幕的宽度和高度)
● scrollWidth/scrollHeight是当前页面的真实宽度和高度(所有屏加起来的宽度和高度~但是是一个约等于的值)
    //-> 我们不管哪些属性,也不管是什么浏览器,也不管是获取还是设置,想要都兼容的话,需要写两套
    document.documentElement[attr]||document.body[attr]
    //->必须document.documentElement在前
    //[获取要写两套]
    document.documentElement.clientHeight||document.body.clientHeight
    //[设置也要写两套]
    document.documentElement.scrollTop=0;
    document.body.scrollTop = 0;

小练习:

● win:编写一个有关于操作浏览器盒子模型的方法
    //如果值传递了attr没有传递value,默认的意思是"获取"
    //如果两个参数都传递了,意思是"设置"
    //->不严谨来说这就是有关于"类的重载":同一个方法,通过传递参数的不同实现了不同的功能
    function win(attr,value){
        if(typeof value === "undefined"){ //没有传递value值 -> '获取'
            return document.documentElement[attr] || document.body[attr]
        }
        // -> 设置
        document.documentElement[attr] = value
        document.body[attr] = value

    }

获取元素的某一个具体的样式属性值

1、元素.style.属性名

    //->需要我们把元素的样式写在行内样式上才可以(写在样式表中是不管用的)
    console.log(box.style.height)  //-> ""
    //如果样式都写在行内,这样就不能属性CSS和HTML想分离

2、使用window.getComputedStyle这个方法获取所有经过浏览器计算过的样式

 //->所有经过浏览器计算过的样式;只要当前的元素标签可以在页面中呈现出来,那么它的所有的样式都是经过浏览器计算过的(渲染过的) -> 哪怕有些样式没有写,也可以获取到
    console.log(window.getComputedStyle(box,null)['height']) //200px
// ->window.getComputedStyle(当前要操作的元素对象,当前元素的伪类[一般不用伪类写null])
    // ->获取的结果是CSSStyleDeclaration这个类的一个实例:包含了当前元素的所有的样式属性和值
    // console.log(window.getComputedStyle(box,null)['height'])

3、ie6-8不兼容

    //在ie下,可以使用currentStyle来获取浏览器计算过的样式
    console.log(box.currentStyle.height)

小练习

● getCss:获取当前元素所有经过浏览器计算过的样式中的[attr]对应的值
 //curEle:[object]当前要操作的元素对象
    //attr:[String]要获取的样式属性的名称
    //1、使用try、catch来处理兼容
    //->前提:必须保证try中的代码在不兼容浏览器中执行的时候报错,这样才可以用catch捕获到异常信息,进行其他的处理
    function getCss(curEle,attr){
        let val = null;
        try{
            val = window.getComputedStyle(curEle,null)[attr]
        } catch(e) {
            val = curEle.currentStyle[attr]
        }
        return val
    }
    //2、判断当前浏览器中是否存在这个属性或者方法,存在就是兼容,不存在就是不兼容
    function getCss(curEle,attr){
        let val = null;
        if("getComputedStyle" in window){ //如果进来了代表兼容
            val = window.getComputedStyle(curEle,null)[attr]
        }else{
            val = curEle.currentStyle[attr]
        }
        return val
    }
    function getCss(curEle,attr){
            let val = null;
            if(winodw.getComputedStyle){ //如果进来了代表兼容
                val = window.getComputedStyle(curEle,null)[attr]
            }else{
                val = curEle.currentStyle[attr]
            }
            return val
    }
    
    //3、通过检测浏览器版本和类型来处理兼容
    window.navigator.userAgent

    //4、升级getCss
    //第一次升级,把单位去掉
    function getCss(curEle,attr){
        let val = null;
        let reg = null;
        if("getComputedStyle" in window){ //如果进来了代表兼容
            val = window.getComputedStyle(curEle,null)[attr]
        }else{
            val = curEle.currentStyle[attr]
        }
        reg = /^(-?\d+(\.\d+)?)(px|pt|rem|rem|em)?$/i;
        return reg.test(val) ? parseFloat(val) : val;
     }

        console.log(getCss(box,'float'))
        console.log(getCss(box,'border'))

用getComputedStyle获得伪类的样式

  window.getComputedStyle(box,"before").content
  window.getComputedStyle(box,"after").height
	//第二个参数写上before或者after

offset系列用法:

1、parentNode:父亲节点 HTML结构层级关系中的上一级元素

2、offsetParent:父级参照物,在同一个平面中,最外层的元素是里面所有元素的父级参照物(和HTML层级结构没有必然的联系)

● 一般来说一个页面中所有元素的父级参照物都是body

document.body.offsetParent ->null

● 想要改变父级参照物需要通过position定位来进行改变:absolute、relative、fixed任意一个值都可以把父级参照物进行修改
 //position:absolute
 //position:relative
 //position:fixed
  ele.style.position = 'absolute' //ele是指元素

3、offsetTop/offsetLeft:当前元素(外边框)距离其父级参照物(内边框)的偏移距离

小练习

offset:等同于jQuery中的offset方法,实现获取页面中任意一个元素,距离body的偏移(包含左偏移和上偏移),不管当前元素的父级参照物是谁
  /*->offset:等同于jQuery中的offset方法,实现获取页面中任意一个元素,
	距离body的偏移(包含左偏移和上偏移),不管当前元素的父级参照物是谁*/
     //-> 获取的结果是一个对象{left:距离body的左偏移,top:距离body的上偏移}
    function offset(curEle){
        let totoleft = null;
        let totoTop = null;
        let par = curEle.offsetParent;
            //-> 首先把自己本身的进行累加
            totoleft += curEle.offsetLeft;
            totoTop += curEle.offsetTop;
            //->只要没找到Body,就把父级参照物的边框和偏移也进行累加

        while(par){
            //->累加父级参照物的边框
            totoleft += par.clientLeft;
            totoTop += par.clientTop;

            //->累加父级参照物本身的偏移
            totoleft += par.offsetLeft;
            totoTop += par.offsetTop;
            par = par.offsetParent;
        }
        return {left:totoleft,top:totoTop}
    }

    console.log(offset(box).left)

可读写属性扩展

1、 上面的JS盒子模型中:client系列/offset系列/scrollWidth/scrollHeight都是"只读"属性->只能通过属性获取值,不能通过属性修改元素的样式
2、scrollTop/scrollLeft:滚动条卷去的高度/宽度(这两个属性是唯一"可读写"属性)
 box.scrollTop = 0; //->直接回到了容器的顶部
    /* ->scrollTop的值是存在边界值(最大和最小值的),我们设置的值比最小值小或者比最大值大都没用,起到
    效果的依然是边界的值*/
    //[最小值是0]
    // box.scrollTop = -1000 // ->直接回到了容器的顶部,没有超出
    // console.log(box.scrollTop) // -> 0
    //[最大值 = 真实的高度 - 当前容器一屏幕的高度]
    let maxTop = box.scrollHeight - box.clientHeight
    console.log(maxTop)