博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【笔记】jQuery源码(宽度&高度)
阅读量:7174 次
发布时间:2019-06-29

本文共 5900 字,大约阅读时间需要 19 分钟。

前言

最近几天忙着找实习的事情,然后就没有更新啦>0<,然后今天要开始继续学习啦。

原生JavaScript里面有几个系列来获取元素的尺寸。

原生属性

偏移量系列

  • offsetWidth
  • offsetHeight
  • offsetLeft
  • offsetTop
  • offsetParent:距离元素最近的定位(relative、absolute)祖先元素,可递归上溯。

offsetWidth/offsetHeight = 元素内容 + padding + border。

客户区系列

  • clientWidth
  • clientHeight

用于描述元素的内尺寸:元素内容+两边内边距

滚动大小

  • scrollWidth
  • scrollHeight
  • scrollLeft
  • scrollTop

scrollWidth/scrollHeight:元素内容的总高度或宽度。

scrollTop/scrollLeft:元素滚动条位置。

在浏览器中的区别在于:
IE6、IE7认为scrollHeight是网页内容实际高度,可以小于clientHeight。FF、Chrome 认为scrollHeight是网页内容高度,不过最小值是clientHeight。
浏览器窗口的滚动条位置:window对象的 pageXoffset 和 pageYoffset , IE8及更早版本可以通过scrollLeft和scrollTop属性获得滚动条位置。

一些细节

document.documentElement与document.body

document.body是DOM中Document对象里的body节点。
document.documentElement是文档对象根节点(html)的引用。

IE 在怪异模型下document.documentElement无法正确取到clietHeight、scrollHeight等值,比如clietHeight=0。可以见IE的怪异模型并没有把html作为盒子模型的一部分。

$(window).width() 代表了当前浏览器可见区域的宽度

$(document).width() 则代表了整个文档的宽度,可以有滚动内容

1 元素的宽素可以是内联或者通过link定义,所以通过style是不可取的

2 元素在隐藏状态下是不能获取任何尺寸的 display:none
3 CSS3引入了box-sizing的设置

jQuery.css(elem, type, extra)/^(none|table(?!-c[ea]).+)/test(jQuery.css(elem, "display")) //

。jQuery就会对元素增加position: absolute; visibility: hidden;

function getStyles(elem) {    return elem.ownerDocument.defaultView.getComputedStyle(elem, null);};

这里defaultView在浏览器中返回的是Document的Window对象。

window.getComputedStyle("元素", "伪类")返回当前元素的所有样式。它只能获取样式,是只读的,并且它获得的是元素最终的样式,不仅仅是style属性里写的。
然后为什么用defaultView,其实是差不多的,可以看大佬的博客谈到的:
另外IE还有一个element.currentStyle,也是元素最终的样式。

//交换元素样式(获取到display为none的宽度)function swap(elem, options, callback, args) {    var ret, name,        old = {};            //遍历options的属性,付给传入元素,并且保存原来元素对应的属性    for (name in options) {        old[name] = elem.style[name];        elem.style[name] = options[name];    }        //下面的代码是相当于执行了getWidthOrHeight函数获取到了宽度    ret = callback.apply(elem, args || []);        //再复原元素    for (name in options) {        elem.style[name] = old[name];    }    return ret;};//获取当前样式function curCSS(elem,name) {    var computed = getStyles(elem);    var ret = computed.getPropertyValue(name) || computed[name];    return ret;}

getPropertyValue()在上面大佬的文章里也有提到过,就是获取属性值的。在IE中则使用getAttribute方法,但是它在拿style属性值的时候,前者可以不用驼峰式写法,后者则必须。

//获取宽高function getWidthOrHeight( elem, name, extra ) {            val = name === "width" ? elem.offsetWidth : elem.offsetHeight,        styles = getStyles( elem ),        //borderBox情况        isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";    // IE11全屏的时候在iframe里的元素会缩小100辈    // In IE 11 fullscreen elements inside of an iframe have    // 100x too small dimensions (gh-1764).    if ( document.msFullscreenElement && window.top !== window ) {        if ( elem.getClientRects().length ) {            val = Math.round( elem.getBoundingClientRect()[ name ] * 100 );        }    }    // 一些没有设置HTML属性的元素获取offsetWidth会返回undefined    if ( val <= 0 || val == null ) {        //获取元素样式的值        val = curCSS( elem, name, styles );        if ( val < 0 || val == null ) {            val = elem.style[ name ];        }        // 计算单位不是px,所以直接返回        if ( rnumnonpx.test( val ) ) {            return val;        }        valueIsBorderBox = isBorderBox &&            ( support.boxSizingReliable() || val === elem.style[ name ] );        // 以防出现""和"auto"值        val = parseFloat( val ) || 0;    }    return ( val +        augmentWidthOrHeight(            elem,            name,            extra || ( isBorderBox ? "border" : "content" ),            valueIsBorderBox,            styles        )    ) + "px";}

计算display为none的元素的宽度

var cssShow = {    display: "block",    position: "absolute",    visibility: "hidden"}$('#test2').click(function(){    var elem = div;    function width() {        if( /^(none|table(?!-c[ea]).+)/.test(curCSS(div, 'display'))  ){            return swap(elem, cssShow, function() {                return getWidthOrHeight(elem, 'width', 'content');            })        }    }    show('模拟jQuery.width的处理: '+ width())})

偏移算法

innerWidth、innerHeight

用于获得匹配集合中第一个元素的当前计算的内部宽高(包括padding,但不包括border),或 设置每一个匹配元素的内部宽高。

outerWidth、outerHeight

获取元素集合中第一个元素的当前计算宽高度值,包括padding,border和选择性的margin。

var cssExpand = ["Top", "Right", "Bottom", "Left"];/*** 额外处理高度/宽度* elem:目标元素* name:目标测量(width/height)* extra:包括的最外层内容* isBorderBox:是怪异模式盒子吗* styles:样式*/function augmentWidthOrHeight(elem, name, extra, isBorderBox, styles) {    var i = extra === (isBorderBox ? "border" : "content") ?    // 如果isBorderBox有值,则直接i=4,跳过下面的循环,就避免额外的步骤    4 :    // 否则初始化垂直水平的属性,如果是width,name就是1,否则就是0    name === "width" ? 1 : 0,    val = 0;    /*    * width:如果i=1,则循环只会加上right和left    * height:如果i=0,则循环只会加上top和bottom    */    for (; i < 4; i += 2) {        // 如果extra是margin就把margin都加上        if (extra === "margin") {            val += jQuery.css(elem, extra + cssExpand[i], true, styles);        }        // 如果是怪异模型        if (isBorderBox) {            //width包含了padding,所以如果exrta是content的话要去除padding            if (extra === "content") {                val -= jQuery.css(elem, "padding" + cssExpand[i], true, styles);            }            //如果extra不是margin的话,还要减去2边的宽度            if (extra !== "margin") {                val -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);            }        } else {            //因为不是怪异模型,所以直接再加上padding            val += jQuery.css(elem, "padding" + cssExpand[i], true, styles);            // extra不可能是padding了(上面加过了),所以再加上border            if (extra !== "padding") {                val += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);            }        }    }    return val;}

首先获取基本的offsetWidth和offsetHeight,要得到下面几个值,再加上这个函数的结果即可。

innerWidth:augmentWidthOrHeight(elem, 'width', "padding", true, styles)
innerHeight:augmentWidthOrHeight(elem, 'height', "padding", true, styles)
outerWidth:augmentWidthOrHeight(elem, 'width', "border", true, styles)
outerHeight:augmentWidthOrHeight(elem, 'height', "border", true, styles)

转载地址:http://awdzm.baihongyu.com/

你可能感兴趣的文章
取消Eclipse SVN的自动链接方式
查看>>
Lamda表达式,map和集合操作
查看>>
discuz的php7版本号
查看>>
Hibernate中的session和load延迟载入矛盾问题,怎样解决?
查看>>
MACD判断定背离,底背离
查看>>
UML建模学习1:UML统一建模语言简单介绍
查看>>
【书籍推荐】
查看>>
Bing Advanced Search Tricks You Should Know
查看>>
EF6 DbModelBuilder
查看>>
裴波那切数的探讨
查看>>
linux比较文件夹的差异命令
查看>>
CentOS6下基于Nginx搭建mp4/flv流媒体服务器
查看>>
区块链技术--密码学
查看>>
Java垃圾回收机制(转)
查看>>
复杂查询
查看>>
【python】正则表达式
查看>>
使用Mongoose类库实现简单的增删改查
查看>>
OHDSI——数据标准化
查看>>
实现php的startsWith和endsWith
查看>>
Windows Community Toolkit 4.0 - DataGrid - Part01
查看>>