前言
依旧是来自慕课网jQuery源码解析,自己的整理。目前看来所有的文章其实还是有点乱,后面完了我会好好再整理整理/(ㄒoㄒ)/~~。
定义HTML样式的方法
- <link/>外部引入
- <style/>嵌入样式
- style属性
给一个HTML元素设置css属性,如:
var head= document.getElementById("head");
head.style.width = "20px";
head.style.height = "10px";
head.style.display = "block";
存在的问题:
1.每次只能设置一个,而且每设置一次浏览器要绘制一次(高级的浏览器可能会合并style的次数)
2.style接口只能针对
行类样式,link引入的样式无法获取。3.样式属性名的兼容问题,比如驼峰,保留字float。
Tip:style的内部属性命名采用的驼峰形式,比如 background-image(backgroundImage),比较特殊的就是float,因为是保留字就换成了cssFloat,IE:styleFloat。对于width、hight这些处理都最好要有一个量度单位。
解决方法:
1.合并cssText。
var head= document.getElementById("head");
head.style.cssText="width:20px;height:10px;display:bolck";
cssText很快捷且所有浏览器都支持。批量操作样式时,cssText只需一次 reflow,提高了页面渲染性能。
2.利用文档碎片。
缺点是样式被整体覆盖,处理的时候要先获取需要保留的样式再拼接。
参考文章:https://www.w3cmm.com/dom/ins…
//使用CSSRules去获得样式(非内联的也可以获得)
//添加新的CSS
function addCSSRule(key, value) {
//获取最后一个样式表
var css = document.styleSheets[document.styleSheets.length - 1];
//如果浏览器支持InsertRule方法则使用这个插入,否则是IE,则使用addRule
css.cssRules ?
(css.insertRule(key + "{" + value + "}", css.cssRules.length)) :
(css.addRule(key, value));
}
//移除CSS
function removeCSSRule(key) {
for (var i = 0; i < document.styleSheets.length; i++) {
var css = document.styleSheets[i];
css.cssRules ?
(function() {
for (var j = 0; j < css.cssRules.length; j++) {
if (css.cssRules[j].selectorText == key) {
css.deleteRule(j);
}
}
})() :
(css.removeRule(key));
}
}
//调用示例
addCSSRule("#a","color:red;background:yellow")
removeCSSRule("#a")
钩子机制
$.cssHooks 对象提供了一种方法通过定义函数来获取和设置特定的CSS值的方法
jQuery提供一个 API 来调用用户自定义的函数,用于扩展,以便获取和设置特定属性值。在 .attr,.prop(),.val()和 .css()的操作中都会引入钩子,钩子都有相似的结构。
var someHook = {
get: function(elem) {
// obtain and return a value
return "something";
},
set: function(elem, value) {
// do something with value
}
}
钩子用来做啥?
做css3浏览器兼容的时候,需要特定的前缀,比如:
Webkit 内核浏览器:-webkit-border-radius
Firefox 内核浏览器:-moz-border-radius
你可以只传一个border-radius,然后CSS hook可以自动帮你把这些前缀都加上。
我们平做浏览器兼容,一般都是:
if(webkit){
........................
}else if(firefox){
...........................
}else if(...)
如果我们换成hook的话:
$.cssHooks.borderRadius = {
get: function( elem, computed, extra ) {
return $.css( elem, borderRadius );
},
set: function( elem, value) {
elem.style[ borderRadius ] = value;
}
};
样式操作接口
jQuery操作样式的接口jQuery.fn.css
与jQuery.css
jQuery.style( elem, name, value ) //设置值
jQuery.css( elem, name ) //获取值
以下主要集中讲解关于获取值的过程:
- 用户调用css()传值是比较随便,所以先检测是不是驼峰写法:
origName = jQuery.camelCase( name );
- 另外要处理如float这样的特殊值,以及浏览器前缀的问题:
name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));
- 如果元素是display为none无法获得定位,width、height、margin获取问题也需要被处理,这里就要用到CSS钩子:
每一个特殊的情况都有对应的处理,比如width:
cssHooks = {
width:{
get:function(){},
set:function(){}
}
}
用户在获取width的时候,可能会有以下几种情况:
- 元素为display:none,获取不到尺寸
- jQuery有width、innerWidth、outerWidth等各种不同取值方式
- 元素被设置css3的盒子模型
- 其余元素采用getComputedStyle获取对应的值。
模拟实现
//获取最终属性
var getStyles = function(elem) {
return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
};
//返回一个css属性映射到一个浏览器商前缀的属性
function vendorPropName(style, name) {
// 不用处理前缀的属性直接返回
if (name in style) {
return name;
}
//检查前缀,capName把第一个字母大写
var capName = name[0].toUpperCase() + name.slice(1),
origName = name,
i = cssPrefixes.length;
//加上CSS前缀
while (i--) {
name = cssPrefixes[i] + capName;
if (name in style) {
return name;
}
}
return origName;
}
//获取当前样式
function curCSS(elem, name, computed) {
var width, minWidth, maxWidth, ret,
style = elem.style;
computed = computed || getStyles(elem);
if (computed) {
ret = computed.getPropertyValue(name) || computed[name];
}
return ret;
}
//jQuery.css获取css值
function css(elem, name, extra, styles) {
var val, num, hooks,
//转成驼峰写法(如:background-color -> backgroundColor)
origName = jQuery.camelCase(name);
//如果是特殊属性float转成cssFloat,以及带有浏览器前缀处理
name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));
//处理获取width、height等尺寸属性的情况
hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
if (hooks && "get" in hooks) {
val = hooks.get(elem, true, extra);
}
//通过computed接口直接获取样式
if (val === undefined) {
val = curCSS(elem, name, styles);
}
return val;
}
另外在jQuery原型上的css方法,也就是我们直接调用的那个css()是这样的:
//name:设置的属性名,value:设置的属性值
css: function( name, value ) {
return access( this, function( elem, name, value ) {
var styles, len,
map = {},
i = 0;
if ( jQuery.isArray( name ) ) {
styles = getStyles( elem );
len = name.length;
for ( ; i < len; i++ ) {
map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
}
return map;
}
//如果value是undefined说明是获取值,否则是设置值
return value !== undefined ?
jQuery.style( elem, name, value ) :
jQuery.css( elem, name );
}, name, value, arguments.length > 1 );
}