Skip to content

Latest commit

 

History

History
219 lines (157 loc) · 10.3 KB

样式操作.md

File metadata and controls

219 lines (157 loc) · 10.3 KB

样式操作

jQuery 样式操作由下面五个子模块组成:

  • 内联样式
  • 计算样式
  • 类样式
  • 坐标
  • 尺寸

它主要解决如下的问题:

  • 浏览器兼容。
  • 驼峰、连字符样式名的自动转换。
  • 简化样式读写。

总体结构

工具属性和方法

jQuery.cssNumber

表示不用自动添加 px 单位的 css 属性。

cssNumber: {
	"columnCount": true,
	"fillOpacity": true,
	"fontWeight": true,
	"lineHeight": true,
	"opacity": true,
	"orphans": true,
	"widows": true,
	"zIndex": true,
	"zoom": true
}

normal 对应的数字值。

cssNormalTransform = {
	letterSpacing: 0,
	fontWeight: 400
}
getStyles(elem)

获取所有的计算样式。

  1. 如果浏览器支持 window.getComputedStyle 那么通过 window.getComputedStyle(elem,null) 来获取指定元素的计算样式。第二个参数可以指定伪元素,IE 11 才支持,所以尽量别用。
  2. IE 6-8 不支持 window.getComputedStyle,但是支持 currentStyle 属性,因此对 IE 6-8 使用 elem.currentStyle 来获取指定元素的计算样式。
curCSS(elem,name,_computed)

获取指定名称的计算样式。同样是如果浏览器支持 window.getComputedStyle 那么利用 window.getComputedStyle 来获取计算样式,否则通过 currentStyle 属性。不过还是有一些 bug 的。

  • window.getComputedStyle:Chrome < 17 and Safari 5.0 使用计算结果替代使用的值来计算 margin-right。(这个应该是在 cssHooks 中修复的)Safari 5.1.7 (最新)返回百分比但是我们需要像素值。(此处修复的是非像素值)
  • currentStyle:IE 通过 currentStyle 获取到的是 cascade style也就是 em、% 等,所以需要把他转化为特定的像素值!

内联样式和计算样式

jquery.style(elem,name,value,extra)

负责读取和设置内联样式。设置内联样式时,会计算相对值、添加单位、解决样式不兼容。读取和设置内联样式时会优先调用修正对象上的 get/set 方法。

  1. 过滤文本节点和注释节点。
  2. 获取驼峰样式名,并且进行修正,如果有需要还会加上对应的浏览器前缀。
  3. 根据 name 或驼峰名获取修正对象 hooks
  4. 如果传入了 value
  5. 如果类型是字符串,并且匹配 +=/-= 则表示是相对值,那么将其转为数值并加上原来的值,设置类型为数字。
  6. 如果是数字类型,并且根据 jQuery.cssNumber 需要自动加上 px 单位,那么加上。
  7. 在 IE 9、10 下要清空 background-* 内联样式时,为出问题,因为设置为 "inherit"
  8. 如果存在 hooks.set,那么优先调用。
  9. 否则直接在 elem.style 上进行赋值,记得捕获异常,因为在 IE 下,如果传入了非法值会报错。
  10. 否则。
  11. 如果存在 hooks.get,那么优先调用。
  12. 否则直接在 elem.style 上进行取值。
jQuery.css(elem,name,extra,styles)

负责读取计算样式。读取内联样式时会优先调用修正对象上的 get 方法。

  1. 获取驼峰样式名,并且进行修正,如果有需要还会加上对应的浏览器前缀。
  2. 根据 name 或驼峰名获取修正对象 hooks
  3. 如果存在 hooks.get,那么优先调用。
  4. 如果没有 hooks.gethooks.get 得到的是 undefined,则调用 curCSS( elem, name, styles ); 获取计算值。
  5. 如果得到的是 normal,将其通过 cssNormalTransform 转换为数字值。
  6. 如果传入的 extratrue,那么强制转为数字,如果成功则返回,不成功还是返回原来的值。
jQuery.fn.css(name,value)

四种调用模式:

  • .css(propertyName):获取匹配元素集合第一个元素的计算样式。
  • .css(propertyName, value):在每个匹配元素上设置一个内联样式。
  • .css(propertyName, function(index, value)):在每个匹配元素上设置一个内联样式,属性值由函数返回。

执行过程:

  1. 如果 name 是数组,那么会调用 jQuery.css 取得所有的计算值,返回。
  2. 否则如果 valueundefined,则通过 jQuery.css 进行取值。
  3. 否则用 jQuery.style 设置内联样式值。
jQuery.cssHooks
  • opacity
  • 支持 opacity 的情况:读取计算样式时,使用 curCSS,如果得到空字符串,那么返回 1。
  • 不支持 opacity 的情况:从 elem.style.filterelem.currentStyle.filter 中读取,并除以 100。未设置 filter,那么如果是计算值,则返回 1,内联样式返回空字符串。set 方法也是通过 filter 来设置。
  • marginRight:早先的 WebKit window.getComputedStyle 方法无法正确获取 margin-right 计算值。修正方法是通过临时设置 display:inline-block 来得到正确的值。
  • heightwidth:尺寸一节详细介绍。
  • topleft:早先的 WebKit window.getComputedStyle 方法返回位置相关的值是百分比,需要用 jQuery( elem ).position() 求出像素值。
  • marginpaddingborderWidth:动画里用到,后面写。

坐标

jQuery.fn.offset(options)

为所有匹配元素设置 options 指定的坐标,或者读取第一个匹配元素的坐标。

  1. 如果传入了 options,那么调用 jQuery.offset.setOffset 进行设置。
  2. 过滤不在文档中的元素。
  3. 如果存在 getBoundingClientRect 方法,那么利用它来获取窗口坐标。(IE 4 就支持了,只是不返回 widthheight,不支持的是 BlackBerry 5、iOS 3,对此的策略原来是手动计算,现在的策略是直接返回 {left:0,top:0}
  4. 获取 window
  5. 相对文档的上坐标 = 距窗口的上坐标 + 垂直方向偏移 - 文档上边框厚度。(左坐标类似)

垂直偏移优先从 window.pageYOffset,其次是 documentElement.scrollTop

jQuery.offset.setOffset(elem,options,i)

设置单个元素的文档坐标。

  1. 如果定位是 static,则设置为 relative,使 lefttop 生效。
  2. 获取当前文档坐标,计算样式等。
  3. 如果当前元素的 positionabsolutefixed 且计算样式为 auto,那么通过 .position() 得到相对于 offsetParent 的坐标。
  4. 如果 options 是函数则求值。
  5. 计算最终的内联样式。最终内联样式 = 目标文档坐标 - 当前文档坐标 + 计算样式。
  6. 如果 options 中有 using 指定了回调,那么交给它来设置。否则利用 .css 方法设置内联样式。
jQuery.fn.position()

获取第一个匹配元素相对于 offsetParent 的坐标。

  1. 如果没有匹配元素则返回 null
  2. 对于 fixed 定位的元素 offset = elem.getBoundingClientRect()
  3. 否则。
  4. 获取 offsetParent 元素。
  5. 获取当前元素的文档坐标。
  6. 获取 offsetParent 的文档坐标。
  7. 对于 offsetParenthtml 的情况,要加上 border
  8. 当前元素的文档坐标减去 offsetParent 的文档坐标,对于 WebKit offsetLeftmarginLeft 会自动相等,导致不正确。所以还要减去对应方向的 margin。对于 jQuery 来说这个 elemwidth+padding+border+margin 看成了一个整体,所以最终得到的 top 是 elem 这个整体距离被定为祖辈元素顶部内边的距离。这与 offsetTopoffsetLeft 不一致。
jQuery.fn.offsetParent()
  1. .map 遍历。
  2. 通过 offsetParent() 属性得到最近定位祖先,没找到则返回 html
  3. 如果找到的为 static 定位,那么继续找,直到找到 html
  4. .map 会将得到的元素包装为 jQuery 对象。
jQuery.fn.scrollLeft([val])jQuery.fn.scrollRight([val])

读取匹配元素中每个元素的滚动条偏移或设置每个元素的滚动条偏移。

  1. 如果没有传入 val,则读取值,window 上通过 pageXOffset/pageYOffset 读取,其他的通过 scrollLeft/scrollRight 读取。
  2. 否则,设置值。window 通过 scrollTo 方法来滚动到指定位置,其它的直接通过赋值 scrollLeft/scrollRight 完成设置。

尺寸

getWidthOrHeight(elem,name,extra)

  1. 变量初始化。
  2. valueIsBorderBoxborderBox 的值。
  3. valoffsetWidthoffsetHeight
  4. styles:所有计算样式。
  5. isBorderBox:判断是否为 borderBox
  6. 一些非 HTML 元素会返回 null/undefined
  7. curCSS 得到计算样式。
  8. 否则读取内联样式。
  9. 如果得到的不是 px 结尾,那么直接返回。
  10. 检测盒模型是否可靠。
  11. augmentWidthOrHeight() 根据 extras 进行选择性地加减 paddingmarginborder

augmentWidthOrHeight(elem,name,extra,isBorderBox,styles)

  1. extramargin,则加上左右或上下的 margin
  2. 如果是 borderBox
  3. extra === "content":则要减掉左右或上下的 padding
  4. extra !== "margin":则要减掉左右或上下的 border
  5. 否则。
  6. 加上左右或上下的 padding
  7. extra !== "padding":则要加上左右或上下的 border

更加形象的解释就是:

  • 如果 extraundefined,那么就是 content
  • 如果 extrapadding,那么就是 content+padding
  • 如果 extraborder,那么就是 content+padding+border
  • 如果 extramargin,那么就是 content+padding+border+margin
jQuery.fn.width([value])jQuery.fn.height([value])
  1. 对于 window:返回 elem.document.documentElement[ "client" + name ];
  2. 对于 document:返回 body、documentElement 的 scroll-*offset-*、documentElement 的 client-* 中的大者。
  3. 根据是否传入 value,来调用 jQuery.stylejQuery.css 获取或设置值。
  4. cssHooks 中会根据 extra 的值,对 get/set 方法进行修正。
  5. 返回的是 content
jQuery.fn.innerWidth()jQuery.fn.innerHeight()

jQuery.fn.width()jQuery.fn.height()。返回的是 content+padding

jQuery.fn.outerWidth(margin)jQuery.fn.outerHeight(margin)

jQuery.fn.width()jQuery.fn.height(),只是传入的 extra 不同,这个方法还可以传入可选的 margin 来表示是否在尺寸中加入 margin。返回的是 content+padding+border+[margin]