jq源码 | 2020-12-24 11:42:19 238次 0次
样式操作涉及到元素的尺寸大小、类名、表现等。
CSS操作
jQuery.fn.extend( { css: function( name, value ) { return access( this, function( elem, name, value ) { ... // 这里第二部分有说明 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; // If a hook was provided get the computed value from there if ( hooks && "get" in hooks ) { val = hooks.get( elem, true, extra ); } ... // 支持数组的形式设置 if ( Array.isArray( name ) ) { ... jQuery.css } // 主要看 style 和 css 方法,这两个方法挂载在 jq 本身静态方法 return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); }, name, value, arguments.length > 1 ); } } );
jQuery.css 静态方法:
//属性值的获取操作 css: function( elem, name, extra, styles ) { // 转为驼峰 origName = cssCamelCase( name ), ... // 如果需要比如 -transform 自动补全前缀 webkit moz ms // 如果是 transform 不带前面的 - 则不处理 name = finalPropName( origName ); ... // 这个方法通过 getComputedStyle // 不支持这个的则使用 elem.ownerDocument.defaultView // 获取当前属性值 if ( val === undefined ) { val = curCSS( elem, name, styles ); } ... return val; }
jQuery.style 静态方法:
这里的逻辑和上面的css操作基本一致, 真正的设置样式由这个方法触发 ... if ( isCustomProp ) { style.setProperty( name, value ); } else { style[ name ] = value; }
尺寸操作
window:
window.screenTop 浏览器顶部距离屏幕顶部的距离(全屏时为0)
window.screen.height 分辨率
window.innerWidth 窗口宽度(打开控制台时剩余的宽度)=== document.documentElement.clientWidth
注:document.documentElement.offsetWidth(不包括 margin ),clientWidth则包含
元素:
定义入口:
dimensions.js 中: jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { // Margin is only for outerHeight, outerWidth jQuery.fn[ funcName ] = function( margin, value ) { ... return access( this, function( elem, type, value ) { var doc; if ( isWindow( elem ) ) { // $( window ) return funcName.indexOf( "outer" ) === 0 ? elem[ "inner" + name ] : elem.document.documentElement[ "client" + name ]; } // $(document) if ( elem.nodeType === 9 ) { doc = elem.documentElement; // 不指定 <!DOCTYPE HTML> 时 // document.body.XXX 取到的值不正确 // document.documentElement.XX 取值正确 return Math.max( elem.body[ "scroll" + name ], doc[ "scroll" + name ], elem.body[ "offset" + name ], doc[ "offset" + name ], doc[ "client" + name ] ); } // 对于 dom 则还是通过 css style 来操作 return value === undefined ? // get jQuery.css( elem, type, extra ) : // set jQuery.style( elem, type, value, extra ); }, type, chainable ? margin : undefined, chainable ); }; } ); } );
其中对于 width height 等属性的操作,jq 中有一个 hooks 的设计,用来专门处理尺寸的样式:
jQuery.each( [ "height", "width" ], function( _i, dimension ) { jQuery.cssHooks[ dimension ] = { get: function( elem, computed, extra ) { if ( computed ) { ... // 取值操作 getWidthOrHeight( elem, dimension, extra ); } }, set: function( elem, value, extra ) { ... // 根据 box-sizing 模型修正数据 subtract = extra ? boxModelAdjustment(...) : 0; ... // 赋值 $('.test').height('+=400')这种写法也会修正处理 return setPositiveNumber( elem, value, subtract ); } }; } );
通过 getWidthOrHeight 方法发现 jq 并没有通过 js 提供这些 api 来获取节点的样式,而是通过 getComputedStyle 返回的对象 CSSStyleDeclaration 类型对象来取值,并且取值后再次执行 boxModelAdjustment 修正盒模型的值 :
EleObj.ownerDocument.defaultView.getComputedStyle(EleObj).getPropertyValue('height')
setPositiveNumber 设置值操作直接返回值本身。
对于偏移的一些计算可以通过 getBoundingClientRect 方法实现。
属性操作
class 操作
// 这个方法很简单,后续可能会改为 classList jQuery.fn.extend( { addClass: function( value ) { ... while ( ( clazz = classes[ j++ ] ) ) { // 避免重复值 新旧class值拼一块 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } } ... // 判断新旧值 不一致再赋值 if ( curValue !== finalValue ) { elem.setAttribute( "class", finalValue ); } } } } return this; }, removeClass: function( value ) { ... while ( ( clazz = classes[ j++ ] ) ) { // 和添加的区别是这里替换已存在的class为空 while ( cur.indexOf( " " + clazz + " " ) > -1 ) { cur = cur.replace( " " + clazz + " ", " " ); } } ... } } } return this; }, ... } );
prop & attr
prop 是指 dom 对象上自带的一些属性,属于标准中预置的
attr 是指后面可以自己添加自定义的一些特性
prop:elem[ name ] = value 直接赋值给当前dom对象 attr: elem.setAttribute( name, value + "" ); 通过 setAttribute 添加特性
0人赞